diff options
Diffstat (limited to 'src/lib9/_p9dir.c')
-rw-r--r-- | src/lib9/_p9dir.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/lib9/_p9dir.c b/src/lib9/_p9dir.c new file mode 100644 index 00000000..459bd157 --- /dev/null +++ b/src/lib9/_p9dir.c @@ -0,0 +1,121 @@ +#include <u.h> +#define NOPLAN9DEFINES +#include <libc.h> + +#include <sys/stat.h> +#include <sys/disklabel.h> +#include <dirent.h> +#include <pwd.h> +#include <grp.h> + +int +_p9dir(struct stat *st, char *name, Dir *d, char **str, char *estr) +{ + char *s; + char tmp[20]; + struct group *g; + struct passwd *p; + int sz; + + sz = 0; + if(d) + memset(d, 0, sizeof *d); + + /* name */ + s = strrchr(name, '/'); + if(s) + s++; + if(!s || !*s) + s = name; + if(*s == '/') + s++; + if(*s == 0) + s = "/"; + if(d){ + if(*str + strlen(s)+1 > estr) + d->name = "oops"; + else{ + strcpy(*str, s); + d->name = *str; + *str += strlen(*str)+1; + } + } + sz += strlen(s)+1; + + /* user */ + p = getpwuid(st->st_uid); + if(p == nil){ + snprint(tmp, sizeof tmp, "%d", (int)st->st_uid); + s = tmp; + }else + s = p->pw_name; + sz += strlen(s)+1; + if(d){ + if(*str+strlen(s)+1 > estr) + d->uid = "oops"; + else{ + strcpy(*str, s); + d->uid = *str; + *str += strlen(*str)+1; + } + } + + /* group */ + g = getgrgid(st->st_gid); + if(g == nil){ + snprint(tmp, sizeof tmp, "%d", (int)st->st_gid); + s = tmp; + }else + s = g->gr_name; + sz += strlen(s)+1; + if(d){ + if(*str + strlen(s)+1 > estr) + d->gid = "oops"; + else{ + strcpy(*str, s); + d->gid = *str; + *str += strlen(*str)+1; + } + } + + if(d){ + d->type = 'M'; + + d->muid = ""; + d->qid.path = ((uvlong)st->st_dev<<32) | st->st_ino; + d->qid.vers = st->st_gen; + d->mode = st->st_mode&0777; + d->atime = st->st_atime; + d->mtime = st->st_mtime; + d->length = st->st_size; + + if(S_ISDIR(st->st_mode)){ + d->length = 0; + d->mode |= DMDIR; + d->qid.type = QTDIR; + } + + /* fetch real size for disks */ + if(S_ISCHR(st->st_mode)){ + int fd, n; + struct disklabel lab; + + if((fd = open(name, O_RDONLY)) < 0) + goto nosize; + if(ioctl(fd, DIOCGDINFO, &lab) < 0) + goto nosize; + n = minor(st->st_rdev)&7; + if(n >= lab.d_npartitions) + goto nosize; + + d->length = (vlong)(lab.d_partitions[n].p_size) * lab.d_secsize; + + nosize: + if(fd >= 0) + close(fd); + } + } + + return sz; +} + |