blob: c7578a51168cdbb5b567cd38c4114425f19d5f2d [file] [log] [blame]
rsc478ee962003-11-23 20:04:53 +00001#include <u.h>
2#define NOPLAN9DEFINES
3#include <libc.h>
rsc478ee962003-11-23 20:04:53 +00004#include <sys/types.h>
rscfd04aac2003-11-23 18:12:54 +00005#include <sys/stat.h>
rscfd04aac2003-11-23 18:12:54 +00006#include <dirent.h>
7#include <pwd.h>
8#include <grp.h>
9
Russ Cox2c82cd62008-07-03 17:45:17 -040010#if defined(__APPLE__)
11#define _HAVESTGEN
12#include <sys/disk.h>
13static vlong
14disksize(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
rsc97529502007-05-15 13:10:51 +000030#include <sys/disk.h>
rsc64bcfff2003-11-25 02:11:11 +000031#include <sys/disklabel.h>
rscfe8c9252005-07-21 18:29:04 +000032#include <sys/ioctl.h>
Russ Cox2c82cd62008-07-03 17:45:17 -040033static vlong
34disksize(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}
rsc69bdb782007-05-11 00:16:40 +000042
Russ Cox2c82cd62008-07-03 17:45:17 -040043#elif defined(__OpenBSD__)
44#define _HAVESTGEN
rsc97529502007-05-15 13:10:51 +000045#include <sys/disklabel.h>
46#include <sys/ioctl.h>
Russ Cox2c82cd62008-07-03 17:45:17 -040047static vlong
48disksize(int fd, struct stat *st)
rsc669250d2003-12-03 22:50:48 +000049{
Russ Cox2c82cd62008-07-03 17:45:17 -040050 struct disklabel lab;
rsc669250d2003-12-03 22:50:48 +000051 if(!S_ISCHR(st->st_mode))
52 return 0;
Russ Cox2c82cd62008-07-03 17:45:17 -040053 if(ioctl(fd, DIOCGDINFO, &lab) < 0)
rsc69bdb782007-05-11 00:16:40 +000054 return 0;
Russ Cox2c82cd62008-07-03 17:45:17 -040055 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;
rsc69bdb782007-05-11 00:16:40 +000059}
rsc69bdb782007-05-11 00:16:40 +000060
Russ Cox2c82cd62008-07-03 17:45:17 -040061#elif defined(__linux__)
rsc7317e772004-04-25 22:24:56 +000062#include <linux/hdreg.h>
63#include <linux/fs.h>
64#include <sys/ioctl.h>
rsca3e9d892005-08-10 17:16:38 +000065#undef major
66#define major(dev) ((int)(((dev) >> 8) & 0xff))
rsc7317e772004-04-25 22:24:56 +000067static vlong
Russ Cox2c82cd62008-07-03 17:45:17 -040068disksize(int fd, struct stat *st)
rsc7317e772004-04-25 22:24:56 +000069{
70 u64int u64;
71 long l;
72 struct hd_geometry geo;
73
rscceecb312004-06-09 14:13:49 +000074 memset(&geo, 0, sizeof geo);
75 l = 0;
76 u64 = 0;
rsc76e6aca2004-05-15 23:16:38 +000077#ifdef BLKGETSIZE64
rsc7317e772004-04-25 22:24:56 +000078 if(ioctl(fd, BLKGETSIZE64, &u64) >= 0)
79 return u64;
rsc76e6aca2004-05-15 23:16:38 +000080#endif
rsc7317e772004-04-25 22:24:56 +000081 if(ioctl(fd, BLKGETSIZE, &l) >= 0)
rsc3d484b02005-12-29 21:41:54 +000082 return l*512;
rsc7317e772004-04-25 22:24:56 +000083 if(ioctl(fd, HDIO_GETGEO, &geo) >= 0)
84 return (vlong)geo.heads*geo.sectors*geo.cylinders*512;
85 return 0;
86}
rsc7317e772004-04-25 22:24:56 +000087
Russ Cox2c82cd62008-07-03 17:45:17 -040088#else
89static vlong
90disksize(int fd, struct stat *st)
91{
92 return 0;
93}
rsc64bcfff2003-11-25 02:11:11 +000094#endif
95
rsc63fcc2b2006-06-12 17:21:10 +000096int _p9usepwlibrary = 1;
rsc6f6553d2004-04-08 19:31:21 +000097/*
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 */
rscfd04aac2003-11-23 18:12:54 +0000103int
rsc0a229052005-02-08 20:08:28 +0000104_p9dir(struct stat *lst, struct stat *st, char *name, Dir *d, char **str, char *estr)
rscfd04aac2003-11-23 18:12:54 +0000105{
106 char *s;
107 char tmp[20];
rsc6f6553d2004-04-08 19:31:21 +0000108 static struct group *g;
109 static struct passwd *p;
110 static int gid, uid;
rsc7317e772004-04-25 22:24:56 +0000111 int sz, fd;
rscfd04aac2003-11-23 18:12:54 +0000112
rsc631fe872004-05-14 20:08:02 +0000113 fd = -1;
114 USED(fd);
rscfd04aac2003-11-23 18:12:54 +0000115 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 */
rsc6f6553d2004-04-08 19:31:21 +0000141 if(p && st->st_uid == uid && p->pw_uid == uid)
142 ;
rsc63fcc2b2006-06-12 17:21:10 +0000143 else if(_p9usepwlibrary){
rsc6f6553d2004-04-08 19:31:21 +0000144 p = getpwuid(st->st_uid);
145 uid = st->st_uid;
146 }
rsc63fcc2b2006-06-12 17:21:10 +0000147 if(p == nil || st->st_uid != uid || p->pw_uid != uid){
rscfd04aac2003-11-23 18:12:54 +0000148 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 */
rsc6f6553d2004-04-08 19:31:21 +0000164 if(g && st->st_gid == gid && g->gr_gid == gid)
165 ;
rsc63fcc2b2006-06-12 17:21:10 +0000166 else if(_p9usepwlibrary){
rsc6f6553d2004-04-08 19:31:21 +0000167 g = getgrgid(st->st_gid);
168 gid = st->st_gid;
169 }
rsc63fcc2b2006-06-12 17:21:10 +0000170 if(g == nil || st->st_gid != gid || g->gr_gid != gid){
rscfd04aac2003-11-23 18:12:54 +0000171 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;
rsc1c253ce2003-11-23 19:49:17 +0000191#ifdef _HAVESTGEN
rscfd04aac2003-11-23 18:12:54 +0000192 d->qid.vers = st->st_gen;
rsc1c253ce2003-11-23 19:49:17 +0000193#endif
rsc3d484b02005-12-29 21:41:54 +0000194 if(d->qid.vers == 0)
195 d->qid.vers = st->st_mtime + st->st_ctime;
rscfd04aac2003-11-23 18:12:54 +0000196 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 }
rsc98660df2005-02-21 14:25:12 +0000206 if(S_ISLNK(lst->st_mode)) /* yes, lst not st */
rsc2acd6fa2005-02-08 20:17:02 +0000207 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 }
rscfd04aac2003-11-23 18:12:54 +0000220 /* fetch real size for disks */
Russ Cox2c82cd62008-07-03 17:45:17 -0400221 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);
rsc7317e772004-04-25 22:24:56 +0000224 close(fd);
225 }
rscfd04aac2003-11-23 18:12:54 +0000226 }
227
228 return sz;
229}
230