aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/fossil/9dir.c
diff options
context:
space:
mode:
authorDavid du Colombier <0intro@gmail.com>2013-09-23 23:00:39 +0200
committerDavid du Colombier <0intro@gmail.com>2013-09-23 23:00:39 +0200
commit6f4d00ee45693290fae042b27536b54f77b96acd (patch)
tree60ad31bf16ed2000661c02345dd2a63851588a5d /src/cmd/fossil/9dir.c
parentfea86f063930ea187f1c77e93207ac8d39125520 (diff)
downloadplan9port-6f4d00ee45693290fae042b27536b54f77b96acd.tar.gz
plan9port-6f4d00ee45693290fae042b27536b54f77b96acd.tar.bz2
plan9port-6f4d00ee45693290fae042b27536b54f77b96acd.zip
fossil: import from plan 9
R=rsc https://codereview.appspot.com/7988047
Diffstat (limited to 'src/cmd/fossil/9dir.c')
-rw-r--r--src/cmd/fossil/9dir.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/cmd/fossil/9dir.c b/src/cmd/fossil/9dir.c
new file mode 100644
index 00000000..09b483bd
--- /dev/null
+++ b/src/cmd/fossil/9dir.c
@@ -0,0 +1,132 @@
+#include "stdinc.h"
+
+#include "9.h"
+
+/* one entry buffer for reading directories */
+struct DirBuf {
+ DirEntryEnum* dee;
+ int valid;
+ DirEntry de;
+};
+
+static DirBuf*
+dirBufAlloc(File* file)
+{
+ DirBuf *db;
+
+ db = vtMemAllocZ(sizeof(DirBuf));
+ db->dee = deeOpen(file);
+ if(db->dee == nil){
+ /* can happen if dir is removed from under us */
+ vtMemFree(db);
+ return nil;
+ }
+ return db;
+}
+
+void
+dirBufFree(DirBuf* db)
+{
+ if(db == nil)
+ return;
+
+ if(db->valid)
+ deCleanup(&db->de);
+ deeClose(db->dee);
+ vtMemFree(db);
+}
+
+int
+dirDe2M(DirEntry* de, uchar* p, int np)
+{
+ int n;
+ Dir dir;
+
+ memset(&dir, 0, sizeof(Dir));
+
+ dir.qid.path = de->qid;
+ dir.qid.vers = de->mcount;
+ dir.mode = de->mode & 0777;
+ if(de->mode & ModeAppend){
+ dir.qid.type |= QTAPPEND;
+ dir.mode |= DMAPPEND;
+ }
+ if(de->mode & ModeExclusive){
+ dir.qid.type |= QTEXCL;
+ dir.mode |= DMEXCL;
+ }
+ if(de->mode & ModeDir){
+ dir.qid.type |= QTDIR;
+ dir.mode |= DMDIR;
+ }
+ if(de->mode & ModeSnapshot){
+ dir.qid.type |= QTMOUNT; /* just for debugging */
+ dir.mode |= DMMOUNT;
+ }
+ if(de->mode & ModeTemporary){
+ dir.qid.type |= QTTMP;
+ dir.mode |= DMTMP;
+ }
+
+ dir.atime = de->atime;
+ dir.mtime = de->mtime;
+ dir.length = de->size;
+
+ dir.name = de->elem;
+ if((dir.uid = unameByUid(de->uid)) == nil)
+ dir.uid = smprint("(%s)", de->uid);
+ if((dir.gid = unameByUid(de->gid)) == nil)
+ dir.gid = smprint("(%s)", de->gid);
+ if((dir.muid = unameByUid(de->mid)) == nil)
+ dir.muid = smprint("(%s)", de->mid);
+
+ n = convD2M(&dir, p, np);
+
+ vtMemFree(dir.muid);
+ vtMemFree(dir.gid);
+ vtMemFree(dir.uid);
+
+ return n;
+}
+
+int
+dirRead(Fid* fid, uchar* p, int count, vlong offset)
+{
+ int n, nb;
+ DirBuf *db;
+
+ /*
+ * special case of rewinding a directory
+ * otherwise ignore the offset
+ */
+ if(offset == 0 && fid->db){
+ dirBufFree(fid->db);
+ fid->db = nil;
+ }
+
+ if(fid->db == nil){
+ fid->db = dirBufAlloc(fid->file);
+ if(fid->db == nil)
+ return -1;
+ }
+
+ db = fid->db;
+
+ for(nb = 0; nb < count; nb += n){
+ if(!db->valid){
+ n = deeRead(db->dee, &db->de);
+ if(n < 0)
+ return -1;
+ if(n == 0)
+ break;
+ db->valid = 1;
+ }
+ n = dirDe2M(&db->de, p+nb, count-nb);
+ if(n <= BIT16SZ)
+ break;
+ db->valid = 0;
+ deCleanup(&db->de);
+ }
+
+ return nb;
+}