| _p9dir.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| _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… | |
| 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 |