Blob
1 #include <u.h>2 #define NOPLAN9DEFINES3 #include <libc.h>5 #include <sys/types.h>6 #include <sys/stat.h>7 #include <dirent.h>8 #include <pwd.h>9 #include <grp.h>11 #if defined(__FreeBSD__)12 #include <sys/disklabel.h>13 static int diskdev[] = {14 151, /* aacd */15 116, /* ad */16 157, /* ar */17 118, /* afd */18 133, /* amrd */19 13, /* da */20 102, /* fla */21 109, /* idad */22 95, /* md */23 131, /* mlxd */24 168, /* pst */25 147, /* twed */26 43, /* vn */27 3, /* wd */28 87, /* wfd */29 };30 static int31 isdisk(struct stat *st)32 {33 int i, dev;35 if(!S_ISCHR(st->st_mode))36 return 0;37 dev = major(st->st_rdev);38 for(i=0; i<nelem(diskdev); i++)39 if(diskdev[i] == dev)40 return 1;41 return 0;42 }43 #define _HAVEDISKLABEL44 #endif46 #if !defined(__linux__) && !defined(__sun__)47 #define _HAVESTGEN48 #endif50 /*51 * Caching the last group and passwd looked up is52 * a significant win (stupidly enough) on most systems.53 * It's not safe for threaded programs, but neither is using54 * getpwnam in the first place, so I'm not too worried.55 */56 int57 _p9dir(struct stat *st, char *name, Dir *d, char **str, char *estr)58 {59 char *s;60 char tmp[20];61 static struct group *g;62 static struct passwd *p;63 static int gid, uid;64 int sz;66 sz = 0;67 if(d)68 memset(d, 0, sizeof *d);70 /* name */71 s = strrchr(name, '/');72 if(s)73 s++;74 if(!s || !*s)75 s = name;76 if(*s == '/')77 s++;78 if(*s == 0)79 s = "/";80 if(d){81 if(*str + strlen(s)+1 > estr)82 d->name = "oops";83 else{84 strcpy(*str, s);85 d->name = *str;86 *str += strlen(*str)+1;87 }88 }89 sz += strlen(s)+1;91 /* user */92 if(p && st->st_uid == uid && p->pw_uid == uid)93 ;94 else{95 p = getpwuid(st->st_uid);96 uid = st->st_uid;97 }98 if(p == nil){99 snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);100 s = tmp;101 }else102 s = p->pw_name;103 sz += strlen(s)+1;104 if(d){105 if(*str+strlen(s)+1 > estr)106 d->uid = "oops";107 else{108 strcpy(*str, s);109 d->uid = *str;110 *str += strlen(*str)+1;111 }112 }114 /* group */115 if(g && st->st_gid == gid && g->gr_gid == gid)116 ;117 else{118 g = getgrgid(st->st_gid);119 gid = st->st_gid;120 }121 if(g == nil){122 snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);123 s = tmp;124 }else125 s = g->gr_name;126 sz += strlen(s)+1;127 if(d){128 if(*str + strlen(s)+1 > estr)129 d->gid = "oops";130 else{131 strcpy(*str, s);132 d->gid = *str;133 *str += strlen(*str)+1;134 }135 }137 if(d){138 d->type = 'M';140 d->muid = "";141 d->qid.path = ((uvlong)st->st_dev<<32) | st->st_ino;142 #ifdef _HAVESTGEN143 d->qid.vers = st->st_gen;144 #endif145 d->mode = st->st_mode&0777;146 d->atime = st->st_atime;147 d->mtime = st->st_mtime;148 d->length = st->st_size;150 if(S_ISDIR(st->st_mode)){151 d->length = 0;152 d->mode |= DMDIR;153 d->qid.type = QTDIR;154 }156 /* fetch real size for disks */157 #ifdef _HAVEDISKLABEL158 if(isdisk(st)){159 int fd, n;160 struct disklabel lab;162 if((fd = open(name, O_RDONLY)) < 0)163 goto nosize;164 if(ioctl(fd, DIOCGDINFO, &lab) < 0)165 goto nosize;166 n = minor(st->st_rdev)&7;167 if(n >= lab.d_npartitions)168 goto nosize;170 d->length = (vlong)(lab.d_partitions[n].p_size) * lab.d_secsize;172 nosize:173 if(fd >= 0)174 close(fd);175 }176 #endif177 }179 return sz;180 }