1 /*
2 Plan 9 from User Space src/lib9/_p9dir.c
3 http://code.swtch.com/plan9port/src/tip/src/lib9/_p9dir.c
4
5 Copyright 2001-2007 Russ Cox. All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 THE SOFTWARE.
24 */
25
26 #include <u.h>
27 #define NOPLAN9DEFINES
28 #include <libc.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <dirent.h>
32
33 /*
34 * Caching the last group and passwd looked up is
35 * a significant win (stupidly enough) on most systems.
36 * It's not safe for threaded programs, but neither is using
37 * getpwnam in the first place, so I'm not too worried.
38 */
39 int
40 _p9dir(struct stat *lst, struct stat *st, char *name, Dir *d, char **str, char *estr)
41 {
42 char *s;
43 char tmp[20];
44 int sz, fd;
45
46 fd = -1;
47 USED(fd);
48 sz = 0;
49 if(d)
50 memset(d, 0, sizeof *d);
51
52 /* name */
53 s = strrchr(name, '/');
54 if(s)
55 s++;
56 if(!s || !*s)
57 s = name;
58 if(*s == '/')
59 s++;
60 if(*s == 0)
61 s = "/";
62 if(d){
63 if(*str + strlen(s)+1 > estr)
64 d->name = "oops";
65 else{
66 strcpy(*str, s);
67 d->name = *str;
68 *str += strlen(*str)+1;
69 }
70 }
71 sz += strlen(s)+1;
72
73 /* user */
74 snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);
75 s = tmp;
76 sz += strlen(s)+1;
77 if(d){
78 if(*str+strlen(s)+1 > estr)
79 d->uid = "oops";
80 else{
81 strcpy(*str, s);
82 d->uid = *str;
83 *str += strlen(*str)+1;
84 }
85 }
86
87 /* group */
88 snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);
89 s = tmp;
90 sz += strlen(s)+1;
91 if(d){
92 if(*str + strlen(s)+1 > estr)
93 d->gid = "oops";
94 else{
95 strcpy(*str, s);
96 d->gid = *str;
97 *str += strlen(*str)+1;
98 }
99 }
100
101 if(d){
102 d->type = 'M';
103
104 d->muid = "";
105 d->qid.path = ((uvlong)st->st_dev<<32) | st->st_ino;
106 #ifdef _HAVESTGEN
107 d->qid.vers = st->st_gen;
108 #endif
109 if(d->qid.vers == 0)
110 d->qid.vers = st->st_mtime + st->st_ctime;
111 d->mode = st->st_mode&0777;
112 d->atime = st->st_atime;
113 d->mtime = st->st_mtime;
114 d->length = st->st_size;
115
116 if(S_ISDIR(st->st_mode)){
117 d->length = 0;
118 d->mode |= DMDIR;
119 d->qid.type = QTDIR;
120 }
121 #ifdef S_ISLNK
122 if(S_ISLNK(lst->st_mode)) /* yes, lst not st */
123 d->mode |= DMSYMLINK;
124 #endif
125 if(S_ISFIFO(st->st_mode))
126 d->mode |= DMNAMEDPIPE;
127 #ifdef S_ISSOCK
128 if(S_ISSOCK(st->st_mode))
129 d->mode |= DMSOCKET;
130 #endif
131 if(S_ISBLK(st->st_mode)){
132 d->mode |= DMDEVICE;
133 d->qid.path = ('b'<<16)|st->st_rdev;
134 }
135 if(S_ISCHR(st->st_mode)){
136 d->mode |= DMDEVICE;
137 d->qid.path = ('c'<<16)|st->st_rdev;
138 }
139 /* fetch real size for disks */
140 if(S_ISBLK(st->st_mode) && (fd = open(name, O_RDONLY)) >= 0){
141 d->length = 0;
142 close(fd);
143 }
144 #if defined(DIOCGMEDIASIZE)
145 if(isdisk(st)){
146 int fd;
147 off_t mediasize;
148
149 if((fd = open(name, O_RDONLY)) >= 0){
150 if(ioctl(fd, DIOCGMEDIASIZE, &mediasize) >= 0)
151 d->length = mediasize;
152 close(fd);
153 }
154 }
155 #elif defined(_HAVEDISKLABEL)
156 if(isdisk(st)){
157 int fd, n;
158 struct disklabel lab;
159
160 if((fd = open(name, O_RDONLY)) < 0)
161 goto nosize;
162 if(ioctl(fd, DIOCGDINFO, &lab) < 0)
163 goto nosize;
164 n = minor(st->st_rdev)&7;
165 if(n >= lab.d_npartitions)
166 goto nosize;
167
168 d->length = (vlong)(lab.d_partitions[n].p_size) * lab.d_secsize;
169
170 nosize:
171 if(fd >= 0)
172 close(fd);
173 }
174 #endif
175 }
176
177 return sz;
178 }
179