VirtualBox

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

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

IPRT: Linux: #warning The <sys/sysctl.h> header is deprecated and will be removed, bugref:9597

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 20.1 KB
Line 
1/* $Id: sysfs.cpp 81582 2019-10-30 10:42:48Z 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/stat.h>
47#include <sys/fcntl.h>
48#include <sys/sysmacros.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); /* not mandatory */
230
231 int rc;
232 size_t cchRead;
233 rc = RTFileRead(hFile, pszBuf, cchBuf, &cchRead);
234 if (RT_SUCCESS(rc))
235 {
236 /*
237 * ASSUME that if we've read less than we asked for, we've reached the
238 * end of the file. Otherwise, we've been given a buffer too small for
239 * the entire remainder of the file.
240 */
241 if (cchRead < cchBuf)
242 pszBuf[cchRead] = '\0';
243 else if (cchBuf)
244 {
245 rc = RTFileSeek(hFile, -1, RTFILE_SEEK_CURRENT, NULL);
246 if (RT_SUCCESS(rc))
247 rc = VERR_BUFFER_OVERFLOW;
248 cchRead = cchBuf - 1;
249 pszBuf[cchRead] = '\0';
250 }
251 else
252 rc = VERR_BUFFER_OVERFLOW;
253 }
254 else
255 {
256 if (cchBuf > 0)
257 *pszBuf = '\0';
258 cchRead = 0;
259 }
260
261 if (pcchRead)
262 *pcchRead = cchRead;
263 return rc;
264}
265
266
267RTDECL(int) RTLinuxSysFsWriteStr(RTFILE hFile, const char *pszBuf, size_t cchBuf, size_t *pcchWritten)
268{
269 if (!cchBuf)
270 cchBuf = strlen(pszBuf) + 1; /* Include the terminator */
271 return RTFileWrite(hFile, pszBuf, cchBuf, pcchWritten);
272}
273
274
275RTDECL(int) RTLinuxSysFsReadFile(RTFILE hFile, void *pvBuf, size_t cbBuf, size_t *pcbRead)
276{
277 int rc;
278 size_t cbRead = 0;
279
280 rc = RTFileRead(hFile, pvBuf, cbBuf, &cbRead);
281 if (RT_SUCCESS(rc))
282 {
283 if (pcbRead)
284 *pcbRead = cbRead;
285 if (cbRead < cbBuf)
286 rc = VINF_SUCCESS;
287 else
288 {
289 /* Check for EOF */
290 uint64_t offCur = 0;
291 uint8_t bRead;
292 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_CURRENT, &offCur);
293 if (RT_SUCCESS(rc))
294 {
295 int rc2 = RTFileRead(hFile, &bRead, 1, NULL);
296 if (RT_SUCCESS(rc2))
297 {
298 rc = VERR_BUFFER_OVERFLOW;
299
300 rc2 = RTFileSeek(hFile, offCur, RTFILE_SEEK_BEGIN, NULL);
301 if (RT_FAILURE(rc2))
302 rc = rc2;
303 }
304 else if (rc2 != VERR_EOF)
305 rc = rc2;
306 }
307 }
308 }
309
310 return rc;
311}
312
313
314RTDECL(int) RTLinuxSysFsWriteFile(RTFILE hFile, void *pvBuf, size_t cbBuf, size_t *pcbWritten)
315{
316 return RTFileWrite(hFile, pvBuf, cbBuf, pcbWritten);
317}
318
319
320RTDECL(int) RTLinuxSysFsReadIntFileV(unsigned uBase, int64_t *pi64, const char *pszFormat, va_list va)
321{
322 RTFILE hFile;
323
324 AssertPtrReturn(pi64, VERR_INVALID_POINTER);
325
326 int rc = RTLinuxSysFsOpenV(&hFile, pszFormat, va);
327 if (RT_SUCCESS(rc))
328 {
329 char szNum[128];
330 size_t cchNum;
331 rc = RTLinuxSysFsReadStr(hFile, szNum, sizeof(szNum), &cchNum);
332 if (RT_SUCCESS(rc))
333 {
334 if (cchNum > 0)
335 {
336 int64_t i64Ret = -1;
337 rc = RTStrToInt64Ex(szNum, NULL, uBase, &i64Ret);
338 if (RT_SUCCESS(rc))
339 *pi64 = i64Ret;
340 }
341 else
342 rc = VERR_INVALID_PARAMETER;
343 }
344
345 RTFileClose(hFile);
346 }
347
348 return rc;
349}
350
351
352RTDECL(int) RTLinuxSysFsReadIntFile(unsigned uBase, int64_t *pi64, const char *pszFormat, ...)
353{
354 va_list va;
355 va_start(va, pszFormat);
356 int rc = RTLinuxSysFsReadIntFileV(uBase, pi64, pszFormat, va);
357 va_end(va);
358 return rc;
359}
360
361
362RTDECL(int) RTLinuxSysFsWriteU8FileV(unsigned uBase, uint8_t u8, const char *pszFormat, va_list va)
363{
364 return RTLinuxSysFsWriteU64FileV(uBase, u8, pszFormat, va);
365}
366
367
368RTDECL(int) RTLinuxSysFsWriteU8File(unsigned uBase, uint8_t u8, const char *pszFormat, ...)
369{
370 va_list va;
371 va_start(va, pszFormat);
372 int rc = RTLinuxSysFsWriteU64FileV(uBase, u8, pszFormat, va);
373 va_end(va);
374 return rc;
375}
376
377
378RTDECL(int) RTLinuxSysFsWriteU16FileV(unsigned uBase, uint16_t u16, const char *pszFormat, va_list va)
379{
380 return RTLinuxSysFsWriteU64FileV(uBase, u16, pszFormat, va);
381}
382
383
384RTDECL(int) RTLinuxSysFsWriteU16File(unsigned uBase, uint16_t u16, const char *pszFormat, ...)
385{
386 va_list va;
387 va_start(va, pszFormat);
388 int rc = RTLinuxSysFsWriteU64FileV(uBase, u16, pszFormat, va);
389 va_end(va);
390 return rc;
391}
392
393
394RTDECL(int) RTLinuxSysFsWriteU32FileV(unsigned uBase, uint32_t u32, const char *pszFormat, va_list va)
395{
396 return RTLinuxSysFsWriteU64FileV(uBase, u32, pszFormat, va);
397}
398
399
400RTDECL(int) RTLinuxSysFsWriteU32File(unsigned uBase, uint32_t u32, const char *pszFormat, ...)
401{
402 va_list va;
403 va_start(va, pszFormat);
404 int rc = RTLinuxSysFsWriteU64FileV(uBase, u32, pszFormat, va);
405 va_end(va);
406 return rc;
407}
408
409
410RTDECL(int) RTLinuxSysFsWriteU64FileV(unsigned uBase, uint64_t u64, const char *pszFormat, va_list va)
411{
412 RTFILE hFile;
413
414 const char *pszFmt = NULL;
415 switch (uBase)
416 {
417 case 8:
418 pszFmt = "%#llo";
419 break;
420 case 10:
421 pszFmt = "%llu";
422 break;
423 case 16:
424 pszFmt = "%#llx";
425 break;
426 default:
427 return VERR_INVALID_PARAMETER;
428 }
429
430 int rc = RTLinuxSysFsOpenExV(&hFile, RTFILE_O_OPEN | RTFILE_O_WRITE | RTFILE_O_DENY_NONE, pszFormat, va);
431 if (RT_SUCCESS(rc))
432 {
433 char szNum[128];
434 size_t cchNum = RTStrPrintf(szNum, sizeof(szNum), pszFmt, u64);
435 if (cchNum > 0)
436 {
437 size_t cbWritten = 0;
438 rc = RTLinuxSysFsWriteStr(hFile, &szNum[0], cchNum, &cbWritten);
439 if ( RT_SUCCESS(rc)
440 && cbWritten != cchNum)
441 rc = VERR_BUFFER_OVERFLOW;
442 }
443 else
444 rc = VERR_INVALID_PARAMETER;
445
446 RTFileClose(hFile);
447 }
448
449 return rc;
450}
451
452
453RTDECL(int) RTLinuxSysFsWriteU64File(unsigned uBase, uint32_t u64, const char *pszFormat, ...)
454{
455 va_list va;
456 va_start(va, pszFormat);
457 int rc = RTLinuxSysFsWriteU64FileV(uBase, u64, pszFormat, va);
458 va_end(va);
459 return rc;
460}
461
462
463RTDECL(int) RTLinuxSysFsReadDevNumFileV(dev_t *pDevNum, const char *pszFormat, va_list va)
464{
465 RTFILE hFile;
466
467 AssertPtrReturn(pDevNum, VERR_INVALID_POINTER);
468
469 int rc = RTLinuxSysFsOpenV(&hFile, pszFormat, va);
470 if (RT_SUCCESS(rc))
471 {
472 size_t cchNum = 0;
473 char szNum[128];
474 rc = RTLinuxSysFsReadStr(hFile, szNum, sizeof(szNum), &cchNum);
475 if (RT_SUCCESS(rc))
476 {
477 if (cchNum > 0)
478 {
479 uint32_t u32Maj = 0;
480 uint32_t u32Min = 0;
481 char *pszNext = NULL;
482 rc = RTStrToUInt32Ex(szNum, &pszNext, 10, &u32Maj);
483 if (RT_FAILURE(rc) || (rc != VWRN_TRAILING_CHARS) || (*pszNext != ':'))
484 rc = VERR_INVALID_PARAMETER;
485 else
486 {
487 rc = RTStrToUInt32Ex(pszNext + 1, NULL, 10, &u32Min);
488 if ( rc != VINF_SUCCESS
489 && rc != VWRN_TRAILING_CHARS
490 && rc != VWRN_TRAILING_SPACES)
491 rc = VERR_INVALID_PARAMETER;
492 else
493 *pDevNum = makedev(u32Maj, u32Min);
494 }
495 }
496 else
497 rc = VERR_INVALID_PARAMETER;
498 }
499
500 RTFileClose(hFile);
501 }
502
503 return rc;
504}
505
506
507RTDECL(int) RTLinuxSysFsReadDevNumFile(dev_t *pDevNum, const char *pszFormat, ...)
508{
509 va_list va;
510 va_start(va, pszFormat);
511 int rc = RTLinuxSysFsReadDevNumFileV(pDevNum, pszFormat, va);
512 va_end(va);
513 return rc;
514}
515
516
517RTDECL(int) RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, size_t *pcchRead, const char *pszFormat, va_list va)
518{
519 RTFILE hFile;
520
521 AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
522
523 int rc = RTLinuxSysFsOpenV(&hFile, pszFormat, va);
524 if (RT_SUCCESS(rc))
525 {
526 /*
527 * Note! We cannot use RTLinuxSysFsReadStr here as it has different
528 * semantics wrt to newline characters. It is not known why
529 * the semantics has to differ... Michael, any clues?
530 */
531 size_t cchRead;
532 rc = RTFileRead(hFile, pszBuf, cchBuf, &cchRead);
533 if (RT_SUCCESS(rc))
534 {
535 char *pchNewLine = (char *)memchr(pszBuf, '\n', cchRead);
536 if (pchNewLine)
537 {
538 *pchNewLine = '\0';
539 cchRead = pchNewLine - pszBuf;
540 }
541 else if (cchRead < cchBuf)
542 pszBuf[cchRead] = '\0';
543 else
544 {
545 if (cchBuf)
546 {
547 cchRead = cchBuf - 1;
548 pszBuf[cchRead] = '\0';
549 }
550 else
551 cchRead = 0;
552 rc = VERR_BUFFER_OVERFLOW;
553 }
554 }
555 else
556 cchRead = 0;
557
558 RTFileClose(hFile);
559
560 if (pcchRead)
561 *pcchRead = cchRead;
562 }
563 else
564 {
565 if (cchBuf)
566 *pszBuf = '\0';
567 if (pcchRead)
568 *pcchRead = 0;
569 }
570 return rc;
571}
572
573
574RTDECL(int) RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, size_t *pcchRead, const char *pszFormat, ...)
575{
576 va_list va;
577 va_start(va, pszFormat);
578 int rc = RTLinuxSysFsReadStrFileV(pszBuf, cchBuf, pcchRead, pszFormat, va);
579 va_end(va);
580 return rc;
581}
582
583
584RTDECL(int) RTLinuxSysFsWriteStrFileV(const char *pszBuf, size_t cchBuf, size_t *pcchWritten, const char *pszFormat, va_list va)
585{
586 RTFILE hFile;
587
588 AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
589
590 int rc = RTLinuxSysFsOpenExV(&hFile, RTFILE_O_OPEN | RTFILE_O_WRITE | RTFILE_O_DENY_NONE, pszFormat, va);
591 if (RT_SUCCESS(rc))
592 {
593 rc = RTLinuxSysFsWriteStr(hFile, pszBuf, cchBuf, pcchWritten);
594 RTFileClose(hFile);
595 }
596 return rc;
597}
598
599
600RTDECL(int) RTLinuxSysFsWriteStrFile(const char *pszBuf, size_t cchBuf, size_t *pcchWritten, const char *pszFormat, ...)
601{
602 va_list va;
603 va_start(va, pszFormat);
604 int rc = RTLinuxSysFsWriteStrFileV(pszBuf, cchBuf, pcchWritten, pszFormat, va);
605 va_end(va);
606 return rc;
607}
608
609RTDECL(int) RTLinuxSysFsGetLinkDestV(char *pszBuf, size_t cchBuf, size_t *pchBuf, const char *pszFormat, va_list va)
610{
611 AssertReturn(cchBuf >= 2, VERR_INVALID_PARAMETER);
612
613 /*
614 * Construct the filename and read the link.
615 */
616 char szFilename[RTPATH_MAX];
617 int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
618 if (RT_SUCCESS(rc))
619 {
620 char szLink[RTPATH_MAX];
621 rc = RTSymlinkRead(szFilename, szLink, sizeof(szLink), 0);
622 if (RT_SUCCESS(rc))
623 {
624 /*
625 * Extract the file name component and copy it into the return buffer.
626 */
627 size_t cchName;
628 const char *pszName = RTPathFilename(szLink);
629 if (pszName)
630 {
631 cchName = strlen(pszName);
632 if (cchName < cchBuf)
633 memcpy(pszBuf, pszName, cchName + 1);
634 else
635 rc = VERR_BUFFER_OVERFLOW;
636 }
637 else
638 {
639 *pszBuf = '\0';
640 cchName = 0;
641 }
642
643 if (pchBuf)
644 *pchBuf = cchName;
645 }
646 }
647
648 return rc;
649}
650
651
652RTDECL(int) RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, size_t *pchBuf, const char *pszFormat, ...)
653{
654 va_list va;
655 va_start(va, pszFormat);
656 int rc = RTLinuxSysFsGetLinkDestV(pszBuf, cchBuf, pchBuf, pszFormat, va);
657 va_end(va);
658 return rc;
659}
660
661
662RTDECL(int) RTLinuxCheckDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf,
663 size_t cchBuf, const char *pszPattern,
664 va_list va)
665{
666 AssertReturn(cchBuf >= 2, VERR_INVALID_PARAMETER);
667 AssertReturn( fMode == RTFS_TYPE_DEV_CHAR
668 || fMode == RTFS_TYPE_DEV_BLOCK,
669 VERR_INVALID_PARAMETER);
670 AssertPtrReturn(pszPattern, VERR_INVALID_PARAMETER);
671
672 /*
673 * Construct the filename and read the link.
674 */
675 char szFilename[RTPATH_MAX];
676 int rc = rtLinuxConstructPathV(szFilename, sizeof(szFilename), "/dev/",
677 pszPattern, va);
678 if (RT_SUCCESS(rc))
679 {
680 RTFSOBJINFO Info;
681 rc = RTPathQueryInfo(szFilename, &Info, RTFSOBJATTRADD_UNIX);
682 if ( rc == VERR_PATH_NOT_FOUND
683 || ( RT_SUCCESS(rc)
684 && ( Info.Attr.u.Unix.Device != DevNum
685 || (Info.Attr.fMode & RTFS_TYPE_MASK) != fMode)))
686 rc = VERR_FILE_NOT_FOUND;
687
688 if (RT_SUCCESS(rc))
689 {
690 size_t cchPath = strlen(szFilename);
691 if (cchPath < cchBuf)
692 memcpy(pszBuf, szFilename, cchPath + 1);
693 else
694 rc = VERR_BUFFER_OVERFLOW;
695 }
696 }
697
698 return rc;
699}
700
701
702RTDECL(int) RTLinuxCheckDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf,
703 size_t cchBuf, const char *pszPattern,
704 ...)
705{
706 va_list va;
707 va_start(va, pszPattern);
708 int rc = RTLinuxCheckDevicePathV(DevNum, fMode, pszBuf, cchBuf,
709 pszPattern, va);
710 va_end(va);
711 return rc;
712}
713
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use