VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/sysfs.cpp@ 60427

最後變更 在這個檔案從60427是 60427,由 vboxsync 提交於 9 年 前

Runtime/linux/sysfs.cpp: Fixes for the tstRTSystemQueryDmi testcase, don't seek to the end of the file to get the file size because that is often bogus for sysfs entries (the indicated file size is much bigger than what can be read really). Fix an inconsistency in RTLinuxSysFsReadStrFileV() which would return a VERR_BUFFER_OVERFLOW error if the given buffer matches the string size if there is a newline end the end which is filtered out anyway. Small adjustment for RTLinuxSysFsWriteStr() to also write zero terminators if the string size is not given

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 20.2 KB
 
1/* $Id: sysfs.cpp 60427 2016-04-11 14:30:32Z vboxsync $ */
2/** @file
3 * IPRT - Linux sysfs access.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_SYSTEM
32#include <iprt/assert.h>
33#include <iprt/dir.h>
34#include <iprt/err.h>
35#include <iprt/file.h>
36#include <iprt/fs.h>
37#include <iprt/param.h>
38#include <iprt/path.h>
39#include <iprt/string.h>
40#include <iprt/symlink.h>
41
42#include <iprt/linux/sysfs.h>
43
44#include <unistd.h>
45#include <stdio.h>
46#include <sys/sysctl.h>
47#include <sys/stat.h>
48#include <sys/fcntl.h>
49#include <errno.h>
50
51
52
53/**
54 * Constructs the path of a sysfs file from the format parameters passed,
55 * prepending a prefix if the path is relative.
56 *
57 * @returns IPRT status code.
58 * @param pszPrefix The prefix to prepend if the path is relative. Must end
59 * in '/'.
60 * @param pszBuf Where to write the path. Must be at least
61 * sizeof(@a pszPrefix) characters long
62 * @param cchBuf The size of the buffer pointed to by @a pszBuf.
63 * @param pszFormat The name format, either absolute or relative to the
64 * prefix specified by @a pszPrefix.
65 * @param va The format args.
66 */
67static int rtLinuxConstructPathV(char *pszBuf, size_t cchBuf,
68 const char *pszPrefix,
69 const char *pszFormat, va_list va)
70{
71 size_t cchPrefix = strlen(pszPrefix);
72 AssertReturn(pszPrefix[cchPrefix - 1] == '/', VERR_INVALID_PARAMETER);
73 AssertReturn(cchBuf > cchPrefix + 1, VERR_INVALID_PARAMETER);
74
75 /** @todo While RTStrPrintfV prevents overflows, it doesn't make it easy to
76 * check for truncations. RTPath should provide some formatters and
77 * joiners which can take over this rather common task that is
78 * performed here. */
79 size_t cch = RTStrPrintfV(pszBuf, cchBuf, pszFormat, va);
80 if (*pszBuf != '/')
81 {
82 AssertReturn(cchBuf >= cch + cchPrefix + 1, VERR_BUFFER_OVERFLOW);
83 memmove(pszBuf + cchPrefix, pszBuf, cch + 1);
84 memcpy(pszBuf, pszPrefix, cchPrefix);
85 cch += cchPrefix;
86 }
87 return VINF_SUCCESS;
88}
89
90
91/**
92 * Constructs the path of a sysfs file from the format parameters passed,
93 * prepending a prefix if the path is relative.
94 *
95 * @returns IPRT status code.
96 * @param pszPrefix The prefix to prepend if the path is relative. Must end
97 * in '/'.
98 * @param pszBuf Where to write the path. Must be at least
99 * sizeof(@a pszPrefix) characters long
100 * @param cchBuf The size of the buffer pointed to by @a pszBuf.
101 * @param pszFormat The name format, either absolute or relative to "/sys/".
102 * @param ... The format args.
103 */
104DECLINLINE(int) rtLinuxConstructPath(char *pszBuf, size_t cchBuf,
105 const char *pszPrefix,
106 const char *pszFormat, ...)
107{
108 va_list va;
109 va_start(va, pszFormat);
110 int rc = rtLinuxConstructPathV(pszBuf, cchBuf, pszPrefix, pszFormat, va);
111 va_end(va);
112 return rc;
113}
114
115
116/**
117 * Constructs the path of a sysfs file from the format parameters passed,
118 * prepending "/sys/" if the path is relative.
119 *
120 * @returns IPRT status code.
121 * @param pszBuf Where to write the path. Must be at least
122 * sizeof("/sys/") characters long
123 * @param cchBuf The size of the buffer pointed to by @a pszBuf.
124 * @param pszFormat The name format, either absolute or relative to "/sys/".
125 * @param va The format args.
126 */
127DECLINLINE(int) rtLinuxSysFsConstructPath(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va)
128{
129 return rtLinuxConstructPathV(pszBuf, cchBuf, "/sys/", pszFormat, va);
130}
131
132
133RTDECL(int) RTLinuxSysFsExistsExV(const char *pszFormat, va_list va)
134{
135 int iSavedErrno = errno;
136
137 /*
138 * Construct the filename and call stat.
139 */
140 char szFilename[RTPATH_MAX];
141 int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
142 if (RT_SUCCESS(rc))
143 {
144 struct stat st;
145 int rcStat = stat(szFilename, &st);
146 if (rcStat != 0)
147 rc = RTErrConvertFromErrno(errno);
148 }
149
150 errno = iSavedErrno;
151 return rc;
152}
153
154
155RTDECL(bool) RTLinuxSysFsExistsV(const char *pszFormat, va_list va)
156{
157 return RT_SUCCESS(RTLinuxSysFsExistsExV(pszFormat, va));
158}
159
160
161RTDECL(int) RTLinuxSysFsExistsEx(const char *pszFormat, ...)
162{
163 va_list va;
164 va_start(va, pszFormat);
165 int rc = RTLinuxSysFsExistsExV(pszFormat, va);
166 va_end(va);
167 return rc;
168}
169
170
171RTDECL(bool) RTLinuxSysFsExists(const char *pszFormat, ...)
172{
173 va_list va;
174 va_start(va, pszFormat);
175 bool fRet = RTLinuxSysFsExistsV(pszFormat, va);
176 va_end(va);
177 return fRet;
178}
179
180
181RTDECL(int) RTLinuxSysFsOpenV(PRTFILE phFile, const char *pszFormat, va_list va)
182{
183 /*
184 * Construct the filename and call open.
185 */
186 char szFilename[RTPATH_MAX];
187 int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
188 if (RT_SUCCESS(rc))
189 rc = RTFileOpen(phFile, szFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
190 return rc;
191}
192
193
194RTDECL(int) RTLinuxSysFsOpenExV(PRTFILE phFile, uint64_t fOpen, const char *pszFormat, va_list va)
195{
196 /*
197 * Construct the filename and call open.
198 */
199 char szFilename[RTPATH_MAX];
200 int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
201 if (RT_SUCCESS(rc))
202 rc = RTFileOpen(phFile, szFilename, fOpen);
203 return rc;
204}
205
206
207RTDECL(int) RTLinuxSysFsOpen(PRTFILE phFile, const char *pszFormat, ...)
208{
209 va_list va;
210 va_start(va, pszFormat);
211 int rc = RTLinuxSysFsOpenV(phFile, pszFormat, va);
212 va_end(va);
213 return rc;
214}
215
216
217RTDECL(int) RTLinuxSysFsOpenEx(PRTFILE phFile, uint64_t fOpen, const char *pszFormat, ...)
218{
219 va_list va;
220 va_start(va, pszFormat);
221 int rc = RTLinuxSysFsOpenExV(phFile, fOpen, pszFormat, va);
222 va_end(va);
223 return rc;
224}
225
226
227RTDECL(int) RTLinuxSysFsReadStr(RTFILE hFile, char *pszBuf, size_t cchBuf, size_t *pcchRead)
228{
229 Assert(cchBuf > 1);
230 size_t cchRead = 0;
231 int rc = RTFileRead(hFile, pszBuf, cchBuf - 1, &cchRead);
232 pszBuf[RT_SUCCESS(rc) ? cchRead : 0] = '\0';
233 if ( RT_SUCCESS(rc)
234 && pcchRead)
235 *pcchRead = cchRead;
236 if (RT_SUCCESS(rc))
237 {
238 /* Check for EOF */
239 uint64_t offCur = 0;
240 uint8_t bRead;
241 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_CURRENT, &offCur);
242 if (RT_SUCCESS(rc))
243 {
244 int rc2 = RTFileRead(hFile, &bRead, 1, NULL);
245 if (RT_SUCCESS(rc2))
246 {
247 rc = VERR_BUFFER_OVERFLOW;
248
249 rc2 = RTFileSeek(hFile, offCur, RTFILE_SEEK_BEGIN, NULL);
250 if (RT_FAILURE(rc2))
251 rc = rc2;
252 }
253 else if (rc2 != VERR_EOF)
254 rc = rc2;
255 }
256 }
257 return rc;
258}
259
260
261RTDECL(int) RTLinuxSysFsWriteStr(RTFILE hFile, const char *pszBuf, size_t cchBuf, size_t *pcchWritten)
262{
263 if (!cchBuf)
264 cchBuf = strlen(pszBuf) + 1; /* Include the terminator */
265 return RTFileWrite(hFile, pszBuf, cchBuf, pcchWritten);
266}
267
268
269RTDECL(int) RTLinuxSysFsReadFile(RTFILE hFile, void *pvBuf, size_t cbBuf, size_t *pcbRead)
270{
271 int rc;
272 size_t cbRead = 0;
273
274 rc = RTFileRead(hFile, pvBuf, cbBuf, &cbRead);
275 if (RT_SUCCESS(rc))
276 {
277 if (pcbRead)
278 *pcbRead = cbRead;
279 if (cbRead < cbBuf)
280 rc = VINF_SUCCESS;
281 else
282 {
283 /* Check for EOF */
284 uint64_t offCur = 0;
285 uint8_t bRead;
286 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_CURRENT, &offCur);
287 if (RT_SUCCESS(rc))
288 {
289 int rc2 = RTFileRead(hFile, &bRead, 1, NULL);
290 if (RT_SUCCESS(rc2))
291 {
292 rc = VERR_BUFFER_OVERFLOW;
293
294 rc2 = RTFileSeek(hFile, offCur, RTFILE_SEEK_BEGIN, NULL);
295 if (RT_FAILURE(rc2))
296 rc = rc2;
297 }
298 else if (rc2 != VERR_EOF)
299 rc = rc2;
300 }
301 }
302 }
303
304 return rc;
305}
306
307
308RTDECL(int) RTLinuxSysFsWriteFile(RTFILE hFile, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
309{
310 return RTFileWrite(hFile, pvBuf, cbBuf, pcbWritten);
311}
312
313
314RTDECL(int) RTLinuxSysFsReadIntFileV(unsigned uBase, int64_t *pi64, const char *pszFormat, va_list va)
315{
316 RTFILE hFile;
317
318 AssertPtrReturn(pi64, VERR_INVALID_POINTER);
319
320 int rc = RTLinuxSysFsOpenV(&hFile, pszFormat, va);
321 if (RT_SUCCESS(rc))
322 {
323 char szNum[128];
324 size_t cchNum;
325 rc = RTLinuxSysFsReadStr(hFile, szNum, sizeof(szNum), &cchNum);
326 if (RT_SUCCESS(rc))
327 {
328 if (cchNum > 0)
329 {
330 int64_t i64Ret = -1;
331 rc = RTStrToInt64Ex(szNum, NULL, uBase, &i64Ret);
332 if (RT_SUCCESS(rc))
333 *pi64 = i64Ret;
334 }
335 else
336 rc = VERR_INVALID_PARAMETER;
337 }
338
339 RTFileClose(hFile);
340 }
341
342 return rc;
343}
344
345
346RTDECL(int) RTLinuxSysFsReadIntFile(unsigned uBase, int64_t *pi64, const char *pszFormat, ...)
347{
348 va_list va;
349 va_start(va, pszFormat);
350 int rc = RTLinuxSysFsReadIntFileV(uBase, pi64, pszFormat, va);
351 va_end(va);
352 return rc;
353}
354
355
356RTDECL(int) RTLinuxSysFsWriteU8FileV(unsigned uBase, uint8_t u8, const char *pszFormat, va_list va)
357{
358 return RTLinuxSysFsWriteU64FileV(uBase, u8, pszFormat, va);
359}
360
361
362RTDECL(int) RTLinuxSysFsWriteU8File(unsigned uBase, uint8_t u8, const char *pszFormat, ...)
363{
364 va_list va;
365 va_start(va, pszFormat);
366 int rc = RTLinuxSysFsWriteU64FileV(uBase, u8, pszFormat, va);
367 va_end(va);
368 return rc;
369}
370
371
372RTDECL(int) RTLinuxSysFsWriteU16FileV(unsigned uBase, uint16_t u16, const char *pszFormat, va_list va)
373{
374 return RTLinuxSysFsWriteU64FileV(uBase, u16, pszFormat, va);
375}
376
377
378RTDECL(int) RTLinuxSysFsWriteU16File(unsigned uBase, uint16_t u16, const char *pszFormat, ...)
379{
380 va_list va;
381 va_start(va, pszFormat);
382 int rc = RTLinuxSysFsWriteU64FileV(uBase, u16, pszFormat, va);
383 va_end(va);
384 return rc;
385}
386
387
388RTDECL(int) RTLinuxSysFsWriteU32FileV(unsigned uBase, uint32_t u32, const char *pszFormat, va_list va)
389{
390 return RTLinuxSysFsWriteU64FileV(uBase, u32, pszFormat, va);
391}
392
393
394RTDECL(int) RTLinuxSysFsWriteU32File(unsigned uBase, uint32_t u32, const char *pszFormat, ...)
395{
396 va_list va;
397 va_start(va, pszFormat);
398 int rc = RTLinuxSysFsWriteU64FileV(uBase, u32, pszFormat, va);
399 va_end(va);
400 return rc;
401}
402
403
404RTDECL(int) RTLinuxSysFsWriteU64FileV(unsigned uBase, uint64_t u64, const char *pszFormat, va_list va)
405{
406 RTFILE hFile;
407
408 const char *pszFmt = NULL;
409 switch (uBase)
410 {
411 case 8:
412 pszFmt = "%#llo";
413 break;
414 case 10:
415 pszFmt = "%llu";
416 break;
417 case 16:
418 pszFmt = "%#llx";
419 break;
420 default:
421 return VERR_INVALID_PARAMETER;
422 }
423
424 int rc = RTLinuxSysFsOpenExV(&hFile, RTFILE_O_OPEN | RTFILE_O_WRITE | RTFILE_O_DENY_NONE, pszFormat, va);
425 if (RT_SUCCESS(rc))
426 {
427 char szNum[128];
428 size_t cchNum = RTStrPrintf(szNum, sizeof(szNum), pszFmt, u64);
429 if (cchNum > 0)
430 {
431 size_t cbWritten = 0;
432 rc = RTLinuxSysFsWriteStr(hFile, &szNum[0], cchNum, &cbWritten);
433 if ( RT_SUCCESS(rc)
434 && cbWritten != cchNum)
435 rc = VERR_BUFFER_OVERFLOW;
436 }
437 else
438 rc = VERR_INVALID_PARAMETER;
439
440 RTFileClose(hFile);
441 }
442
443 return rc;
444}
445
446
447RTDECL(int) RTLinuxSysFsWriteU64File(unsigned uBase, uint32_t u64, const char *pszFormat, ...)
448{
449 va_list va;
450 va_start(va, pszFormat);
451 int rc = RTLinuxSysFsWriteU64FileV(uBase, u64, pszFormat, va);
452 va_end(va);
453 return rc;
454}
455
456
457RTDECL(int) RTLinuxSysFsReadDevNumFileV(dev_t *pDevNum, const char *pszFormat, va_list va)
458{
459 RTFILE hFile;
460
461 AssertPtrReturn(pDevNum, VERR_INVALID_POINTER);
462
463 int rc = RTLinuxSysFsOpenV(&hFile, pszFormat, va);
464 if (RT_SUCCESS(rc))
465 {
466 size_t cchNum = 0;
467 char szNum[128];
468 rc = RTLinuxSysFsReadStr(hFile, szNum, sizeof(szNum), &cchNum);
469 if (RT_SUCCESS(rc))
470 {
471 if (cchNum > 0)
472 {
473 uint32_t u32Maj = 0;
474 uint32_t u32Min = 0;
475 char *pszNext = NULL;
476 rc = RTStrToUInt32Ex(szNum, &pszNext, 10, &u32Maj);
477 if (RT_FAILURE(rc) || (rc != VWRN_TRAILING_CHARS) || (*pszNext != ':'))
478 rc = VERR_INVALID_PARAMETER;
479 else
480 {
481 rc = RTStrToUInt32Ex(pszNext + 1, NULL, 10, &u32Min);
482 if ( rc != VINF_SUCCESS
483 && rc != VWRN_TRAILING_CHARS
484 && rc != VWRN_TRAILING_SPACES)
485 rc = VERR_INVALID_PARAMETER;
486 else
487 *pDevNum = makedev(u32Maj, u32Min);
488 }
489 }
490 else
491 rc = VERR_INVALID_PARAMETER;
492 }
493
494 RTFileClose(hFile);
495 }
496
497 return rc;
498}
499
500
501RTDECL(int) RTLinuxSysFsReadDevNumFile(dev_t *pDevNum, const char *pszFormat, ...)
502{
503 va_list va;
504 va_start(va, pszFormat);
505 int rc = RTLinuxSysFsReadDevNumFileV(pDevNum, pszFormat, va);
506 va_end(va);
507 return rc;
508}
509
510
511RTDECL(int) RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, size_t *pcchRead, const char *pszFormat, va_list va)
512{
513 RTFILE hFile;
514
515 AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
516
517 int rc = RTLinuxSysFsOpenV(&hFile, pszFormat, va);
518 if (RT_SUCCESS(rc))
519 {
520 size_t cchRead = 0;
521 rc = RTLinuxSysFsReadStr(hFile, pszBuf, cchBuf, &cchRead);
522 if ( RT_SUCCESS(rc)
523 && cchRead > 0)
524 {
525 char *pchNewLine = (char *)memchr(pszBuf, '\n', cchRead);
526 if (pchNewLine)
527 {
528 *pchNewLine = '\0';
529 cchRead--;
530 }
531 }
532 else if ( rc == VERR_BUFFER_OVERFLOW
533 && cchRead > 0)
534 {
535 /*
536 * Check if the last character would have been a newline we filter out
537 * anyway and revert the buffer overflow.
538 */
539 char achBuf[2];
540 size_t cchPeek = 0;
541 uint64_t offCur = 0;
542
543 int rc2 = RTFileSeek(hFile, 0, RTFILE_SEEK_CURRENT, &offCur);
544 if (RT_SUCCESS(rc2))
545 {
546 rc2 = RTLinuxSysFsReadStr(hFile, &achBuf[0], sizeof(achBuf), &cchPeek);
547 if ( RT_SUCCESS(rc2)
548 && cchPeek > 0)
549 rc2 = RTFileSeek(hFile, offCur, RTFILE_SEEK_BEGIN, NULL);
550 if ( RT_SUCCESS(rc2)
551 && cchPeek > 0
552 && achBuf[0] == '\n')
553 rc = VINF_SUCCESS;
554 }
555 }
556
557 RTFileClose(hFile);
558
559 if (pcchRead)
560 *pcchRead = cchRead;
561 }
562 return rc;
563}
564
565
566RTDECL(int) RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, size_t *pcchRead, const char *pszFormat, ...)
567{
568 va_list va;
569 va_start(va, pszFormat);
570 int rc = RTLinuxSysFsReadStrFileV(pszBuf, cchBuf, pcchRead, pszFormat, va);
571 va_end(va);
572 return rc;
573}
574
575
576RTDECL(int) RTLinuxSysFsWriteStrFileV(const char *pszBuf, size_t cchBuf, size_t *pcchWritten, const char *pszFormat, va_list va)
577{
578 RTFILE hFile;
579
580 AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
581
582 int rc = RTLinuxSysFsOpenExV(&hFile, RTFILE_O_OPEN | RTFILE_O_WRITE | RTFILE_O_DENY_NONE, pszFormat, va);
583 if (RT_SUCCESS(rc))
584 {
585 rc = RTLinuxSysFsWriteStr(hFile, pszBuf, cchBuf, pcchWritten);
586 RTFileClose(hFile);
587 }
588 return rc;
589}
590
591
592RTDECL(int) RTLinuxSysFsWriteStrFile(const char *pszBuf, size_t cchBuf, size_t *pcchWritten, const char *pszFormat, ...)
593{
594 va_list va;
595 va_start(va, pszFormat);
596 int rc = RTLinuxSysFsWriteStrFileV(pszBuf, cchBuf, pcchWritten, pszFormat, va);
597 va_end(va);
598 return rc;
599}
600
601RTDECL(int) RTLinuxSysFsGetLinkDestV(char *pszBuf, size_t cchBuf, size_t *pchBuf, const char *pszFormat, va_list va)
602{
603 AssertReturn(cchBuf >= 2, VERR_INVALID_PARAMETER);
604
605 /*
606 * Construct the filename and read the link.
607 */
608 char szFilename[RTPATH_MAX];
609 int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
610 if (RT_SUCCESS(rc))
611 {
612 char szLink[RTPATH_MAX];
613 rc = RTSymlinkRead(szFilename, szLink, sizeof(szLink), 0);
614 if (RT_SUCCESS(rc))
615 {
616 /*
617 * Extract the file name component and copy it into the return buffer.
618 */
619 size_t cchName;
620 const char *pszName = RTPathFilename(szLink);
621 if (pszName)
622 {
623 cchName = strlen(pszName);
624 if (cchName < cchBuf)
625 memcpy(pszBuf, pszName, cchName + 1);
626 else
627 rc = VERR_BUFFER_OVERFLOW;
628 }
629 else
630 {
631 *pszBuf = '\0';
632 cchName = 0;
633 }
634
635 if (pchBuf)
636 *pchBuf = cchName;
637 }
638 }
639
640 return rc;
641}
642
643
644RTDECL(int) RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, size_t *pchBuf, const char *pszFormat, ...)
645{
646 va_list va;
647 va_start(va, pszFormat);
648 int rc = RTLinuxSysFsGetLinkDestV(pszBuf, cchBuf, pchBuf, pszFormat, va);
649 va_end(va);
650 return rc;
651}
652
653
654RTDECL(int) RTLinuxCheckDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf,
655 size_t cchBuf, const char *pszPattern,
656 va_list va)
657{
658 AssertReturn(cchBuf >= 2, VERR_INVALID_PARAMETER);
659 AssertReturn( fMode == RTFS_TYPE_DEV_CHAR
660 || fMode == RTFS_TYPE_DEV_BLOCK,
661 VERR_INVALID_PARAMETER);
662 AssertPtrReturn(pszPattern, VERR_INVALID_PARAMETER);
663
664 /*
665 * Construct the filename and read the link.
666 */
667 char szFilename[RTPATH_MAX];
668 int rc = rtLinuxConstructPathV(szFilename, sizeof(szFilename), "/dev/",
669 pszPattern, va);
670 if (RT_SUCCESS(rc))
671 {
672 RTFSOBJINFO Info;
673 rc = RTPathQueryInfo(szFilename, &Info, RTFSOBJATTRADD_UNIX);
674 if ( rc == VERR_PATH_NOT_FOUND
675 || ( RT_SUCCESS(rc)
676 && ( Info.Attr.u.Unix.Device != DevNum
677 || (Info.Attr.fMode & RTFS_TYPE_MASK) != fMode)))
678 rc = VERR_FILE_NOT_FOUND;
679
680 if (RT_SUCCESS(rc))
681 {
682 size_t cchPath = strlen(szFilename);
683 if (cchPath < cchBuf)
684 memcpy(pszBuf, szFilename, cchPath + 1);
685 else
686 rc = VERR_BUFFER_OVERFLOW;
687 }
688 }
689
690 return rc;
691}
692
693
694RTDECL(int) RTLinuxCheckDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf,
695 size_t cchBuf, const char *pszPattern,
696 ...)
697{
698 va_list va;
699 va_start(va, pszPattern);
700 int rc = RTLinuxCheckDevicePathV(DevNum, fMode, pszBuf, cchBuf,
701 pszPattern, va);
702 va_end(va);
703 return rc;
704}
705
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette