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