]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/cifsd/dir.c
cifsd: fix compiler warning
[plan9front.git] / sys / src / cmd / ip / cifsd / dir.c
1 #include <u.h>
2 #include <libc.h>
3 #include "dat.h"
4 #include "fns.h"
5
6 static char*
7 append(char **p, char *s)
8 {
9         int n;
10         char *o;
11
12         if(s == nil)
13                 return nil;
14         n = strlen(s)+1;
15         memmove(o = *p, s, n);
16         *p += n;
17         return o;
18 }
19
20 static Dir*
21 xdirdup(Dir *d, int n)
22 {
23         char *p;
24         Dir *o;
25         int i;
26
27         p = nil;
28         for(i=0; i<n; i++){
29                 p += strlen(d[i].name)+1;
30                 if(d[i].uid) p += strlen(d[i].uid)+1;
31                 if(d[i].gid) p += strlen(d[i].gid)+1;
32                 if(d[i].muid) p += strlen(d[i].muid)+1;
33         }
34         o = malloc(n*sizeof(*d) + (uintptr)p);
35         memmove(o, d, n*sizeof(*d));
36         p = (char*)&o[n];
37         for(i=0; i<n; i++){
38                 o[i].name = append(&p, d[i].name);
39                 o[i].uid = append(&p, d[i].uid);
40                 o[i].gid = append(&p, d[i].gid);
41                 o[i].muid = append(&p, d[i].muid);
42         }
43         return o;
44 }
45
46 static int xdirread0(char **path, int (*namecmp)(char *, char *), Dir **d);
47
48 int
49 xdirread(char **path, int (*namecmp)(char *, char *), Dir **d)
50 {
51         Dir *t;
52         int n;
53
54         if((n = xdirread0(path, namecmp, &t)) > 0)
55                 *d =  xdirdup(t, n);
56         else
57                 *d = nil;
58         return n;
59 }
60
61 static Dir*
62 xdirstat0(char **path, int (*namecmp)(char *, char *), char *err)
63 {
64         char *base, *name;
65         Dir *d, *t;
66         int n, i;
67
68         if(d = dirstat(*path))
69                 return d;
70         if(!splitpath(*path, &base, &name))
71                 return nil;
72         if((n = xdirread0(&base, namecmp, &t)) < 0)
73                 goto out;
74         for(i=0; i<n; i++){
75                 if(namecmp(t[i].name, name))
76                         continue;
77                 free(*path); *path = conspath(base, t[i].name);
78                 d = xdirdup(&t[i], 1);
79                 goto out;
80         }
81         werrstr("%s", err);
82 out:
83         free(base);
84         free(name);
85         return d;
86 }
87
88 Dir*
89 xdirstat(char **path, int (*namecmp)(char *, char *))
90 {
91         return xdirstat0(path, namecmp, "name not found");
92 }
93
94 typedef struct XDir XDir;
95 struct XDir
96 {
97         Qid     qid;
98         char    *path;
99         int     ndir;
100         Dir     *dir;
101         XDir    *next;
102 };
103
104 static void
105 freexdir(XDir *x)
106 {
107         free(x->path);
108         free(x->dir);
109         free(x);
110 }
111
112 static int
113 qidcmp(Qid *q1, Qid *q2)
114 {
115         return (q1->type != q2->type) || (q1->path != q2->path) || (q1->vers != q2->vers);
116 }
117
118 static XDir *xdirlist;
119 static int xdircount;
120
121 static int
122 xdirread0(char **path, int (*namecmp)(char *, char *), Dir **d)
123 {
124         XDir *x, *p;
125         int fd, n;
126         Dir *t;
127
128         t = nil;
129         for(p = nil, x = xdirlist; x; p=x, x=x->next){
130                 if(namecmp(x->path, *path))
131                         continue;
132                 if(x == xdirlist)
133                         xdirlist = x->next;
134                 else
135                         p->next = x->next;
136                 while(t = dirstat(x->path)){
137                         if(qidcmp(&t->qid, &x->qid))
138                                 break;
139                         free(t);
140                         x->next = xdirlist;
141                         xdirlist = x;
142                         if(strcmp(x->path, *path)){
143                                 free(*path);
144                                 *path = strdup(x->path);
145                         }
146                         if(d) *d = x->dir;
147                         return x->ndir;
148                 }
149                 xdircount--;
150                 freexdir(x);
151                 break;
152         }
153         if((fd = open(*path, OREAD)) < 0){
154                 free(t);
155                 if(t = xdirstat0(path, namecmp, "directory entry not found"))
156                         fd = open(*path, OREAD);
157         } else if(t == nil)
158                 t = dirfstat(fd);
159
160         n = -1;
161         if(fd < 0 || t == nil)
162                 goto out;
163         if((t->qid.type & QTDIR) == 0){
164                 werrstr("not a directory");
165                 goto out;
166         }
167         if((n = dirreadall(fd, d)) < 0)
168                 goto out;
169
170         if(xdircount >= 8){
171                 xdircount--;
172                 for(p = xdirlist, x = xdirlist->next; x->next; p = x, x = x->next)
173                         ;
174                 p->next = nil;
175                 freexdir(x);
176         }
177
178         x = mallocz(sizeof(*x), 1);
179         x->qid = t->qid;
180         x->path = strdup(*path);
181         x->ndir = n;
182         x->dir = *d;
183
184         x->next = xdirlist;
185         xdirlist = x;
186         xdircount++;
187
188 out:
189         if(fd >= 0)
190                 close(fd);
191         free(t);
192         return n;
193 }
194
195 void
196 xdirflush(char *path, int (*namecmp)(char *, char *))
197 {
198         XDir **pp, **xx, *x;
199         char *d, *s;
200         int n;
201
202         n = strlen(path);
203         if(s = strrchr(path, '/'))
204                 n = s - path;
205         d = smprint("%.*s", n, path);
206         s = malloc(++n);
207         for(pp = &xdirlist; x = *pp; pp = xx){
208                 xx = &x->next;
209                 snprint(s, n, "%s", x->path);
210                 if(namecmp(d, s) == 0){
211                         *pp = *xx; xx = pp;
212                         xdircount--;
213                         freexdir(x);
214                 }
215         }
216         free(s);
217         free(d);
218 }