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