VirtualBox

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

Last change on this file was 108482, checked in by vboxsync, 4 weeks ago

Some minor compile fixes when targetting Linux with clang, bugref:10874

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

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