From fd22a0ee205cedb8626f1c015b0eca604d365689 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 17 Jul 2011 04:20:04 +0000 Subject: initial windows support --- eio.c | 170 +++++++++++++++++++++++++++++++++++++++++------------------------- eio.h | 20 +++++--- 2 files changed, 119 insertions(+), 71 deletions(-) diff --git a/eio.c b/eio.c index 74f73b8..7a6d9bb 100644 --- a/eio.c +++ b/eio.c @@ -113,6 +113,9 @@ static void eio_destroy (eio_req *req); #define link(old,neu) (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1)) #define chmod(path,mode) _chmod (path, mode) + #define dup(fd) _dup (fd) + #define dup2(fd1,fd2) _dup2 (fd1, fd2) + #define fchmod(fd,mode) EIO_ENOSYS () #define chown(path,uid,gid) EIO_ENOSYS () #define fchown(fd,uid,gid) EIO_ENOSYS () @@ -140,7 +143,7 @@ static void eio_destroy (eio_req *req); } /* POSIX API only */ - #define CreateHardLink(neu,old) 0 + #define CreateHardLink(neu,old,flags) 0 #define CreateSymbolicLink(neu,old,flags) 0 struct statvfs @@ -148,6 +151,11 @@ static void eio_destroy (eio_req *req); int dummy; }; + #define DT_DIR EIO_DT_DIR + #define DT_REG EIO_DT_REG + #define D_NAME(entp) entp.cFileName + #define D_TYPE(entp) (entp.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? DT_DIR : DT_REG) + #else #include @@ -162,6 +170,8 @@ static void eio_destroy (eio_req *req); #include #endif + #define D_NAME(entp) entp->d_name + /* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */ #if __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ #define _DIRENT_HAVE_D_TYPE /* sigh */ @@ -208,7 +218,7 @@ static void eio_destroy (eio_req *req); # define D_INO(de) 0 #endif #ifndef D_NAMLEN -# define D_NAMLEN(de) strlen ((de)->d_name) +# define D_NAMLEN(entp) strlen (D_NAME (entp)) #endif /* used for struct dirent, AIX doesn't provide it */ @@ -252,17 +262,10 @@ static void eio_execute (struct etp_worker *self, eio_req *req); { \ free (wrk->dbuf); \ wrk->dbuf = 0; \ - } \ - \ - if (wrk->dirp) \ - { \ - closedir (wrk->dirp); \ - wrk->dirp = 0; \ } #define ETP_WORKER_COMMON \ - void *dbuf; \ - DIR *dirp; + void *dbuf; /*****************************************************************************/ @@ -398,6 +401,17 @@ typedef struct { static etp_reqq req_queue; static etp_reqq res_queue; +static void ecb_noinline ecb_cold +reqq_init (etp_reqq *q) +{ + int pri; + + for (pri = 0; pri < ETP_NUM_PRI; ++pri) + q->qs[pri] = q->qe[pri] = 0; + + q->size = 0; +} + static int ecb_noinline reqq_push (etp_reqq *q, ETP_REQ *req) { @@ -453,37 +467,14 @@ etp_thread_init (void) X_COND_CREATE (reqwait); } -static void ecb_cold -etp_atfork_prepare (void) -{ -} - -static void ecb_cold -etp_atfork_parent (void) -{ -} - static void ecb_cold etp_atfork_child (void) { - ETP_REQ *prv; - - while ((prv = reqq_shift (&req_queue))) - ETP_DESTROY (prv); - - while ((prv = reqq_shift (&res_queue))) - ETP_DESTROY (prv); - - while (wrk_first.next != &wrk_first) - { - etp_worker *wrk = wrk_first.next; - - if (wrk->req) - ETP_DESTROY (wrk->req); + reqq_init (&req_queue); + reqq_init (&res_queue); - etp_worker_clear (wrk); - etp_worker_free (wrk); - } + wrk_first.next = + wrk_first.prev = &wrk_first; started = 0; idle = 0; @@ -498,7 +489,7 @@ static void ecb_cold etp_once_init (void) { etp_thread_init (); - X_THREAD_ATFORK (etp_atfork_prepare, etp_atfork_parent, etp_atfork_child); + X_THREAD_ATFORK (0, 0, etp_atfork_child); } static int ecb_cold @@ -1485,9 +1476,9 @@ eio_dent_cmp (const eio_dirent *a, const eio_dirent *b) #define EIO_SORT_FAST 60 /* when to only use insertion sort */ static void -eio_dent_radix_sort (eio_dirent *dents, int size, signed char score_bits, ino_t inode_bits) +eio_dent_radix_sort (eio_dirent *dents, int size, signed char score_bits, eio_ino_t inode_bits) { - unsigned char bits [9 + sizeof (ino_t) * 8]; + unsigned char bits [9 + sizeof (eio_ino_t) * 8]; unsigned char *bit = bits; assert (CHAR_BIT == 8); @@ -1499,27 +1490,27 @@ eio_dent_radix_sort (eio_dirent *dents, int size, signed char score_bits, ino_t return; /* first prepare an array of bits to test in our radix sort */ - /* try to take endianness into account, as well as differences in ino_t sizes */ + /* try to take endianness into account, as well as differences in eio_ino_t sizes */ /* inode_bits must contain all inodes ORed together */ /* which is used to skip bits that are 0 everywhere, which is very common */ { - ino_t endianness; + eio_ino_t endianness; int i, j; /* we store the byte offset of byte n into byte n of "endianness" */ - for (i = 0; i < sizeof (ino_t); ++i) + for (i = 0; i < sizeof (eio_ino_t); ++i) ((unsigned char *)&endianness)[i] = i; *bit++ = 0; - for (i = 0; i < sizeof (ino_t); ++i) + for (i = 0; i < sizeof (eio_ino_t); ++i) { /* shifting off the byte offsets out of "endianness" */ int offs = (offsetof (eio_dirent, inode) + (endianness & 0xff)) * 8; endianness >>= 8; for (j = 0; j < 8; ++j) - if (inode_bits & (((ino_t)1) << (i * 8 + j))) + if (inode_bits & (((eio_ino_t)1) << (i * 8 + j))) *bit++ = offs + j; } @@ -1530,9 +1521,9 @@ eio_dent_radix_sort (eio_dirent *dents, int size, signed char score_bits, ino_t /* now actually do the sorting (a variant of MSD radix sort) */ { - eio_dirent *base_stk [9 + sizeof (ino_t) * 8], *base; - eio_dirent *end_stk [9 + sizeof (ino_t) * 8], *end; - unsigned char *bit_stk [9 + sizeof (ino_t) * 8]; + eio_dirent *base_stk [9 + sizeof (eio_ino_t) * 8], *base; + eio_dirent *end_stk [9 + sizeof (eio_ino_t) * 8], *end; + unsigned char *bit_stk [9 + sizeof (eio_ino_t) * 8]; int stk_idx = 0; base_stk [stk_idx] = dents; @@ -1621,7 +1612,7 @@ eio_dent_insertion_sort (eio_dirent *dents, int size) } static void -eio_dent_sort (eio_dirent *dents, int size, signed char score_bits, ino_t inode_bits) +eio_dent_sort (eio_dirent *dents, int size, signed char score_bits, eio_ino_t inode_bits) { if (size <= 1) return; /* our insertion sort relies on size > 0 */ @@ -1639,25 +1630,61 @@ eio_dent_sort (eio_dirent *dents, int size, signed char score_bits, ino_t inode_ static void eio__scandir (eio_req *req, etp_worker *self) { - DIR *dirp; - EIO_STRUCT_DIRENT *entp; char *name, *names; - int namesalloc = 4096; + int namesalloc = 4096 - sizeof (void *) * 4; int namesoffs = 0; int flags = req->int1; eio_dirent *dents = 0; int dentalloc = 128; int dentoffs = 0; - ino_t inode_bits = 0; + eio_ino_t inode_bits = 0; +#ifdef _WIN32 + HANDLE dirp; + WIN32_FIND_DATA entp; +#else + DIR *dirp; + EIO_STRUCT_DIRENT *entp; +#endif req->result = -1; if (!(flags & EIO_READDIR_DENTS)) flags &= ~(EIO_READDIR_DIRS_FIRST | EIO_READDIR_STAT_ORDER); - X_LOCK (wrklock); - /* the corresponding closedir is in ETP_WORKER_CLEAR */ - self->dirp = dirp = opendir (req->ptr1); +#ifdef _WIN32 + { + char *path = malloc (MAX_PATH); + _snprintf (path, MAX_PATH, "%s/*", (const char *)req->ptr1); + dirp = FindFirstFile (path, &entp); + free (path); + + if (!dirp) + { + switch (GetLastError ()) + { + case ERROR_FILE_NOT_FOUND: + req->result = 0; + break; + + case ERROR_PATH_NOT_FOUND: + case ERROR_NO_MORE_FILES: + errno = ENOENT; + break; + + case ERROR_NOT_ENOUGH_MEMORY: + errno = ENOMEM; + break; + + default: + errno = EINVAL; + break; + } + + } + } +#else + dirp = opendir (req->ptr1); +#endif if (req->flags & EIO_FLAG_PTR1_FREE) free (req->ptr1); @@ -1665,18 +1692,30 @@ eio__scandir (eio_req *req, etp_worker *self) req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; req->ptr2 = names = malloc (namesalloc); - X_UNLOCK (wrklock); if (dirp && names && (!flags || dents)) for (;;) { + int more; + +#ifdef _WIN32 + more = dirp; +#else errno = 0; entp = readdir (dirp); + more = entp; +#endif - if (!entp) + if (!more) { +#ifndef _WIN32 + int old_errno = errno; + closedir (dirp); + errno = old_errno; + if (errno) break; +#endif /* sort etc. */ req->int1 = flags; @@ -1715,7 +1754,7 @@ eio__scandir (eio_req *req, etp_worker *self) } /* now add the entry to our list(s) */ - name = entp->d_name; + name = D_NAME (entp); /* skip . and .. entries */ if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2]))) @@ -1725,9 +1764,7 @@ eio__scandir (eio_req *req, etp_worker *self) while (ecb_expect_false (namesoffs + len > namesalloc)) { namesalloc *= 2; - X_LOCK (wrklock); req->ptr2 = names = realloc (names, namesalloc); - X_UNLOCK (wrklock); if (!names) break; @@ -1742,9 +1779,7 @@ eio__scandir (eio_req *req, etp_worker *self) if (ecb_expect_false (dentoffs == dentalloc)) { dentalloc *= 2; - X_LOCK (wrklock); req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent)); - X_UNLOCK (wrklock); if (!dents) break; @@ -1834,6 +1869,14 @@ eio__scandir (eio_req *req, etp_worker *self) errno = ECANCELED; break; } + +#ifdef _WIN32 + if (!FindNextFile (dirp, &entp)) + { + FindClose (dirp); + dirp = 0; + } +#endif } } @@ -1859,7 +1902,6 @@ X_THREAD_PROC (etp_proc) ETP_REQ *req; struct timespec ts; etp_worker *self = (etp_worker *)thr_arg; - int timeout; /* try to distribute timeouts somewhat evenly */ ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL); diff --git a/eio.h b/eio.h index 585345b..15c0182 100644 --- a/eio.h +++ b/eio.h @@ -67,13 +67,19 @@ typedef int (*eio_cb)(eio_req *req); #endif #ifdef _WIN32 -typedef int eio_uid_t; -typedef int eio_gid_t; -typedef intptr_t eio_ssize_t; /* or SSIZE_T */ + typedef int eio_uid_t; + typedef int eio_gid_t; + typedef intptr_t eio_ssize_t; /* or SSIZE_T */ + #if __GNUC__ + typedef long long eio_ino_t; + #else + typedef __int64 eio_ino_t; /* unsigned not supported by msvc */ + #endif #else -typedef uid_t eio_uid_t; -typedef gid_t eio_gid_t; -typedef ssize_t eio_ssize_t; + typedef uid_t eio_uid_t; + typedef gid_t eio_gid_t; + typedef ssize_t eio_ssize_t; + typedef ino_t eio_ino_t; #endif #ifndef EIO_STRUCT_STATVFS @@ -122,7 +128,7 @@ struct eio_dirent unsigned short namelen; /* size of filename without trailing 0 */ unsigned char type; /* one of EIO_DT_* */ signed char score; /* internal use */ - ino_t inode; /* the inode number, if available, otherwise unspecified */ + eio_ino_t inode; /* the inode number, if available, otherwise unspecified */ }; /* eio_msync flags */ -- cgit v1.2.3