VirtualBox

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

Last change on this file since 89669 was 86579, checked in by vboxsync, 4 years ago

IPRT/sysfs.h: Added RTLinuxConstructPath and RTLinuxConstructPathV. bugref:9224

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

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