VirtualBox

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

Last change on this file since 98278 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

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