Blob


1 #include <u.h>
2 #define NOPLAN9DEFINES
3 #include <libc.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <dirent.h>
8 #include <pwd.h>
9 #include <grp.h>
11 #if defined(__FreeBSD__)
12 #include <sys/disklabel.h>
13 static int diskdev[] = {
14 151, /* aacd */
15 116, /* ad */
16 157, /* ar */
17 118, /* afd */
18 133, /* amrd */
19 13, /* da */
20 102, /* fla */
21 109, /* idad */
22 95, /* md */
23 131, /* mlxd */
24 168, /* pst */
25 147, /* twed */
26 43, /* vn */
27 3, /* wd */
28 87, /* wfd */
29 };
30 static int
31 isdisk(struct stat *st)
32 {
33 int i, dev;
35 if(!S_ISCHR(st->st_mode))
36 return 0;
37 dev = major(st->st_rdev);
38 for(i=0; i<nelem(diskdev); i++)
39 if(diskdev[i] == dev)
40 return 1;
41 return 0;
42 }
43 #define _HAVEDISKLABEL
44 #endif
46 #if !defined(__linux__) && !defined(__sun__)
47 #define _HAVESTGEN
48 #endif
50 /*
51 * Caching the last group and passwd looked up is
52 * a significant win (stupidly enough) on most systems.
53 * It's not safe for threaded programs, but neither is using
54 * getpwnam in the first place, so I'm not too worried.
55 */
56 int
57 _p9dir(struct stat *st, char *name, Dir *d, char **str, char *estr)
58 {
59 char *s;
60 char tmp[20];
61 static struct group *g;
62 static struct passwd *p;
63 static int gid, uid;
64 int sz;
66 sz = 0;
67 if(d)
68 memset(d, 0, sizeof *d);
70 /* name */
71 s = strrchr(name, '/');
72 if(s)
73 s++;
74 if(!s || !*s)
75 s = name;
76 if(*s == '/')
77 s++;
78 if(*s == 0)
79 s = "/";
80 if(d){
81 if(*str + strlen(s)+1 > estr)
82 d->name = "oops";
83 else{
84 strcpy(*str, s);
85 d->name = *str;
86 *str += strlen(*str)+1;
87 }
88 }
89 sz += strlen(s)+1;
91 /* user */
92 if(p && st->st_uid == uid && p->pw_uid == uid)
93 ;
94 else{
95 p = getpwuid(st->st_uid);
96 uid = st->st_uid;
97 }
98 if(p == nil){
99 snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);
100 s = tmp;
101 }else
102 s = p->pw_name;
103 sz += strlen(s)+1;
104 if(d){
105 if(*str+strlen(s)+1 > estr)
106 d->uid = "oops";
107 else{
108 strcpy(*str, s);
109 d->uid = *str;
110 *str += strlen(*str)+1;
114 /* group */
115 if(g && st->st_gid == gid && g->gr_gid == gid)
117 else{
118 g = getgrgid(st->st_gid);
119 gid = st->st_gid;
121 if(g == nil){
122 snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);
123 s = tmp;
124 }else
125 s = g->gr_name;
126 sz += strlen(s)+1;
127 if(d){
128 if(*str + strlen(s)+1 > estr)
129 d->gid = "oops";
130 else{
131 strcpy(*str, s);
132 d->gid = *str;
133 *str += strlen(*str)+1;
137 if(d){
138 d->type = 'M';
140 d->muid = "";
141 d->qid.path = ((uvlong)st->st_dev<<32) | st->st_ino;
142 #ifdef _HAVESTGEN
143 d->qid.vers = st->st_gen;
144 #endif
145 d->mode = st->st_mode&0777;
146 d->atime = st->st_atime;
147 d->mtime = st->st_mtime;
148 d->length = st->st_size;
150 if(S_ISDIR(st->st_mode)){
151 d->length = 0;
152 d->mode |= DMDIR;
153 d->qid.type = QTDIR;
156 /* fetch real size for disks */
157 #ifdef _HAVEDISKLABEL
158 if(isdisk(st)){
159 int fd, n;
160 struct disklabel lab;
162 if((fd = open(name, O_RDONLY)) < 0)
163 goto nosize;
164 if(ioctl(fd, DIOCGDINFO, &lab) < 0)
165 goto nosize;
166 n = minor(st->st_rdev)&7;
167 if(n >= lab.d_npartitions)
168 goto nosize;
170 d->length = (vlong)(lab.d_partitions[n].p_size) * lab.d_secsize;
172 nosize:
173 if(fd >= 0)
174 close(fd);
176 #endif
179 return sz;