summaryrefslogtreecommitdiff
path: root/lib9/dirstat-posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9/dirstat-posix.c')
-rw-r--r--lib9/dirstat-posix.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/lib9/dirstat-posix.c b/lib9/dirstat-posix.c
new file mode 100644
index 00000000..8925b6da
--- /dev/null
+++ b/lib9/dirstat-posix.c
@@ -0,0 +1,79 @@
+#include "lib9.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+
+static char nullstring[] = "";
+static char Enovmem[] = "out of memory";
+
+static Dir*
+statconv(struct stat *s, char *name)
+{
+ struct passwd *p;
+ struct group *g;
+ Dir *dir;
+ int str;
+ char *n;
+
+ str = 0;
+ p = getpwuid(s->st_uid);
+ if(p)
+ str += strlen(p->pw_name)+1;
+ g = getgrgid(s->st_gid);
+ if(g)
+ str += strlen(g->gr_name)+1;
+ dir = malloc(sizeof(Dir)+str);
+ if(dir == nil){
+ werrstr(Enovmem);
+ return nil;
+ }
+ n = (char*)dir+sizeof(Dir);
+ dir->name = name;
+ dir->uid = dir->gid = dir->muid = nullstring;
+ if(p){
+ dir->uid = n;
+ strcpy(n, p->pw_name);
+ n += strlen(p->pw_name)+1;
+ }
+ if(g){
+ dir->gid = n;
+ strcpy(n, g->gr_name);
+ }
+ dir->qid.type = S_ISDIR(s->st_mode)? QTDIR: QTFILE;
+ dir->qid.path = s->st_ino;
+ dir->qid.vers = s->st_mtime;
+ dir->mode = (dir->qid.type<<24)|(s->st_mode&0777);
+ dir->atime = s->st_atime;
+ dir->mtime = s->st_mtime;
+ dir->length = s->st_size;
+ dir->dev = s->st_dev;
+ dir->type = S_ISFIFO(s->st_mode)? '|': 'M';
+ return dir;
+}
+
+Dir*
+dirfstat(int fd)
+{
+ struct stat sbuf;
+
+ if(fstat(fd, &sbuf) < 0)
+ return nil;
+ return statconv(&sbuf, nullstring);
+}
+
+Dir*
+dirstat(char *f)
+{
+ struct stat sbuf;
+ char *p;
+
+ if(stat(f, &sbuf) < 0)
+ return nil;
+ p = strrchr(f, '/');
+ if(p)
+ p++;
+ else
+ p = nullstring;
+ return statconv(&sbuf, p);
+}