VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use