Changeset 15644 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Dec 18, 2008 11:16:58 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/sysfs.cpp
r15399 r15644 34 34 *******************************************************************************/ 35 35 #define LOG_GROUP RTLOGGROUP_SYSTEM 36 #include <iprt/linux/sysfs.h> 37 #include <iprt/assert.h> 38 #include <iprt/param.h> 39 #include <iprt/path.h> 40 #include <iprt/string.h> 41 36 42 #include <unistd.h> 37 43 #include <stdio.h> … … 41 47 #include <errno.h> 42 48 43 #include <iprt/linux/sysfs.h>44 #include <iprt/assert.h>45 #include <iprt/param.h>46 #include <iprt/string.h>47 48 49 49 50 /** … … 51 52 * prepending "/sys/" if the path is relative. 52 53 * 53 * @returns The number of characters written, or -1 and errno on failure. 54 * @returns The number of characters returned, or -1 and errno set to ERANGE on 55 * failure. 56 * 54 57 * @param pszBuf Where to write the path. Must be at least 55 58 * sizeof("/sys/") characters long 56 * @param cchBuf The size of the buffer pointed to by @a pszBuf 59 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 57 60 * @param pszFormat The name format, either absolute or relative to "/sys/". 58 61 * @param va The format args. 59 62 */ 60 static ssize_t rtLinuxSysFsConstructPath(char *pszBuf, size_t cchBuf, 61 const char *pszFormat, va_list va) 62 { 63 static ssize_t rtLinuxSysFsConstructPath(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va) 64 { 65 static const char s_szPrefix[] = "/sys/"; 66 AssertReturnStmt(cchBuf > sizeof(s_szPrefix), errno = ERANGE, -1); 67 68 size_t cch = RTStrPrintfV(pszBuf, cchBuf, pszFormat, va); 69 if (*pszBuf != '/') 70 { 71 AssertReturnStmt(cchBuf >= cch + sizeof(s_szPrefix), errno = ERANGE, -1); 72 memmove(pszBuf + sizeof(s_szPrefix) - 1, pszBuf, cch + 1); 73 memcpy(pszBuf, s_szPrefix, sizeof(s_szPrefix) - 1); 74 cch += sizeof(s_szPrefix) - 1; 75 } 76 return cch; 77 } 78 79 80 RTDECL(bool) RTLinuxSysFsExistsV(const char *pszFormat, va_list va) 81 { 82 int iSavedErrno = errno; 83 84 /* 85 * Construct the filename and call stat. 86 */ 87 bool fRet = false; 63 88 char szFilename[RTPATH_MAX]; 64 const char szPrefix[] = "/sys/"; 65 if (cchBuf < sizeof(szPrefix)) 66 AssertFailedReturnStmt(errno = EINVAL, -1); 67 size_t cch = RTStrPrintfV(szFilename, sizeof(szFilename), pszFormat, va); 68 if (szFilename[0] == '/') 69 *pszBuf = '\0'; 70 else 71 strcpy(pszBuf, szPrefix); 72 strncat(pszBuf, szFilename, cchBuf); 73 return strlen(pszBuf); 74 } 75 76 /** 77 * Checks if a sysfs file (or directory, device, symlink, whatever) exists. 78 * 79 * @returns true / false, errno is preserved. 80 * @param pszFormat The name format, either absolute or relative to "/sys/". 81 * @param va The format args. 82 */ 83 bool RTLinuxSysFsExistsV(const char *pszFormat, va_list va) 84 { 85 int iSavedErrno = errno; 86 87 /* 88 * Construct the filename and call stat. 89 */ 90 char szFilename[RTPATH_MAX]; 91 bool fRet = false; 92 ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), 93 pszFormat, va); 94 if (rc > 0 && static_cast<size_t>(rc) < sizeof(szFilename)) 89 ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va); 90 if (rc != -1) 95 91 { 96 92 struct stat st; … … 102 98 } 103 99 104 /** 105 * Checks if a sysfs file (or directory, device, symlink, whatever) exists. 106 * 107 * @returns true / false, errno is preserved. 108 * @param pszFormat The name format, either absolute or relative to "/sys/". 109 * @param ... The format args. 110 */ 111 bool RTLinuxSysFsExists(const char *pszFormat, ...) 100 101 RTDECL(bool) RTLinuxSysFsExists(const char *pszFormat, ...) 112 102 { 113 103 va_list va; … … 119 109 120 110 121 /** 122 * Opens a sysfs file. 123 * 124 * @returns The file descriptor. -1 and errno on failure. 125 * @param pszFormat The name format, either absolute or relative to "/sys/". 126 * @param va The format args. 127 */ 128 int RTLinuxSysFsOpenV(const char *pszFormat, va_list va) 111 RTDECL(int) RTLinuxSysFsOpenV(const char *pszFormat, va_list va) 129 112 { 130 113 /* … … 132 115 */ 133 116 char szFilename[RTPATH_MAX]; 134 ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), 135 pszFormat, va); 136 if (rc > 0 && static_cast<size_t>(rc) < sizeof(szFilename)) 117 ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va); 118 if (rc != -1) 137 119 rc = open(szFilename, O_RDONLY, 0); 138 120 return rc; … … 140 122 141 123 142 /** 143 * Opens a sysfs file. 144 * 145 * @returns The file descriptor. -1 and errno on failure. 146 * @param pszFormat The name format, either absolute or relative to "/sys/". 147 * @param ... The format args. 148 */ 149 int RTLinuxSysFsOpen(const char *pszFormat, ...) 124 RTDECL(int) RTLinuxSysFsOpen(const char *pszFormat, ...) 150 125 { 151 126 va_list va; … … 157 132 158 133 159 /** 160 * Closes a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV. 161 * 162 * @param fd 163 */ 164 void RTLinuxSysFsClose(int fd) 134 RTDECL(void) RTLinuxSysFsClose(int fd) 165 135 { 166 136 int iSavedErrno = errno; … … 170 140 171 141 172 /** 173 * Reads a string from a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV. 174 * 175 * @returns The number of bytes read. -1 and errno on failure. 176 * @param fd The file descriptor returned by RTLinuxSysFsOpen or RTLinuxSysFsOpenV. 177 * @param pszBuf Where to store the string. 178 * @param cchBuf The size of the buffer. Must be at least 2 bytes. 179 */ 180 ssize_t RTLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf) 142 RTDECL(ssize_t) RTLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf) 181 143 { 182 144 Assert(cchBuf > 1); … … 187 149 188 150 189 /** 190 * Reads a number from a sysfs file. 191 * 192 * @returns 64-bit signed value on success, -1 and errno on failure. 193 * @param uBase The number base, 0 for autodetect. 194 * @param pszFormat The filename format, either absolute or relative to "/sys/". 195 * @param va Format args. 196 */ 197 int64_t RTLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va) 151 RTDECL(int64_t) RTLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va) 198 152 { 199 153 int fd = RTLinuxSysFsOpenV(pszFormat, va); … … 221 175 222 176 223 /** 224 * Reads a number from a sysfs file. 225 * 226 * @returns 64-bit signed value on success, -1 and errno on failure. 227 * @param uBase The number base, 0 for autodetect. 228 * @param pszFormat The filename format, either absolute or relative to "/sys/". 229 * @param ... Format args. 230 */ 231 int64_t RTLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...) 177 RTDECL(int64_t) RTLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...) 232 178 { 233 179 va_list va; … … 239 185 240 186 241 /** 242 * Reads a string from a sysfs file. If the file contains a newline, we only 243 * return the text up until there. 244 * 245 * @returns number of characters read on success, -1 and errno on failure. 246 * @param pszBuf Where to store the path element. Must be at least two 247 * characters, but a longer buffer would be advisable. 248 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 249 * @param pszFormat The filename format, either absolute or relative to "/sys/". 250 * @param va Format args. 251 */ 252 ssize_t RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va) 187 RTDECL(ssize_t) RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va) 253 188 { 254 189 int fd = RTLinuxSysFsOpenV(pszFormat, va); … … 258 193 ssize_t cchRet = RTLinuxSysFsReadStr(fd, pszBuf, cchBuf); 259 194 RTLinuxSysFsClose(fd); 260 char *pchNewLine = NULL;261 195 if (cchRet > 0) 262 pchNewLine = reinterpret_cast<char *>(memchr(pszBuf, '\n', cchRet)); 263 if (pchNewLine != NULL) 264 *pchNewLine = '\0'; 196 { 197 char *pchNewLine = (char *)memchr(pszBuf, '\n', cchRet); 198 if (pchNewLine) 199 *pchNewLine = '\0'; 200 } 265 201 return cchRet; 266 202 } 267 203 268 204 269 /** 270 * Reads a string from a sysfs file. If the file contains a newline, we only 271 * return the text up until there. 272 * 273 * @returns number of characters read on success, -1 and errno on failure. 274 * @param pszBuf Where to store the path element. Must be at least two 275 * characters, but a longer buffer would be advisable. 276 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 277 * @param pszFormat The filename format, either absolute or relative to "/sys/". 278 * @param ... Format args. 279 */ 280 ssize_t RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, const char *pszFormat, ...) 205 RTDECL(ssize_t) RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, const char *pszFormat, ...) 281 206 { 282 207 va_list va; … … 288 213 289 214 290 /** 291 * Reads the last element of the path of the file pointed to by the symbolic 292 * link specified. This is needed at least to get the name of the driver 293 * associated with a device, where pszFormat should be the "driver" link in the 294 * devices sysfs directory. 295 * 296 * @returns The number of characters written on success, -1 and errno on failure. 297 * @param pszBuf Where to store the path element. Must be at least two 298 * characters, but a longer buffer would be advisable. 299 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 300 * @param pszFormat The filename format, either absolute or relative to "/sys/". 301 * @param ... Format args. 302 */ 303 int RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, const char *pszFormat, ...) 304 { 305 if (cchBuf < 2) 306 AssertFailedReturnStmt(errno = EINVAL, -1); 307 va_list va; 308 va_start(va, pszFormat); 309 char szFilename[RTPATH_MAX], szLink[RTPATH_MAX]; 215 RTDECL(ssize_t) RTLinuxSysFsGetLinkDestV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va) 216 { 217 AssertReturnStmt(cchBuf >= 2, errno = EINVAL, -1); 218 219 /* 220 * Construct the filename and read the link. 221 */ 222 char szFilename[RTPATH_MAX]; 310 223 int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va); 311 va_end(va); 312 if (rc == sizeof(szFilename)) 313 { 314 rc = -1; 315 errno = EINVAL; /* Bad format arguements */ 316 } 317 if (rc > 0) 318 rc = readlink(szFilename, szLink, sizeof(szLink)); 319 if (rc > 0 && static_cast<size_t>(rc) > sizeof(szLink) - 1) 320 { 321 rc = -1; 322 errno = EIO; /* The path name can't be this big. */ 323 } 324 if (rc >= 0) 325 { 326 szLink[rc] = '\0'; 327 char *lastPart = strrchr(szLink, '/'); 328 Assert(lastPart != NULL); /* rtLinuxSysFsConstructPath guarantees a path 329 * starting with '/'. */ 224 if (rc == -1) 225 return -1; 226 227 char szLink[RTPATH_MAX]; 228 rc = readlink(szFilename, szLink, sizeof(szLink)); 229 if (rc == -1) 230 return -1; 231 if ((size_t)rc > sizeof(szLink) - 1) 232 { 233 errno = ERANGE; 234 return -1; 235 } 236 szLink[rc] = '\0'; /* readlink fun. */ 237 238 /* 239 * Extract the file name component and copy it into the return buffer. 240 */ 241 size_t cchName; 242 const char *pszName = RTPathFilename(szLink); 243 if (pszName) 244 { 245 cchName = strlen(pszName); 246 if (cchName >= cchBuf) 247 { 248 errno = ERANGE; 249 return -1; 250 } 251 memcpy(pszBuf, pszName, cchName); 252 } 253 else 254 { 330 255 *pszBuf = '\0'; 331 strncat(pszBuf, lastPart + 1, cchBuf); 332 rc = strlen(pszBuf); 333 } 256 cchName = 0; 257 } 258 return cchName; 259 } 260 261 262 RTDECL(ssize_t) RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, const char *pszFormat, ...) 263 { 264 va_list va; 265 va_start(va, pszFormat); 266 int rc = RTLinuxSysFsGetLinkDestV(pszBuf, cchBuf, pszFormat, va); 267 va_end(va); 334 268 return rc; 335 269 }
Note:
See TracChangeset
for help on using the changeset viewer.