… | |
… | |
1243 | { |
1243 | { |
1244 | char *rel = req->ptr1; |
1244 | char *rel = req->ptr1; |
1245 | char *res; |
1245 | char *res; |
1246 | char *tmp1, *tmp2; |
1246 | char *tmp1, *tmp2; |
1247 | #if SYMLOOP_MAX > 32 |
1247 | #if SYMLOOP_MAX > 32 |
1248 | int links = SYMLOOP_MAX; |
1248 | int symlinks = SYMLOOP_MAX; |
1249 | #else |
1249 | #else |
1250 | int links = 32; |
1250 | int symlinks = 32; |
1251 | #endif |
1251 | #endif |
1252 | |
1252 | |
1253 | req->result = -1; |
1253 | req->result = -1; |
1254 | |
1254 | |
1255 | errno = EINVAL; |
1255 | errno = EINVAL; |
… | |
… | |
1273 | } |
1273 | } |
1274 | |
1274 | |
1275 | res = req->ptr2; |
1275 | res = req->ptr2; |
1276 | tmp1 = res + PATH_MAX; |
1276 | tmp1 = res + PATH_MAX; |
1277 | tmp2 = tmp1 + PATH_MAX; |
1277 | tmp2 = tmp1 + PATH_MAX; |
|
|
1278 | |
|
|
1279 | #if 0 /* disabled, the musl way to do things is just too racy */ |
|
|
1280 | #if __linux && defined(O_NONBLOCK) && defined(O_NOATIME) |
|
|
1281 | /* on linux we may be able to ask the kernel */ |
|
|
1282 | { |
|
|
1283 | int fd = open (rel, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOATIME); |
|
|
1284 | |
|
|
1285 | if (fd >= 0) |
|
|
1286 | { |
|
|
1287 | sprintf (tmp1, "/proc/self/fd/%d", fd); |
|
|
1288 | req->result = readlink (tmp1, res, PATH_MAX); |
|
|
1289 | close (fd); |
|
|
1290 | |
|
|
1291 | /* here we should probably stat the open file and the disk file, to make sure they still match */ |
|
|
1292 | |
|
|
1293 | if (req->result > 0) |
|
|
1294 | goto done; |
|
|
1295 | } |
|
|
1296 | else if (errno == ELOOP || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EIO) |
|
|
1297 | return; |
|
|
1298 | } |
|
|
1299 | #endif |
|
|
1300 | #endif |
1278 | |
1301 | |
1279 | if (*rel != '/') |
1302 | if (*rel != '/') |
1280 | { |
1303 | { |
1281 | if (!getcwd (res, PATH_MAX)) |
1304 | if (!getcwd (res, PATH_MAX)) |
1282 | return; |
1305 | return; |
… | |
… | |
1347 | |
1370 | |
1348 | errno = ENAMETOOLONG; |
1371 | errno = ENAMETOOLONG; |
1349 | if (linklen + 1 + rellen >= PATH_MAX) |
1372 | if (linklen + 1 + rellen >= PATH_MAX) |
1350 | return; |
1373 | return; |
1351 | |
1374 | |
|
|
1375 | errno = ELOOP; |
|
|
1376 | if (!--symlinks) |
|
|
1377 | return; |
|
|
1378 | |
1352 | if (*tmp1 == '/') |
1379 | if (*tmp1 == '/') |
1353 | res = req->ptr2; /* symlink resolves to an absolute path */ |
1380 | res = req->ptr2; /* symlink resolves to an absolute path */ |
1354 | |
1381 | |
1355 | /* we need to be careful, as rel might point into tmp2 already */ |
1382 | /* we need to be careful, as rel might point into tmp2 already */ |
1356 | memmove (tmp2 + linklen + 1, rel, rellen + 1); |
1383 | memmove (tmp2 + linklen + 1, rel, rellen + 1); |
… | |
… | |
1364 | /* special case for the lone root path */ |
1391 | /* special case for the lone root path */ |
1365 | if (res == req->ptr2) |
1392 | if (res == req->ptr2) |
1366 | *res++ = '/'; |
1393 | *res++ = '/'; |
1367 | |
1394 | |
1368 | req->result = res - (char *)req->ptr2; |
1395 | req->result = res - (char *)req->ptr2; |
|
|
1396 | |
|
|
1397 | done: |
1369 | req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */ |
1398 | req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */ |
1370 | } |
1399 | } |
1371 | |
1400 | |
1372 | static signed char |
1401 | static signed char |
1373 | eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) |
1402 | eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) |