URI:
       t9dir.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       t9dir.c (2202B)
       ---
            1 #include "stdinc.h"
            2 
            3 #include "9.h"
            4 
            5 /* one entry buffer for reading directories */
            6 struct DirBuf {
            7         DirEntryEnum*        dee;
            8         int                valid;
            9         DirEntry        de;
           10 };
           11 
           12 static DirBuf*
           13 dirBufAlloc(File* file)
           14 {
           15         DirBuf *db;
           16 
           17         db = vtmallocz(sizeof(DirBuf));
           18         db->dee = deeOpen(file);
           19         if(db->dee == nil){
           20                 /* can happen if dir is removed from under us */
           21                 vtfree(db);
           22                 return nil;
           23         }
           24         return db;
           25 }
           26 
           27 void
           28 dirBufFree(DirBuf* db)
           29 {
           30         if(db == nil)
           31                 return;
           32 
           33         if(db->valid)
           34                 deCleanup(&db->de);
           35         deeClose(db->dee);
           36         vtfree(db);
           37 }
           38 
           39 int
           40 dirDe2M(DirEntry* de, uchar* p, int np)
           41 {
           42         int n;
           43         Dir dir;
           44 
           45         memset(&dir, 0, sizeof(Dir));
           46 
           47         dir.qid.path = de->qid;
           48         dir.qid.vers = de->mcount;
           49         dir.mode = de->mode & 0777;
           50         if(de->mode & ModeAppend){
           51                 dir.qid.type |= QTAPPEND;
           52                 dir.mode |= DMAPPEND;
           53         }
           54         if(de->mode & ModeExclusive){
           55                 dir.qid.type |= QTEXCL;
           56                 dir.mode |= DMEXCL;
           57         }
           58         if(de->mode & ModeDir){
           59                 dir.qid.type |= QTDIR;
           60                 dir.mode |= DMDIR;
           61         }
           62         if(de->mode & ModeSnapshot){
           63                 dir.qid.type |= QTMOUNT;        /* just for debugging */
           64                 dir.mode |= DMMOUNT;
           65         }
           66         if(de->mode & ModeTemporary){
           67                 dir.qid.type |= QTTMP;
           68                 dir.mode |= DMTMP;
           69         }
           70 
           71         dir.atime = de->atime;
           72         dir.mtime = de->mtime;
           73         dir.length = de->size;
           74 
           75         dir.name = de->elem;
           76         if((dir.uid = unameByUid(de->uid)) == nil)
           77                 dir.uid = smprint("(%s)", de->uid);
           78         if((dir.gid = unameByUid(de->gid)) == nil)
           79                 dir.gid = smprint("(%s)", de->gid);
           80         if((dir.muid = unameByUid(de->mid)) == nil)
           81                 dir.muid = smprint("(%s)", de->mid);
           82 
           83         n = convD2M(&dir, p, np);
           84 
           85         vtfree(dir.muid);
           86         vtfree(dir.gid);
           87         vtfree(dir.uid);
           88 
           89         return n;
           90 }
           91 
           92 int
           93 dirRead(Fid* fid, uchar* p, int count, vlong offset)
           94 {
           95         int n, nb;
           96         DirBuf *db;
           97 
           98         /*
           99          * special case of rewinding a directory
          100          * otherwise ignore the offset
          101          */
          102         if(offset == 0 && fid->db){
          103                 dirBufFree(fid->db);
          104                 fid->db = nil;
          105         }
          106 
          107         if(fid->db == nil){
          108                 fid->db = dirBufAlloc(fid->file);
          109                 if(fid->db == nil)
          110                         return -1;
          111         }
          112 
          113         db = fid->db;
          114 
          115         for(nb = 0; nb < count; nb += n){
          116                 if(!db->valid){
          117                         n = deeRead(db->dee, &db->de);
          118                         if(n < 0)
          119                                 return -1;
          120                         if(n == 0)
          121                                 break;
          122                         db->valid = 1;
          123                 }
          124                 n = dirDe2M(&db->de, p+nb, count-nb);
          125                 if(n <= BIT16SZ)
          126                         break;
          127                 db->valid = 0;
          128                 deCleanup(&db->de);
          129         }
          130 
          131         return nb;
          132 }