plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

9dir.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 }