… | |
… | |
200 | /*****************************************************************************/ |
200 | /*****************************************************************************/ |
201 | |
201 | |
202 | #define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) |
202 | #define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) |
203 | |
203 | |
204 | /* calculate time difference in ~1/EIO_TICKS of a second */ |
204 | /* calculate time difference in ~1/EIO_TICKS of a second */ |
205 | ECB_INLINE int |
205 | ecb_inline int |
206 | tvdiff (struct timeval *tv1, struct timeval *tv2) |
206 | tvdiff (struct timeval *tv1, struct timeval *tv2) |
207 | { |
207 | { |
208 | return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS |
208 | return (tv2->tv_sec - tv1->tv_sec ) * EIO_TICKS |
209 | + ((tv2->tv_usec - tv1->tv_usec) >> 10); |
209 | + ((tv2->tv_usec - tv1->tv_usec) >> 10); |
210 | } |
210 | } |
… | |
… | |
1006 | |
1006 | |
1007 | /* according to source inspection, this is correct, and useful behaviour */ |
1007 | /* according to source inspection, this is correct, and useful behaviour */ |
1008 | if (sbytes) |
1008 | if (sbytes) |
1009 | res = sbytes; |
1009 | res = sbytes; |
1010 | |
1010 | |
1011 | # elif defined (__APPLE__) |
1011 | # elif defined (__APPLE__) && 0 /* broken, as everything on os x */ |
1012 | off_t sbytes = count; |
1012 | off_t sbytes = count; |
1013 | res = sendfile (ifd, ofd, offset, &sbytes, 0, 0); |
1013 | res = sendfile (ifd, ofd, offset, &sbytes, 0, 0); |
1014 | |
1014 | |
1015 | /* according to the manpage, sbytes is always valid */ |
1015 | /* according to the manpage, sbytes is always valid */ |
1016 | if (sbytes) |
1016 | if (sbytes) |
… | |
… | |
1115 | count -= cnt; |
1115 | count -= cnt; |
1116 | } |
1116 | } |
1117 | } |
1117 | } |
1118 | |
1118 | |
1119 | return res; |
1119 | return res; |
|
|
1120 | } |
|
|
1121 | |
|
|
1122 | #ifdef PAGESIZE |
|
|
1123 | # define eio_pagesize() PAGESIZE |
|
|
1124 | #else |
|
|
1125 | static intptr_t |
|
|
1126 | eio_pagesize (void) |
|
|
1127 | { |
|
|
1128 | static intptr_t page; |
|
|
1129 | |
|
|
1130 | if (!page) |
|
|
1131 | page = sysconf (_SC_PAGESIZE); |
|
|
1132 | |
|
|
1133 | return page; |
|
|
1134 | } |
|
|
1135 | #endif |
|
|
1136 | |
|
|
1137 | static void |
|
|
1138 | eio_page_align (void **addr, size_t *length) |
|
|
1139 | { |
|
|
1140 | intptr_t mask = eio_pagesize () - 1; |
|
|
1141 | |
|
|
1142 | /* round down addr */ |
|
|
1143 | intptr_t adj = mask & (intptr_t)*addr; |
|
|
1144 | |
|
|
1145 | *addr = (void *)((intptr_t)*addr - adj); |
|
|
1146 | *length += adj; |
|
|
1147 | |
|
|
1148 | /* round up length */ |
|
|
1149 | *length = (*length + mask) & ~mask; |
|
|
1150 | } |
|
|
1151 | |
|
|
1152 | #if !_POSIX_MEMLOCK |
|
|
1153 | # define eio__mlockall(a) ((errno = ENOSYS), -1) |
|
|
1154 | #else |
|
|
1155 | |
|
|
1156 | static int |
|
|
1157 | eio__mlockall (int flags) |
|
|
1158 | { |
|
|
1159 | #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7 |
|
|
1160 | extern int mallopt (int, int); |
|
|
1161 | mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */ |
|
|
1162 | #endif |
|
|
1163 | |
|
|
1164 | if (EIO_MCL_CURRENT != MCL_CURRENT |
|
|
1165 | || EIO_MCL_FUTURE != MCL_FUTURE) |
|
|
1166 | { |
|
|
1167 | flags = 0 |
|
|
1168 | | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0) |
|
|
1169 | | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0); |
|
|
1170 | } |
|
|
1171 | |
|
|
1172 | return mlockall (flags); |
|
|
1173 | } |
|
|
1174 | #endif |
|
|
1175 | |
|
|
1176 | #if !_POSIX_MEMLOCK_RANGE |
|
|
1177 | # define eio__mlock(a,b) ((errno = ENOSYS), -1) |
|
|
1178 | #else |
|
|
1179 | |
|
|
1180 | static int |
|
|
1181 | eio__mlock (void *addr, size_t length) |
|
|
1182 | { |
|
|
1183 | eio_page_align (&addr, &length); |
|
|
1184 | |
|
|
1185 | return mlock (addr, length); |
|
|
1186 | } |
|
|
1187 | |
|
|
1188 | #endif |
|
|
1189 | |
|
|
1190 | #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) |
|
|
1191 | # define eio__msync(a,b,c) ((errno = ENOSYS), -1) |
|
|
1192 | #else |
|
|
1193 | |
|
|
1194 | static int |
|
|
1195 | eio__msync (void *mem, size_t len, int flags) |
|
|
1196 | { |
|
|
1197 | eio_page_align (&mem, &len); |
|
|
1198 | |
|
|
1199 | if (EIO_MS_ASYNC != MS_SYNC |
|
|
1200 | || EIO_MS_INVALIDATE != MS_INVALIDATE |
|
|
1201 | || EIO_MS_SYNC != MS_SYNC) |
|
|
1202 | { |
|
|
1203 | flags = 0 |
|
|
1204 | | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0) |
|
|
1205 | | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0) |
|
|
1206 | | (flags & EIO_MS_SYNC ? MS_SYNC : 0); |
|
|
1207 | } |
|
|
1208 | |
|
|
1209 | return msync (mem, len, flags); |
|
|
1210 | } |
|
|
1211 | |
|
|
1212 | #endif |
|
|
1213 | |
|
|
1214 | static int |
|
|
1215 | eio__mtouch (eio_req *req) |
|
|
1216 | { |
|
|
1217 | void *mem = req->ptr2; |
|
|
1218 | size_t len = req->size; |
|
|
1219 | int flags = req->int1; |
|
|
1220 | |
|
|
1221 | eio_page_align (&mem, &len); |
|
|
1222 | |
|
|
1223 | { |
|
|
1224 | intptr_t addr = (intptr_t)mem; |
|
|
1225 | intptr_t end = addr + len; |
|
|
1226 | intptr_t page = eio_pagesize (); |
|
|
1227 | |
|
|
1228 | if (addr < end) |
|
|
1229 | if (flags & EIO_MT_MODIFY) /* modify */ |
|
|
1230 | do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1231 | else |
|
|
1232 | do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1233 | } |
|
|
1234 | |
|
|
1235 | return 0; |
|
|
1236 | } |
|
|
1237 | |
|
|
1238 | /*****************************************************************************/ |
|
|
1239 | /* requests implemented outside eio_execute, because they are so large */ |
|
|
1240 | |
|
|
1241 | static void |
|
|
1242 | eio__realpath (eio_req *req, etp_worker *self) |
|
|
1243 | { |
|
|
1244 | char *rel = req->ptr1; |
|
|
1245 | char *res; |
|
|
1246 | char *tmp1, *tmp2; |
|
|
1247 | #if SYMLOOP_MAX > 32 |
|
|
1248 | int links = SYMLOOP_MAX; |
|
|
1249 | #else |
|
|
1250 | int links = 32; |
|
|
1251 | #endif |
|
|
1252 | |
|
|
1253 | req->result = -1; |
|
|
1254 | |
|
|
1255 | errno = EINVAL; |
|
|
1256 | if (!rel) |
|
|
1257 | return; |
|
|
1258 | |
|
|
1259 | errno = ENOENT; |
|
|
1260 | if (!*rel) |
|
|
1261 | return; |
|
|
1262 | |
|
|
1263 | if (!req->ptr2) |
|
|
1264 | { |
|
|
1265 | X_LOCK (wrklock); |
|
|
1266 | req->flags |= EIO_FLAG_PTR2_FREE; |
|
|
1267 | X_UNLOCK (wrklock); |
|
|
1268 | req->ptr2 = malloc (PATH_MAX * 3); |
|
|
1269 | |
|
|
1270 | errno = ENOMEM; |
|
|
1271 | if (!req->ptr2) |
|
|
1272 | return; |
|
|
1273 | } |
|
|
1274 | |
|
|
1275 | res = req->ptr2; |
|
|
1276 | tmp1 = res + PATH_MAX; |
|
|
1277 | tmp2 = tmp1 + PATH_MAX; |
|
|
1278 | |
|
|
1279 | if (*rel != '/') |
|
|
1280 | { |
|
|
1281 | if (!getcwd (res, PATH_MAX)) |
|
|
1282 | return; |
|
|
1283 | |
|
|
1284 | if (res [1]) /* only use if not / */ |
|
|
1285 | res += strlen (res); |
|
|
1286 | } |
|
|
1287 | |
|
|
1288 | while (*rel) |
|
|
1289 | { |
|
|
1290 | ssize_t len, linklen; |
|
|
1291 | char *beg = rel; |
|
|
1292 | |
|
|
1293 | while (*rel && *rel != '/') |
|
|
1294 | ++rel; |
|
|
1295 | |
|
|
1296 | len = rel - beg; |
|
|
1297 | |
|
|
1298 | if (!len) /* skip slashes */ |
|
|
1299 | { |
|
|
1300 | ++rel; |
|
|
1301 | continue; |
|
|
1302 | } |
|
|
1303 | |
|
|
1304 | if (beg [0] == '.') |
|
|
1305 | { |
|
|
1306 | if (len == 1) |
|
|
1307 | continue; /* . - nop */ |
|
|
1308 | |
|
|
1309 | if (beg [1] == '.' && len == 2) |
|
|
1310 | { |
|
|
1311 | /* .. - back up one component, if possible */ |
|
|
1312 | |
|
|
1313 | while (res != req->ptr2) |
|
|
1314 | if (*--res == '/') |
|
|
1315 | break; |
|
|
1316 | |
|
|
1317 | continue; |
|
|
1318 | } |
|
|
1319 | } |
|
|
1320 | |
|
|
1321 | errno = ENAMETOOLONG; |
|
|
1322 | if (res + 1 + len + 1 >= tmp1) |
|
|
1323 | return; |
|
|
1324 | |
|
|
1325 | /* copy one component */ |
|
|
1326 | *res = '/'; |
|
|
1327 | memcpy (res + 1, beg, len); |
|
|
1328 | |
|
|
1329 | /* zero-terminate, for readlink */ |
|
|
1330 | res [len + 1] = 0; |
|
|
1331 | |
|
|
1332 | /* now check if it's a symlink */ |
|
|
1333 | linklen = readlink (req->ptr2, tmp1, PATH_MAX); |
|
|
1334 | |
|
|
1335 | if (linklen < 0) |
|
|
1336 | { |
|
|
1337 | if (errno != EINVAL) |
|
|
1338 | return; |
|
|
1339 | |
|
|
1340 | /* it's a normal directory. hopefully */ |
|
|
1341 | res += len + 1; |
|
|
1342 | } |
|
|
1343 | else |
|
|
1344 | { |
|
|
1345 | /* yay, it was a symlink - build new path in tmp2 */ |
|
|
1346 | int rellen = strlen (rel); |
|
|
1347 | |
|
|
1348 | errno = ENAMETOOLONG; |
|
|
1349 | if (linklen + 1 + rellen >= PATH_MAX) |
|
|
1350 | return; |
|
|
1351 | |
|
|
1352 | if (*tmp1 == '/') |
|
|
1353 | res = req->ptr2; /* symlink resolves to an absolute path */ |
|
|
1354 | |
|
|
1355 | /* we need to be careful, as rel might point into tmp2 already */ |
|
|
1356 | memmove (tmp2 + linklen + 1, rel, rellen + 1); |
|
|
1357 | tmp2 [linklen] = '/'; |
|
|
1358 | memcpy (tmp2, tmp1, linklen); |
|
|
1359 | |
|
|
1360 | rel = tmp2; |
|
|
1361 | } |
|
|
1362 | } |
|
|
1363 | |
|
|
1364 | /* special case for the lone root path */ |
|
|
1365 | if (res == req->ptr2) |
|
|
1366 | *res++ = '/'; |
|
|
1367 | |
|
|
1368 | req->result = res - (char *)req->ptr2; |
|
|
1369 | req->ptr2 = realloc (req->ptr2, req->result); /* trade time for space savings */ |
1120 | } |
1370 | } |
1121 | |
1371 | |
1122 | static signed char |
1372 | static signed char |
1123 | eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) |
1373 | eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) |
1124 | { |
1374 | { |
… | |
… | |
1305 | flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER); |
1555 | flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER); |
1306 | |
1556 | |
1307 | X_LOCK (wrklock); |
1557 | X_LOCK (wrklock); |
1308 | /* the corresponding closedir is in ETP_WORKER_CLEAR */ |
1558 | /* the corresponding closedir is in ETP_WORKER_CLEAR */ |
1309 | self->dirp = dirp = opendir (req->ptr1); |
1559 | self->dirp = dirp = opendir (req->ptr1); |
|
|
1560 | |
|
|
1561 | if (req->flags & EIO_FLAG_PTR1_FREE) |
|
|
1562 | free (req->ptr1); |
1310 | |
1563 | |
1311 | req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; |
1564 | req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; |
1312 | req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; |
1565 | req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; |
1313 | req->ptr2 = names = malloc (namesalloc); |
1566 | req->ptr2 = names = malloc (namesalloc); |
1314 | X_UNLOCK (wrklock); |
1567 | X_UNLOCK (wrklock); |
… | |
… | |
1481 | break; |
1734 | break; |
1482 | } |
1735 | } |
1483 | } |
1736 | } |
1484 | } |
1737 | } |
1485 | |
1738 | |
1486 | #ifdef PAGESIZE |
|
|
1487 | # define eio_pagesize() PAGESIZE |
|
|
1488 | #else |
|
|
1489 | static intptr_t |
|
|
1490 | eio_pagesize (void) |
|
|
1491 | { |
|
|
1492 | static intptr_t page; |
|
|
1493 | |
|
|
1494 | if (!page) |
|
|
1495 | page = sysconf (_SC_PAGESIZE); |
|
|
1496 | |
|
|
1497 | return page; |
|
|
1498 | } |
|
|
1499 | #endif |
|
|
1500 | |
|
|
1501 | static void |
|
|
1502 | eio_page_align (void **addr, size_t *length) |
|
|
1503 | { |
|
|
1504 | intptr_t mask = eio_pagesize () - 1; |
|
|
1505 | |
|
|
1506 | /* round down addr */ |
|
|
1507 | intptr_t adj = mask & (intptr_t)*addr; |
|
|
1508 | |
|
|
1509 | *addr = (void *)((intptr_t)*addr - adj); |
|
|
1510 | *length += adj; |
|
|
1511 | |
|
|
1512 | /* round up length */ |
|
|
1513 | *length = (*length + mask) & ~mask; |
|
|
1514 | } |
|
|
1515 | |
|
|
1516 | #if !_POSIX_MEMLOCK |
|
|
1517 | # define eio__mlockall(a) ((errno = ENOSYS), -1) |
|
|
1518 | #else |
|
|
1519 | |
|
|
1520 | static int |
|
|
1521 | eio__mlockall (int flags) |
|
|
1522 | { |
|
|
1523 | #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7 |
|
|
1524 | extern int mallopt (int, int); |
|
|
1525 | mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */ |
|
|
1526 | #endif |
|
|
1527 | |
|
|
1528 | if (EIO_MCL_CURRENT != MCL_CURRENT |
|
|
1529 | || EIO_MCL_FUTURE != MCL_FUTURE) |
|
|
1530 | { |
|
|
1531 | flags = 0 |
|
|
1532 | | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0) |
|
|
1533 | | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0); |
|
|
1534 | } |
|
|
1535 | |
|
|
1536 | return mlockall (flags); |
|
|
1537 | } |
|
|
1538 | #endif |
|
|
1539 | |
|
|
1540 | #if !_POSIX_MEMLOCK_RANGE |
|
|
1541 | # define eio__mlock(a,b) ((errno = ENOSYS), -1) |
|
|
1542 | #else |
|
|
1543 | |
|
|
1544 | static int |
|
|
1545 | eio__mlock (void *addr, size_t length) |
|
|
1546 | { |
|
|
1547 | eio_page_align (&addr, &length); |
|
|
1548 | |
|
|
1549 | return mlock (addr, length); |
|
|
1550 | } |
|
|
1551 | |
|
|
1552 | #endif |
|
|
1553 | |
|
|
1554 | #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) |
|
|
1555 | # define eio__msync(a,b,c) ((errno = ENOSYS), -1) |
|
|
1556 | #else |
|
|
1557 | |
|
|
1558 | static int |
|
|
1559 | eio__msync (void *mem, size_t len, int flags) |
|
|
1560 | { |
|
|
1561 | eio_page_align (&mem, &len); |
|
|
1562 | |
|
|
1563 | if (EIO_MS_ASYNC != MS_SYNC |
|
|
1564 | || EIO_MS_INVALIDATE != MS_INVALIDATE |
|
|
1565 | || EIO_MS_SYNC != MS_SYNC) |
|
|
1566 | { |
|
|
1567 | flags = 0 |
|
|
1568 | | (flags & EIO_MS_ASYNC ? MS_ASYNC : 0) |
|
|
1569 | | (flags & EIO_MS_INVALIDATE ? MS_INVALIDATE : 0) |
|
|
1570 | | (flags & EIO_MS_SYNC ? MS_SYNC : 0); |
|
|
1571 | } |
|
|
1572 | |
|
|
1573 | return msync (mem, len, flags); |
|
|
1574 | } |
|
|
1575 | |
|
|
1576 | #endif |
|
|
1577 | |
|
|
1578 | static int |
|
|
1579 | eio__mtouch (eio_req *req) |
|
|
1580 | { |
|
|
1581 | void *mem = req->ptr2; |
|
|
1582 | size_t len = req->size; |
|
|
1583 | int flags = req->int1; |
|
|
1584 | |
|
|
1585 | eio_page_align (&mem, &len); |
|
|
1586 | |
|
|
1587 | { |
|
|
1588 | intptr_t addr = (intptr_t)mem; |
|
|
1589 | intptr_t end = addr + len; |
|
|
1590 | intptr_t page = eio_pagesize (); |
|
|
1591 | |
|
|
1592 | if (addr < end) |
|
|
1593 | if (flags & EIO_MT_MODIFY) /* modify */ |
|
|
1594 | do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1595 | else |
|
|
1596 | do { *((volatile sig_atomic_t *)addr) ; } while ((addr += page) < len && !EIO_CANCELLED (req)); |
|
|
1597 | } |
|
|
1598 | |
|
|
1599 | return 0; |
|
|
1600 | } |
|
|
1601 | |
|
|
1602 | /*****************************************************************************/ |
1739 | /*****************************************************************************/ |
1603 | |
1740 | |
1604 | #define ALLOC(len) \ |
1741 | #define ALLOC(len) \ |
1605 | if (!req->ptr2) \ |
1742 | if (!req->ptr2) \ |
1606 | { \ |
1743 | { \ |
… | |
… | |
1695 | eio_init (void (*want_poll)(void), void (*done_poll)(void)) |
1832 | eio_init (void (*want_poll)(void), void (*done_poll)(void)) |
1696 | { |
1833 | { |
1697 | return etp_init (want_poll, done_poll); |
1834 | return etp_init (want_poll, done_poll); |
1698 | } |
1835 | } |
1699 | |
1836 | |
1700 | ECB_INLINE void |
1837 | ecb_inline void |
1701 | eio_api_destroy (eio_req *req) |
1838 | eio_api_destroy (eio_req *req) |
1702 | { |
1839 | { |
1703 | free (req); |
1840 | free (req); |
1704 | } |
1841 | } |
1705 | |
1842 | |
… | |
… | |
1771 | case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break; |
1908 | case EIO_RENAME: req->result = rename (req->ptr1, req->ptr2); break; |
1772 | case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break; |
1909 | case EIO_LINK: req->result = link (req->ptr1, req->ptr2); break; |
1773 | case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break; |
1910 | case EIO_SYMLINK: req->result = symlink (req->ptr1, req->ptr2); break; |
1774 | case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break; |
1911 | case EIO_MKNOD: req->result = mknod (req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break; |
1775 | |
1912 | |
|
|
1913 | case EIO_REALPATH: eio__realpath (req, self); break; |
|
|
1914 | |
1776 | case EIO_READLINK: ALLOC (PATH_MAX); |
1915 | case EIO_READLINK: ALLOC (PATH_MAX); |
1777 | req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; |
1916 | req->result = readlink (req->ptr1, req->ptr2, PATH_MAX); break; |
1778 | |
1917 | |
1779 | case EIO_SYNC: req->result = 0; sync (); break; |
1918 | case EIO_SYNC: req->result = 0; sync (); break; |
1780 | case EIO_FSYNC: req->result = fsync (req->int1); break; |
1919 | case EIO_FSYNC: req->result = fsync (req->int1); break; |
… | |
… | |
1997 | eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data) |
2136 | eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data) |
1998 | { |
2137 | { |
1999 | return eio__1path (EIO_READLINK, path, pri, cb, data); |
2138 | return eio__1path (EIO_READLINK, path, pri, cb, data); |
2000 | } |
2139 | } |
2001 | |
2140 | |
|
|
2141 | eio_req *eio_realpath (const char *path, int pri, eio_cb cb, void *data) |
|
|
2142 | { |
|
|
2143 | return eio__1path (EIO_REALPATH, path, pri, cb, data); |
|
|
2144 | } |
|
|
2145 | |
2002 | eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data) |
2146 | eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data) |
2003 | { |
2147 | { |
2004 | return eio__1path (EIO_STAT, path, pri, cb, data); |
2148 | return eio__1path (EIO_STAT, path, pri, cb, data); |
2005 | } |
2149 | } |
2006 | |
2150 | |