--- libeio/eio.c 2009/06/06 17:25:13 1.31 +++ libeio/eio.c 2009/06/06 18:06:55 1.32 @@ -180,6 +180,7 @@ closedir (wrk->dirp); \ wrk->dirp = 0; \ } + #define ETP_WORKER_COMMON \ void *dbuf; \ DIR *dirp; @@ -1012,13 +1013,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ #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 @@ } 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)