ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libeio/eio.c
(Generate patch)

Comparing libeio/eio.c (file contents):
Revision 1.104 by root, Mon Sep 26 16:54:25 2011 UTC vs.
Revision 1.120 by root, Tue Apr 24 18:47:50 2012 UTC

1/* 1/*
2 * libeio implementation 2 * libeio implementation
3 * 3 *
4 * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libeio@schmorp.de> 4 * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann <libeio@schmorp.de>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without modifica- 7 * Redistribution and use in source and binary forms, with or without modifica-
8 * tion, are permitted provided that the following conditions are met: 8 * tion, are permitted provided that the following conditions are met:
9 * 9 *
208 #endif 208 #endif
209 209
210 #define D_NAME(entp) entp->d_name 210 #define D_NAME(entp) entp->d_name
211 211
212 /* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */ 212 /* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */
213 #if __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ 213 #if __FreeBSD__ || __NetBSD__ || __OpenBSD__
214 #define _DIRENT_HAVE_D_TYPE /* sigh */ 214 #define _DIRENT_HAVE_D_TYPE /* sigh */
215 #define D_INO(de) (de)->d_fileno 215 #define D_INO(de) (de)->d_fileno
216 #define D_NAMLEN(de) (de)->d_namlen 216 #define D_NAMLEN(de) (de)->d_namlen
217 #elif __linux || defined d_ino || _XOPEN_SOURCE >= 600 217 #elif __linux || defined d_ino || _XOPEN_SOURCE >= 600
218 #define D_INO(de) (de)->d_ino 218 #define D_INO(de) (de)->d_ino
312 } 312 }
313 313
314 return buf->ptr; 314 return buf->ptr;
315} 315}
316 316
317struct tmpbuf;
318
319#if _POSIX_VERSION >= 200809L
320 #define HAVE_AT 1
321 #define WD2FD(wd) ((wd) ? (wd)->fd : AT_FDCWD)
322 #ifndef O_SEARCH
323 #define O_SEARCH O_RDONLY
324 #endif
325#else
326 #define HAVE_AT 0
327 static const char *wd_expand (struct tmpbuf *tmpbuf, eio_wd wd, const char *path);
328#endif
329
330struct eio_pwd
331{
332#if HAVE_AT
333 int fd;
334#endif
335 int len;
336 char str[1]; /* actually, a 0-terminated canonical path */
337};
338
317/*****************************************************************************/ 339/*****************************************************************************/
318 340
319#define ETP_PRI_MIN EIO_PRI_MIN 341#define ETP_PRI_MIN EIO_PRI_MIN
320#define ETP_PRI_MAX EIO_PRI_MAX 342#define ETP_PRI_MAX EIO_PRI_MAX
321 343
387#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock) 409#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock)
388#define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (wrklock) 410#define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (wrklock)
389 411
390/* worker threads management */ 412/* worker threads management */
391 413
392static void ecb_cold 414static void
393etp_worker_clear (etp_worker *wrk) 415etp_worker_clear (etp_worker *wrk)
394{ 416{
395} 417}
396 418
397static void ecb_cold 419static void ecb_cold
584} 606}
585 607
586static void ecb_cold 608static void ecb_cold
587etp_end_thread (void) 609etp_end_thread (void)
588{ 610{
589 eio_req *req = calloc (1, sizeof (eio_req)); 611 eio_req *req = calloc (1, sizeof (eio_req)); /* will be freed by worker */
590 612
591 req->type = -1; 613 req->type = -1;
592 req->pri = ETP_PRI_MAX - ETP_PRI_MIN; 614 req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
593 615
594 X_LOCK (reqlock); 616 X_LOCK (reqlock);
1010 int res; 1032 int res;
1011 1033
1012#if HAVE_SYS_SYNCFS 1034#if HAVE_SYS_SYNCFS
1013 res = (int)syscall (__NR_syncfs, (int)(fd)); 1035 res = (int)syscall (__NR_syncfs, (int)(fd));
1014#else 1036#else
1015 res = -1; 1037 res = EIO_ENOSYS ();
1016 errno = ENOSYS;
1017#endif 1038#endif
1018 1039
1019 if (res < 0 && errno == ENOSYS && fd >= 0) 1040 if (res < 0 && errno == ENOSYS && fd >= 0)
1020 sync (); 1041 sync ();
1021 1042
1051} 1072}
1052 1073
1053static int 1074static int
1054eio__fallocate (int fd, int mode, off_t offset, size_t len) 1075eio__fallocate (int fd, int mode, off_t offset, size_t len)
1055{ 1076{
1056#if HAVE_FALLOCATE 1077#if HAVE_LINUX_FALLOCATE
1057 return fallocate (fd, mode, offset, len); 1078 return fallocate (fd, mode, offset, len);
1058#else 1079#else
1059 errno = ENOSYS; 1080 return EIO_ENOSYS ();
1060 return -1;
1061#endif 1081#endif
1062} 1082}
1063 1083
1064#if !HAVE_READAHEAD 1084#if !HAVE_READAHEAD
1065# undef readahead 1085# undef readahead
1080 todo -= len; 1100 todo -= len;
1081 } 1101 }
1082 1102
1083 FUBd; 1103 FUBd;
1084 1104
1085 errno = 0; 1105 /* linux's readahead basically only fails for EBADF or EINVAL (not mmappable) */
1106 /* but not for e.g. EIO or eof, so we also never fail */
1086 return count; 1107 return 0;
1087} 1108}
1088 1109
1089#endif 1110#endif
1090 1111
1091/* sendfile always needs emulation */ 1112/* sendfile always needs emulation */
1126 1147
1127 /* according to source inspection, this is correct, and useful behaviour */ 1148 /* according to source inspection, this is correct, and useful behaviour */
1128 if (sbytes) 1149 if (sbytes)
1129 res = sbytes; 1150 res = sbytes;
1130 1151
1131# elif defined (__APPLE__) 1152# elif defined __APPLE__
1132 off_t sbytes = count; 1153 off_t sbytes = count;
1133 res = sendfile (ifd, ofd, offset, &sbytes, 0, 0); 1154 res = sendfile (ifd, ofd, offset, &sbytes, 0, 0);
1134 1155
1135 /* according to the manpage, sbytes is always valid */ 1156 /* according to the manpage, sbytes is always valid */
1136 if (sbytes) 1157 if (sbytes)
1163 HANDLE h = TO_SOCKET (ifd); 1184 HANDLE h = TO_SOCKET (ifd);
1164 SetFilePointer (h, offset, 0, FILE_BEGIN); 1185 SetFilePointer (h, offset, 0, FILE_BEGIN);
1165 res = TransmitFile (TO_SOCKET (ofd), h, count, 0, 0, 0, 0); 1186 res = TransmitFile (TO_SOCKET (ofd), h, count, 0, 0, 0, 0);
1166 1187
1167#else 1188#else
1168 res = -1; 1189 res = EIO_ENOSYS ();
1169 errno = ENOSYS;
1170#endif 1190#endif
1171 1191
1172 /* we assume sendfile can copy at least 128mb in one go */ 1192 /* we assume sendfile can copy at least 128mb in one go */
1173 if (res <= 128 * 1024 * 1024) 1193 if (res <= 128 * 1024 * 1024)
1174 { 1194 {
1360} 1380}
1361 1381
1362/*****************************************************************************/ 1382/*****************************************************************************/
1363/* requests implemented outside eio_execute, because they are so large */ 1383/* requests implemented outside eio_execute, because they are so large */
1364 1384
1365/* copies some absolute path to tmpbuf */ 1385static void
1366static char * 1386eio__lseek (eio_req *req)
1367eio__getwd (struct tmpbuf *tmpbuf, eio_wd wd)
1368{ 1387{
1369 if (wd == EIO_CWD) 1388 /* this usually gets optimised away completely, or your compiler sucks, */
1370 return getcwd (tmpbuf->ptr, PATH_MAX); 1389 /* or the whence constants really are not 0, 1, 2 */
1390 int whence = req->int2 == EIO_SEEK_SET ? SEEK_SET
1391 : req->int2 == EIO_SEEK_CUR ? SEEK_CUR
1392 : req->int2 == EIO_SEEK_END ? SEEK_END
1393 : req->int2;
1371 1394
1372#if HAVE_AT 1395 req->offs = lseek (req->int1, req->offs, whence);
1373 abort (); /*TODO*/ 1396 req->result = req->offs == (off_t)-1 ? -1 : 0;
1374#else
1375 strcpy (tmpbuf->ptr, wd);
1376#endif
1377 return tmpbuf->ptr;
1378} 1397}
1379 1398
1380/* result will always end up in tmpbuf, there is always space for adding a 0-byte */ 1399/* result will always end up in tmpbuf, there is always space for adding a 0-byte */
1381static int 1400static int
1382eio__realpath (struct tmpbuf *tmpbuf, eio_wd wd, const char *path) 1401eio__realpath (struct tmpbuf *tmpbuf, eio_wd wd, const char *path)
1388 int symlinks = SYMLOOP_MAX; 1407 int symlinks = SYMLOOP_MAX;
1389#else 1408#else
1390 int symlinks = 32; 1409 int symlinks = 32;
1391#endif 1410#endif
1392 1411
1393 /*D*/ /*TODO: wd ignored */
1394
1395 errno = EINVAL; 1412 errno = EINVAL;
1396 if (!rel) 1413 if (!rel)
1397 return -1; 1414 return -1;
1398 1415
1399 errno = ENOENT; 1416 errno = ENOENT;
1427#endif 1444#endif
1428#endif 1445#endif
1429 1446
1430 if (*rel != '/') 1447 if (*rel != '/')
1431 { 1448 {
1432 if (!eio__getwd (tmpbuf, wd)) 1449 int len;
1450
1451 errno = ENOENT;
1452 if (wd == EIO_INVALID_WD)
1433 return -1; 1453 return -1;
1454
1455 if (wd == EIO_CWD)
1456 {
1457 if (!getcwd (res, PATH_MAX))
1458 return -1;
1459
1460 len = strlen (res);
1461 }
1462 else
1463 memcpy (res, wd->str, len = wd->len);
1434 1464
1435 if (res [1]) /* only use if not / */ 1465 if (res [1]) /* only use if not / */
1436 res += strlen (res); 1466 res += len;
1437 } 1467 }
1438 1468
1439 while (*rel) 1469 while (*rel)
1440 { 1470 {
1441 eio_ssize_t len, linklen; 1471 eio_ssize_t len, linklen;
1469 } 1499 }
1470 } 1500 }
1471 1501
1472 errno = ENAMETOOLONG; 1502 errno = ENAMETOOLONG;
1473 if (res + 1 + len + 1 >= tmp1) 1503 if (res + 1 + len + 1 >= tmp1)
1474 return; 1504 return -1;
1475 1505
1476 /* copy one component */ 1506 /* copy one component */
1477 *res = '/'; 1507 *res = '/';
1478 memcpy (res + 1, beg, len); 1508 memcpy (res + 1, beg, len);
1479 1509
1688 eio_dent_insertion_sort (dents, size); 1718 eio_dent_insertion_sort (dents, size);
1689} 1719}
1690 1720
1691/* read a full directory */ 1721/* read a full directory */
1692static void 1722static void
1693eio__scandir (eio_req *req) 1723eio__scandir (eio_req *req, etp_worker *self)
1694{ 1724{
1695 char *name, *names; 1725 char *name, *names;
1696 int namesalloc = 4096 - sizeof (void *) * 4; 1726 int namesalloc = 4096 - sizeof (void *) * 4;
1697 int namesoffs = 0; 1727 int namesoffs = 0;
1698 int flags = req->int1; 1728 int flags = req->int1;
1716#ifdef _WIN32 1746#ifdef _WIN32
1717 { 1747 {
1718 int len = strlen ((const char *)req->ptr1); 1748 int len = strlen ((const char *)req->ptr1);
1719 char *path = malloc (MAX_PATH); 1749 char *path = malloc (MAX_PATH);
1720 const char *fmt; 1750 const char *fmt;
1751 const char *reqpath = wd_expand (&self->tmpbuf, req->wd, req->ptr1);
1721 1752
1722 if (!len) 1753 if (!len)
1723 fmt = "./*"; 1754 fmt = "./*";
1724 else if (((const char *)req->ptr1)[len - 1] == '/' || ((const char *)req->ptr1)[len - 1] == '\\') 1755 else if (reqpath[len - 1] == '/' || reqpath[len - 1] == '\\')
1725 fmt = "%s*"; 1756 fmt = "%s*";
1726 else 1757 else
1727 fmt = "%s/*"; 1758 fmt = "%s/*";
1728 1759
1729 _snprintf (path, MAX_PATH, fmt, (const char *)req->ptr1); 1760 _snprintf (path, MAX_PATH, fmt, reqpath);
1730 dirp = FindFirstFile (path, &entp); 1761 dirp = FindFirstFile (path, &entp);
1731 free (path); 1762 free (path);
1732 1763
1733 if (dirp == INVALID_HANDLE_VALUE) 1764 if (dirp == INVALID_HANDLE_VALUE)
1734 { 1765 {
1756 1787
1757 return; 1788 return;
1758 } 1789 }
1759 } 1790 }
1760#else 1791#else
1792 #if HAVE_AT
1793 if (req->wd)
1794 {
1795 int fd = openat (WD2FD (req->wd), req->ptr1, O_CLOEXEC | O_SEARCH | O_DIRECTORY);
1796
1797 if (fd < 0)
1798 return;
1799
1800 dirp = fdopendir (fd);
1801
1802 if (!dirp)
1803 close (fd);
1804 }
1805 else
1761 dirp = opendir (req->ptr1); 1806 dirp = opendir (req->ptr1);
1807 #else
1808 dirp = opendir (wd_expand (&self->tmpbuf, req->wd, req->ptr1));
1809 #endif
1762 1810
1763 if (!dirp) 1811 if (!dirp)
1764 return; 1812 return;
1765#endif 1813#endif
1766 1814
1930 { 1978 {
1931 if (ent->type == EIO_DT_UNKNOWN) 1979 if (ent->type == EIO_DT_UNKNOWN)
1932 { 1980 {
1933 if (*name == '.') /* leading dots are likely directories, and, in any case, rare */ 1981 if (*name == '.') /* leading dots are likely directories, and, in any case, rare */
1934 ent->score = 1; 1982 ent->score = 1;
1935 else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */ 1983 else if (!strchr (name, '.')) /* absence of dots indicate likely dirs */
1936 ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */ 1984 ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */
1937 } 1985 }
1938 else if (ent->type == EIO_DT_DIR) 1986 else if (ent->type == EIO_DT_DIR)
1939 ent->score = 0; 1987 ent->score = 0;
1940 } 1988 }
1960 } 2008 }
1961} 2009}
1962 2010
1963/*****************************************************************************/ 2011/*****************************************************************************/
1964/* working directory stuff */ 2012/* working directory stuff */
2013/* various deficiencies in the posix 2008 api force us to */
2014/* keep the absolute path in string form at all times */
2015/* fuck yeah. */
1965 2016
1966#if HAVE_AT 2017#if !HAVE_AT
1967 2018
1968#define WD2FD(wd) (wd ? ((int)wd) - 1 : AT_FDCWD) 2019/* a bit like realpath, but usually faster because it doesn'T have to return */
1969 2020/* an absolute or canonical path */
1970eio_wd
1971eio_wd_open_sync (eio_wd wd, const char *path)
1972{
1973 int fd = openat (WD2FD (wd), path, O_CLOEXEC | O_SEARCH | O_DIRECTORY);
1974
1975 return fd >= 0 ? (eio_wd)(fd + 1) : EIO_INVALID_WD;
1976}
1977
1978void
1979eio_wd_close_sync (eio_wd wd)
1980{
1981 int fd = WD2FD (wd);
1982
1983 if (fd >= 0)
1984 close (fd);
1985}
1986
1987#else
1988
1989/* on legacy systems, we represent the working directories simply by their path strings */
1990
1991static const char * 2021static const char *
1992wd_expand (struct tmpbuf *tmpbuf, eio_wd wd, const char *path) 2022wd_expand (struct tmpbuf *tmpbuf, eio_wd wd, const char *path)
1993{ 2023{
1994 if (!wd || *path == '/') 2024 if (!wd || *path == '/')
1995 return path; 2025 return path;
1996 2026
2027 if (path [0] == '.' && !path [1])
2028 return wd->str;
2029
1997 { 2030 {
1998 int l1 = strlen ((const char *)wd); 2031 int l1 = wd->len;
1999 int l2 = strlen (path); 2032 int l2 = strlen (path);
2000 2033
2001 char *res = tmpbuf_get (tmpbuf, l1 + l2 + 2); 2034 char *res = tmpbuf_get (tmpbuf, l1 + l2 + 2);
2002 2035
2003 memcpy (res, wd, l1); 2036 memcpy (res, wd->str, l1);
2004 res [l1] = '/'; 2037 res [l1] = '/';
2005 memcpy (res + l1 + 1, path, l2 + 1); 2038 memcpy (res + l1 + 1, path, l2 + 1);
2006 2039
2007 return res; 2040 return res;
2008 } 2041 }
2009} 2042}
2010 2043
2011eio_wd 2044#endif
2045
2046static eio_wd
2012eio__wd_open_sync (struct tmpbuf *tmpbuf, eio_wd wd, const char *path) 2047eio__wd_open_sync (struct tmpbuf *tmpbuf, eio_wd wd, const char *path)
2013{ 2048{
2014 if (*path == '/') /* absolute paths ignore wd */ 2049 int fd;
2015 path = strdup (path); 2050 eio_wd res;
2016 else if (path [0] == '.' && !path [1]) /* special case '.', as it is common */
2017 return wd;
2018 else
2019 {
2020 int len = eio__realpath (tmpbuf, wd, path); 2051 int len = eio__realpath (tmpbuf, wd, path);
2021 2052
2022 path = EIO_INVALID_WD;
2023
2024 if (len >= 0) 2053 if (len < 0)
2025 {
2026 ((char *)tmpbuf->ptr)[len] = 0;
2027 path = strdup (tmpbuf->ptr);
2028 }
2029 }
2030
2031 if (!path)
2032 path = EIO_INVALID_WD; 2054 return EIO_INVALID_WD;
2033 2055
2034 return (eio_wd)path; 2056#if HAVE_AT
2057 fd = openat (WD2FD (wd), path, O_CLOEXEC | O_SEARCH | O_DIRECTORY);
2058
2059 if (fd < 0)
2060 return EIO_INVALID_WD;
2061#endif
2062
2063 res = malloc (sizeof (*res) + len); /* one extra 0-byte */
2064
2065#if HAVE_AT
2066 res->fd = fd;
2067#endif
2068
2069 res->len = len;
2070 memcpy (res->str, tmpbuf->ptr, len);
2071 res->str [len] = 0;
2072
2073 return res;
2035} 2074}
2036 2075
2037eio_wd 2076eio_wd
2038eio_wd_open_sync (eio_wd wd, const char *path) 2077eio_wd_open_sync (eio_wd wd, const char *path)
2039{ 2078{
2045} 2084}
2046 2085
2047void 2086void
2048eio_wd_close_sync (eio_wd wd) 2087eio_wd_close_sync (eio_wd wd)
2049{ 2088{
2050 if (wd != EIO_INVALID_WD) 2089 if (wd != EIO_INVALID_WD && wd != EIO_CWD)
2090 {
2091 #if HAVE_AT
2092 close (wd->fd);
2093 #endif
2051 free (wd); 2094 free (wd);
2095 }
2096}
2097
2098#if HAVE_AT
2099
2100/* they forgot these */
2101
2102static int
2103eio__truncateat (int dirfd, const char *path, off_t length)
2104{
2105 int fd = openat (dirfd, path, O_WRONLY | O_CLOEXEC);
2106 int res;
2107
2108 if (fd < 0)
2109 return fd;
2110
2111 res = ftruncate (fd, length);
2112 close (fd);
2113 return res;
2114}
2115
2116static int
2117eio__statvfsat (int dirfd, const char *path, struct statvfs *buf)
2118{
2119 int fd = openat (dirfd, path, O_SEARCH | O_CLOEXEC);
2120 int res;
2121
2122 if (fd < 0)
2123 return fd;
2124
2125 res = fstatvfs (fd, buf);
2126 close (fd);
2127 return res;
2128
2052} 2129}
2053 2130
2054#endif 2131#endif
2055 2132
2056/*****************************************************************************/ 2133/*****************************************************************************/
2068 req->result = -1; \ 2145 req->result = -1; \
2069 break; \ 2146 break; \
2070 } \ 2147 } \
2071 } 2148 }
2072 2149
2150static void ecb_noinline ecb_cold
2151etp_proc_init (void)
2152{
2153#if HAVE_PRCTL_SET_NAME
2154 /* provide a more sensible "thread name" */
2155 char name[16 + 1];
2156 const int namelen = sizeof (name) - 1;
2157 int len;
2158
2159 prctl (PR_GET_NAME, (unsigned long)name, 0, 0, 0);
2160 name [namelen] = 0;
2161 len = strlen (name);
2162 strcpy (name + (len <= namelen - 4 ? len : namelen - 4), "/eio");
2163 prctl (PR_SET_NAME, (unsigned long)name, 0, 0, 0);
2164#endif
2165}
2166
2073X_THREAD_PROC (etp_proc) 2167X_THREAD_PROC (etp_proc)
2074{ 2168{
2075 ETP_REQ *req; 2169 ETP_REQ *req;
2076 struct timespec ts; 2170 struct timespec ts;
2077 etp_worker *self = (etp_worker *)thr_arg; 2171 etp_worker *self = (etp_worker *)thr_arg;
2078 2172
2079#if HAVE_PRCTL_SET_NAME 2173 etp_proc_init ();
2080 prctl (PR_SET_NAME, (unsigned long)"eio_thread", 0, 0, 0);
2081#endif
2082 2174
2083 /* try to distribute timeouts somewhat evenly */ 2175 /* try to distribute timeouts somewhat evenly */
2084 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL); 2176 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
2085 2177
2086 for (;;) 2178 for (;;)
2148 free (req); 2240 free (req);
2149 2241
2150 X_LOCK (wrklock); 2242 X_LOCK (wrklock);
2151 etp_worker_free (self); 2243 etp_worker_free (self);
2152 X_UNLOCK (wrklock); 2244 X_UNLOCK (wrklock);
2153
2154 return 0;
2155} 2245}
2156 2246
2157/*****************************************************************************/ 2247/*****************************************************************************/
2158 2248
2159int ecb_cold 2249int ecb_cold
2231 switch (req->type) 2321 switch (req->type)
2232 { 2322 {
2233 case EIO_WD_OPEN: req->wd = eio__wd_open_sync (&self->tmpbuf, req->wd, req->ptr1); 2323 case EIO_WD_OPEN: req->wd = eio__wd_open_sync (&self->tmpbuf, req->wd, req->ptr1);
2234 req->result = req->wd == EIO_INVALID_WD ? -1 : 0; 2324 req->result = req->wd == EIO_INVALID_WD ? -1 : 0;
2235 break; 2325 break;
2326 case EIO_WD_CLOSE: req->result = 0;
2327 eio_wd_close_sync (req->wd); break;
2328
2236 case EIO_WD_CLOSE: eio_wd_close_sync (req->wd); break; 2329 case EIO_SEEK: eio__lseek (req); break;
2237
2238 case EIO_READ: ALLOC (req->size); 2330 case EIO_READ: ALLOC (req->size);
2239 req->result = req->offs >= 0 2331 req->result = req->offs >= 0
2240 ? pread (req->int1, req->ptr2, req->size, req->offs) 2332 ? pread (req->int1, req->ptr2, req->size, req->offs)
2241 : read (req->int1, req->ptr2, req->size); break; 2333 : read (req->int1, req->ptr2, req->size); break;
2242 case EIO_WRITE: req->result = req->offs >= 0 2334 case EIO_WRITE: req->result = req->offs >= 0
2245 2337
2246 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break; 2338 case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break;
2247 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break; 2339 case EIO_SENDFILE: req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;
2248 2340
2249#if HAVE_AT 2341#if HAVE_AT
2250 case EIO_GETPATH: abort (); 2342
2251 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2343 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2252 req->result = fstatat (dirfd, path, (EIO_STRUCT_STAT *)req->ptr2); break; 2344 req->result = fstatat (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, 0); break;
2253 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2345 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2254 req->result = lstat (dirfd, path, (EIO_STRUCT_STAT *)req->ptr2); break; 2346 req->result = fstatat (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, AT_SYMLINK_NOFOLLOW); break;
2255#if 0/*D*/ 2347 case EIO_CHOWN: req->result = fchownat (dirfd, req->ptr1, req->int2, req->int3, 0); break;
2348 case EIO_CHMOD: req->result = fchmodat (dirfd, req->ptr1, (mode_t)req->int2, 0); break;
2349 case EIO_TRUNCATE: req->result = eio__truncateat (dirfd, req->ptr1, req->offs); break;
2350 case EIO_OPEN: req->result = openat (dirfd, req->ptr1, req->int1, (mode_t)req->int2); break;
2351
2352 case EIO_UNLINK: req->result = unlinkat (dirfd, req->ptr1, 0); break;
2353 case EIO_RMDIR: req->result = unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break;
2354 case EIO_MKDIR: req->result = mkdirat (dirfd, req->ptr1, (mode_t)req->int2); break;
2355 case EIO_RENAME: req->result = renameat (dirfd, req->ptr1, WD2FD ((eio_wd)req->int3), req->ptr2); break;
2356 case EIO_LINK: req->result = linkat (dirfd, req->ptr1, WD2FD ((eio_wd)req->int3), req->ptr2, 0); break;
2357 case EIO_SYMLINK: req->result = symlinkat (req->ptr1, dirfd, req->ptr2); break;
2358 case EIO_MKNOD: req->result = mknodat (dirfd, req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break;
2359 case EIO_READLINK: ALLOC (PATH_MAX);
2360 req->result = readlinkat (dirfd, req->ptr1, req->ptr2, PATH_MAX); break;
2256 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS)); 2361 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2257 req->result = statvfs (dirfd, path, (EIO_STRUCT_STATVFS *)req->ptr2); break; 2362 req->result = eio__statvfsat (dirfd, req->ptr1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
2258#endif 2363 case EIO_UTIME:
2259 case EIO_CHOWN: req->result = chown (dirfd, path, req->int2, req->int3); break; 2364 case EIO_FUTIME:
2260 case EIO_CHMOD: req->result = chmod (dirfd, path, (mode_t)req->int2); break; 2365 {
2261 case EIO_TRUNCATE: req->result = truncate (dirfd, path, req->offs); break; 2366 struct timespec ts[2];
2262 case EIO_OPEN: req->result = open (dirfd, path, req->int1, (mode_t)req->int2); break; 2367 struct timespec *times;
2263 2368
2264 case EIO_UNLINK: req->result = unlink (dirfd, path); break; 2369 if (req->nv1 != -1. || req->nv2 != -1.)
2265 case EIO_RMDIR: req->result = rmdir (dirfd, path); break; 2370 {
2266 case EIO_MKDIR: req->result = mkdir (dirfd, path, (mode_t)req->int2); break; 2371 ts[0].tv_sec = req->nv1;
2267 case EIO_RENAME: req->result = rename (dirfd, path, req->ptr2); break; 2372 ts[0].tv_nsec = (req->nv1 - ts[0].tv_sec) * 1e9;
2268 case EIO_LINK: req->result = link (dirfd, path, req->ptr2); break; 2373 ts[1].tv_sec = req->nv2;
2269 case EIO_SYMLINK: req->result = symlink (dirfd, path, req->ptr2); break; 2374 ts[1].tv_nsec = (req->nv2 - ts[1].tv_sec) * 1e9;
2270 case EIO_MKNOD: req->result = mknod (dirfd, path, (mode_t)req->int2, (dev_t)req->offs); break; 2375
2376 times = ts;
2377 }
2378 else
2379 times = 0;
2380
2381 req->result = req->type == EIO_FUTIME
2382 ? futimens (req->int1, times)
2383 : utimensat (dirfd, req->ptr1, times, 0);
2384 }
2385 break;
2386
2271#else 2387#else
2388
2272 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2389 case EIO_STAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2273 req->result = stat (path , (EIO_STRUCT_STAT *)req->ptr2); break; 2390 req->result = stat (path , (EIO_STRUCT_STAT *)req->ptr2); break;
2274 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2391 case EIO_LSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2275 req->result = lstat (path , (EIO_STRUCT_STAT *)req->ptr2); break; 2392 req->result = lstat (path , (EIO_STRUCT_STAT *)req->ptr2); break;
2276 case EIO_CHOWN: req->result = chown (path , req->int2, req->int3); break; 2393 case EIO_CHOWN: req->result = chown (path , req->int2, req->int3); break;
2283 case EIO_MKDIR: req->result = mkdir (path , (mode_t)req->int2); break; 2400 case EIO_MKDIR: req->result = mkdir (path , (mode_t)req->int2); break;
2284 case EIO_RENAME: req->result = rename (path , req->ptr2); break; 2401 case EIO_RENAME: req->result = rename (path , req->ptr2); break;
2285 case EIO_LINK: req->result = link (path , req->ptr2); break; 2402 case EIO_LINK: req->result = link (path , req->ptr2); break;
2286 case EIO_SYMLINK: req->result = symlink (path , req->ptr2); break; 2403 case EIO_SYMLINK: req->result = symlink (path , req->ptr2); break;
2287 case EIO_MKNOD: req->result = mknod (path , (mode_t)req->int2, (dev_t)req->offs); break; 2404 case EIO_MKNOD: req->result = mknod (path , (mode_t)req->int2, (dev_t)req->offs); break;
2288
2289 case EIO_READLINK: ALLOC (PATH_MAX); 2405 case EIO_READLINK: ALLOC (PATH_MAX);
2290 req->result = readlink (path, req->ptr2, PATH_MAX); break; 2406 req->result = readlink (path, req->ptr2, PATH_MAX); break;
2407 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2408 req->result = statvfs (path , (EIO_STRUCT_STATVFS *)req->ptr2); break;
2409
2410 case EIO_UTIME:
2411 case EIO_FUTIME:
2412 {
2413 struct timeval tv[2];
2414 struct timeval *times;
2415
2416 if (req->nv1 != -1. || req->nv2 != -1.)
2417 {
2418 tv[0].tv_sec = req->nv1;
2419 tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1e6;
2420 tv[1].tv_sec = req->nv2;
2421 tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1e6;
2422
2423 times = tv;
2424 }
2425 else
2426 times = 0;
2427
2428 req->result = req->type == EIO_FUTIME
2429 ? futimes (req->int1, times)
2430 : utimes (req->ptr1, times);
2431 }
2432 break;
2433
2291#endif 2434#endif
2292 2435
2293 case EIO_REALPATH: if (0 <= (req->result = eio__realpath (&self->tmpbuf, req->wd, req->ptr1))) 2436 case EIO_REALPATH: if (0 <= (req->result = eio__realpath (&self->tmpbuf, req->wd, req->ptr1)))
2294 { 2437 {
2295 ALLOC (req->result); 2438 ALLOC (req->result);
2296 memcpy (req->ptr2, self->tmpbuf.ptr, req->result); 2439 memcpy (req->ptr2, self->tmpbuf.ptr, req->result);
2297 } 2440 }
2298 break; 2441 break;
2299
2300 case EIO_STATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS)); /*D*/
2301 req->result = statvfs (path , (EIO_STRUCT_STATVFS *)req->ptr2); break;
2302 2442
2303 case EIO_FSTAT: ALLOC (sizeof (EIO_STRUCT_STAT)); 2443 case EIO_FSTAT: ALLOC (sizeof (EIO_STRUCT_STAT));
2304 req->result = fstat (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break; 2444 req->result = fstat (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;
2305 2445
2306 case EIO_FSTATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS)); 2446 case EIO_FSTATVFS: ALLOC (sizeof (EIO_STRUCT_STATVFS));
2321 case EIO_MTOUCH: req->result = eio__mtouch (req); break; 2461 case EIO_MTOUCH: req->result = eio__mtouch (req); break;
2322 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break; 2462 case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break;
2323 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break; 2463 case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break;
2324 case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break; 2464 case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break;
2325 2465
2326 case EIO_READDIR: eio__scandir (req); break; 2466 case EIO_READDIR: eio__scandir (req, self); break;
2327 2467
2328 case EIO_BUSY: 2468 case EIO_BUSY:
2329#ifdef _WIN32 2469#ifdef _WIN32
2330 Sleep (req->nv1 * 1e3); 2470 Sleep (req->nv1 * 1e3);
2331#else 2471#else
2338 req->result = select (0, 0, 0, 0, &tv); 2478 req->result = select (0, 0, 0, 0, &tv);
2339 } 2479 }
2340#endif 2480#endif
2341 break; 2481 break;
2342 2482
2343 case EIO_UTIME:
2344 case EIO_FUTIME:
2345 {
2346 struct timeval tv[2];
2347 struct timeval *times;
2348
2349 if (req->nv1 != -1. || req->nv2 != -1.)
2350 {
2351 tv[0].tv_sec = req->nv1;
2352 tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1000000.;
2353 tv[1].tv_sec = req->nv2;
2354 tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1000000.;
2355
2356 times = tv;
2357 }
2358 else
2359 times = 0;
2360
2361 req->result = req->type == EIO_FUTIME
2362 ? futimes (req->int1, times)
2363 : utimes (req->ptr1, times);
2364 }
2365 break;
2366
2367 case EIO_GROUP: 2483 case EIO_GROUP:
2368 abort (); /* handled in eio_request */ 2484 abort (); /* handled in eio_request */
2369 2485
2370 case EIO_NOP: 2486 case EIO_NOP:
2371 req->result = 0; 2487 req->result = 0;
2374 case EIO_CUSTOM: 2490 case EIO_CUSTOM:
2375 req->feed (req); 2491 req->feed (req);
2376 break; 2492 break;
2377 2493
2378 default: 2494 default:
2379 errno = ENOSYS;
2380 req->result = -1; 2495 req->result = EIO_ENOSYS ();
2381 break; 2496 break;
2382 } 2497 }
2383 2498
2384 req->errorno = errno; 2499 req->errorno = errno;
2385} 2500}
2386 2501
2387#ifndef EIO_NO_WRAPPERS 2502#ifndef EIO_NO_WRAPPERS
2388 2503
2504eio_req *eio_wd_open (const char *path, int pri, eio_cb cb, void *data)
2505{
2506 REQ (EIO_WD_OPEN); PATH; SEND;
2507}
2508
2509eio_req *eio_wd_close (eio_wd wd, int pri, eio_cb cb, void *data)
2510{
2511 REQ (EIO_WD_CLOSE); req->wd = wd; SEND;
2512}
2513
2389eio_req *eio_nop (int pri, eio_cb cb, void *data) 2514eio_req *eio_nop (int pri, eio_cb cb, void *data)
2390{ 2515{
2391 REQ (EIO_NOP); SEND; 2516 REQ (EIO_NOP); SEND;
2392} 2517}
2393 2518
2452} 2577}
2453 2578
2454eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data) 2579eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data)
2455{ 2580{
2456 REQ (EIO_READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND; 2581 REQ (EIO_READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND;
2582}
2583
2584eio_req *eio_seek (int fd, off_t offset, int whence, int pri, eio_cb cb, void *data)
2585{
2586 REQ (EIO_SEEK); req->int1 = fd; req->offs = offset; req->int2 = whence; SEND;
2457} 2587}
2458 2588
2459eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data) 2589eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data)
2460{ 2590{
2461 REQ (EIO_READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND; 2591 REQ (EIO_READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines