_p9dir.c (4665B)
1 #include <u.h> 2 #define NOPLAN9DEFINES 3 #include <libc.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <dirent.h> 7 #include <pwd.h> 8 #include <grp.h> 9 10 #if defined(__APPLE__) 11 #define _HAVESTGEN 12 #include <sys/disk.h> 13 static vlong 14 disksize(int fd, struct stat *st) 15 { 16 u64int bc; 17 u32int bs; 18 19 bs = 0; 20 bc = 0; 21 ioctl(fd, DKIOCGETBLOCKSIZE, &bs); 22 ioctl(fd, DKIOCGETBLOCKCOUNT, &bc); 23 if(bs >0 && bc > 0) 24 return bc*bs; 25 return 0; 26 } 27 28 #elif defined(__FreeBSD__) 29 #define _HAVESTGEN 30 #include <sys/disk.h> 31 #include <sys/disklabel.h> 32 #include <sys/ioctl.h> 33 static vlong 34 disksize(int fd, struct stat *st) 35 { 36 off_t mediasize; 37 38 if(ioctl(fd, DIOCGMEDIASIZE, &mediasize) >= 0) 39 return mediasize; 40 return 0; 41 } 42 43 #elif defined(__OpenBSD__) 44 #define _HAVESTGEN 45 #include <sys/disklabel.h> 46 #include <sys/ioctl.h> 47 #include <sys/dkio.h> 48 static vlong 49 disksize(int fd, struct stat *st) 50 { 51 struct disklabel lab; 52 int n; 53 54 if(ioctl(fd, DIOCGDINFO, &lab) < 0) 55 return 0; 56 n = minor(st->st_rdev)&7; 57 if(n >= lab.d_npartitions) 58 return 0; 59 return (vlong)lab.d_partitions[n].p_size * lab.d_secsize; 60 } 61 62 #elif defined(__linux__) 63 #include <linux/hdreg.h> 64 #include <linux/fs.h> 65 #include <sys/ioctl.h> 66 #undef major 67 #define major(dev) ((int)(((dev) >> 8) & 0xff)) 68 static vlong 69 disksize(int fd, struct stat *st) 70 { 71 u64int u64; 72 long l; 73 struct hd_geometry geo; 74 75 memset(&geo, 0, sizeof geo); 76 l = 0; 77 u64 = 0; 78 #ifdef BLKGETSIZE64 79 if(ioctl(fd, BLKGETSIZE64, &u64) >= 0) 80 return u64; 81 #endif 82 if(ioctl(fd, BLKGETSIZE, &l) >= 0) 83 return l*512; 84 if(ioctl(fd, HDIO_GETGEO, &geo) >= 0) 85 return (vlong)geo.heads*geo.sectors*geo.cylinders*512; 86 return 0; 87 } 88 89 #else 90 static vlong 91 disksize(int fd, struct stat *st) 92 { 93 return 0; 94 } 95 #endif 96 97 int _p9usepwlibrary = 1; 98 /* 99 * Caching the last group and passwd looked up is 100 * a significant win (stupidly enough) on most systems. 101 * It's not safe for threaded programs, but neither is using 102 * getpwnam in the first place, so I'm not too worried. 103 */ 104 int 105 _p9dir(struct stat *lst, struct stat *st, char *name, Dir *d, char **str, char *estr) 106 { 107 char *s; 108 char tmp[20]; 109 static struct group *g; 110 static struct passwd *p; 111 static int gid, uid; 112 int sz, fd; 113 114 fd = -1; 115 USED(fd); 116 sz = 0; 117 if(d) 118 memset(d, 0, sizeof *d); 119 120 /* name */ 121 s = strrchr(name, '/'); 122 if(s) 123 s++; 124 if(!s || !*s) 125 s = name; 126 if(*s == '/') 127 s++; 128 if(*s == 0) 129 s = "/"; 130 if(d){ 131 if(*str + strlen(s)+1 > estr) 132 d->name = "oops"; 133 else{ 134 strcpy(*str, s); 135 d->name = *str; 136 *str += strlen(*str)+1; 137 } 138 } 139 sz += strlen(s)+1; 140 141 /* user */ 142 if(p && st->st_uid == uid && p->pw_uid == uid) 143 ; 144 else if(_p9usepwlibrary){ 145 p = getpwuid(st->st_uid); 146 uid = st->st_uid; 147 } 148 if(p == nil || st->st_uid != uid || p->pw_uid != uid){ 149 snprint(tmp, sizeof tmp, "%d", (int)st->st_uid); 150 s = tmp; 151 }else 152 s = p->pw_name; 153 sz += strlen(s)+1; 154 if(d){ 155 if(*str+strlen(s)+1 > estr) 156 d->uid = "oops"; 157 else{ 158 strcpy(*str, s); 159 d->uid = *str; 160 *str += strlen(*str)+1; 161 } 162 } 163 164 /* group */ 165 if(g && st->st_gid == gid && g->gr_gid == gid) 166 ; 167 else if(_p9usepwlibrary){ 168 g = getgrgid(st->st_gid); 169 gid = st->st_gid; 170 } 171 if(g == nil || st->st_gid != gid || g->gr_gid != gid){ 172 snprint(tmp, sizeof tmp, "%d", (int)st->st_gid); 173 s = tmp; 174 }else 175 s = g->gr_name; 176 sz += strlen(s)+1; 177 if(d){ 178 if(*str + strlen(s)+1 > estr) 179 d->gid = "oops"; 180 else{ 181 strcpy(*str, s); 182 d->gid = *str; 183 *str += strlen(*str)+1; 184 } 185 } 186 187 if(d){ 188 d->type = 'M'; 189 190 d->muid = ""; 191 d->qid.path = st->st_ino; 192 /* 193 * do not include st->st_dev in path, because 194 * automounters give the same file system different 195 * st_dev values for successive mounts, causing 196 * spurious write warnings in acme and sam. 197 d->qid.path |= (uvlong)st->st_dev<<32; 198 */ 199 #ifdef _HAVESTGEN 200 d->qid.vers = st->st_gen; 201 #endif 202 if(d->qid.vers == 0) 203 d->qid.vers = st->st_mtime + st->st_ctime; 204 d->mode = st->st_mode&0777; 205 d->atime = st->st_atime; 206 d->mtime = st->st_mtime; 207 d->length = st->st_size; 208 209 if(S_ISLNK(lst->st_mode)){ /* yes, lst not st */ 210 d->mode |= DMSYMLINK; 211 d->length = lst->st_size; 212 } 213 else if(S_ISDIR(st->st_mode)){ 214 d->length = 0; 215 d->mode |= DMDIR; 216 d->qid.type = QTDIR; 217 } 218 else if(S_ISFIFO(st->st_mode)) 219 d->mode |= DMNAMEDPIPE; 220 else if(S_ISSOCK(st->st_mode)) 221 d->mode |= DMSOCKET; 222 else if(S_ISBLK(st->st_mode)){ 223 d->mode |= DMDEVICE; 224 d->qid.path = ('b'<<16)|st->st_rdev; 225 } 226 else if(S_ISCHR(st->st_mode)){ 227 d->mode |= DMDEVICE; 228 d->qid.path = ('c'<<16)|st->st_rdev; 229 } 230 /* fetch real size for disks */ 231 if(S_ISBLK(lst->st_mode)){ 232 if((fd = open(name, O_RDONLY)) >= 0){ 233 d->length = disksize(fd, st); 234 close(fd); 235 } 236 } 237 } 238 239 return sz; 240 }