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