From 1a01097f12bd9cd363a2c3831c3d6ac328816523 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 6 Jun 2009 18:06:55 +0000 Subject: *** empty log message *** --- Changes | 4 +++- eio.c | 48 ++++++++++++++++++++++++++++-------------------- eio.h | 2 +- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/Changes b/Changes index a8d690d..55fe525 100644 --- a/Changes +++ b/Changes @@ -3,7 +3,9 @@ Revision history for libeio TODO: maybe add mincore support? available on at leats darwin, solaris, linux, freebsd 1.0 - - readdir: corretcly set errno to ENOMEM when OOM. + - readdir: correctly handle malloc failures. + - readdir: new flags argument, can return inode + and possibly filetype, can sort in various ways. - added EIO_STACKSIZE. - added msync, mtouch support (untested). - added sync_file_range (untested). diff --git a/eio.c b/eio.c index ddcd296..f4516d1 100644 --- a/eio.c +++ b/eio.c @@ -180,6 +180,7 @@ static void eio_execute (struct etp_worker *self, eio_req *req); closedir (wrk->dirp); \ wrk->dirp = 0; \ } + #define ETP_WORKER_COMMON \ void *dbuf; \ DIR *dirp; @@ -1012,13 +1013,11 @@ eio__scandir (eio_req *req, etp_worker *self) 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); req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; req->ptr1 = names = malloc (namesalloc); req->ptr2 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; - X_UNLOCK (wrklock); if (dirp && names && (!flags || dents)) @@ -1036,12 +1035,21 @@ eio__scandir (eio_req *req, etp_worker *self) req->int1 = flags; req->result = dentoffs; - if (flags & EIO_READDIR_STAT_ORDER || !(~flags & (EIO_READDIR_DIRS_FIRST | EIO_READDIR_FOUND_UNKNOWN)) + if (dents) + { + eio_dirent *ent = dents + dentoffs; + + while (ent > dents) + (--ent)->name = names + (size_t)ent->name; + } + + if (flags & EIO_READDIR_STAT_ORDER + || !(~flags & (EIO_READDIR_DIRS_FIRST | EIO_READDIR_FOUND_UNKNOWN))) { /* pray your qsort doesn't use quicksort */ qsort (dents, dentoffs, sizeof (*dents), eio_dent_cmp); /* score depends of DIRS_FIRST */ } - else if (flags & EIO_READDIR_DIRS_FIRST && !(flags & EIO_READDIR_FOUND_UNKNOWN)) + else if (flags & EIO_READDIR_DIRS_FIRST) { /* in this case, all is known, and we just put dirs first and sort them */ eio_dirent *ent = dents + dentoffs; @@ -1070,13 +1078,23 @@ eio__scandir (eio_req *req, etp_worker *self) qsort (dents, dir - dents, sizeof (*dents), eio_dent_cmp); } - {int i; for(i=0;iinode,e->score,e->name);}}//D + /* only provide the names array unless DENTS is specified */ + if (!(flags & EIO_READDIR_DENTS)) + { + X_LOCK (wrklock); + assert (!dents); + req->ptr1 = 0; + req->ptr2 = names; + X_UNLOCK (wrklock); + } break; } + /* now add the entry to our list(s) */ name = entp->d_name; + /* skip . and .. entries */ if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2]))) { int len = strlen (name) + 1; @@ -1111,7 +1129,7 @@ eio__scandir (eio_req *req, etp_worker *self) ent = dents + dentoffs; - ent->name = names + namesoffs; + ent->name = (char *)(size_t)namesoffs; /* rather dirtily we store the offset in the pointer */ ent->namelen = len - 1; ent->inode = D_INO (entp); @@ -1128,16 +1146,16 @@ eio__scandir (eio_req *req, etp_worker *self) #ifdef DT_CHR case DT_CHR: ent->type = EIO_DT_CHR; break; #endif - #ifdef DT_DIR + #ifdef DT_DIR case DT_DIR: ent->type = EIO_DT_DIR; break; #endif - #ifdef DT_BLK + #ifdef DT_BLK case DT_BLK: ent->type = EIO_DT_BLK; break; #endif - #ifdef DT_REG + #ifdef DT_REG case DT_REG: ent->type = EIO_DT_REG; break; #endif - #ifdef DT_LNK + #ifdef DT_LNK case DT_LNK: ent->type = EIO_DT_LNK; break; #endif #ifdef DT_SOCK @@ -1170,16 +1188,6 @@ eio__scandir (eio_req *req, etp_worker *self) } else req->result = -1; - - /* if user doesn't want the dents, do not provide it */ - if (!(flags & EIO_READDIR_DENTS)) - { - X_LOCK (wrklock); - free (dents); - req->ptr2 = req->ptr1; - req->ptr1 = 0; - X_UNLOCK (wrklock); - } } #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO) diff --git a/eio.h b/eio.h index 2ef2a55..c6ca312 100644 --- a/eio.h +++ b/eio.h @@ -137,7 +137,7 @@ struct eio_req ssize_t result; /* result of syscall, e.g. result = read (... */ off_t offs; /* read, write, truncate, readahead, sync_file_range: file offset */ size_t size; /* read, write, readahead, sendfile, msync, sync_file_range: length */ - void *ptr1; /* all applicable requests: pathname, old name */ + void *ptr1; /* all applicable requests: pathname, old name; readdir: possible output memory buffer */ void *ptr2; /* all applicable requests: new name or memory buffer */ eio_tstamp nv1; /* utime, futime: atime; busy: sleep time */ eio_tstamp nv2; /* utime, futime: mtime */ -- cgit v1.2.3