dtfs_subr.c revision 1.2 1 1.2 pooka /* $NetBSD: dtfs_subr.c,v 1.2 2010/07/14 13:09:52 pooka Exp $ */
2 1.1 pooka
3 1.1 pooka /*
4 1.1 pooka * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
5 1.1 pooka *
6 1.1 pooka * Redistribution and use in source and binary forms, with or without
7 1.1 pooka * modification, are permitted provided that the following conditions
8 1.1 pooka * are met:
9 1.1 pooka * 1. Redistributions of source code must retain the above copyright
10 1.1 pooka * notice, this list of conditions and the following disclaimer.
11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 pooka * notice, this list of conditions and the following disclaimer in the
13 1.1 pooka * documentation and/or other materials provided with the distribution.
14 1.1 pooka *
15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1 pooka * SUCH DAMAGE.
26 1.1 pooka */
27 1.1 pooka
28 1.1 pooka #include <sys/types.h>
29 1.1 pooka #include <sys/time.h>
30 1.1 pooka
31 1.1 pooka #include <assert.h>
32 1.1 pooka #include <err.h>
33 1.1 pooka #include <errno.h>
34 1.1 pooka #include <puffs.h>
35 1.1 pooka #include <stdlib.h>
36 1.1 pooka #include <string.h>
37 1.1 pooka #include <unistd.h>
38 1.1 pooka #include <util.h>
39 1.1 pooka
40 1.1 pooka #include "dtfs.h"
41 1.1 pooka
42 1.1 pooka void
43 1.1 pooka dtfs_baseattrs(struct vattr *vap, enum vtype type, ino_t id)
44 1.1 pooka {
45 1.1 pooka struct timeval tv;
46 1.1 pooka struct timespec ts;
47 1.1 pooka
48 1.1 pooka gettimeofday(&tv, NULL);
49 1.1 pooka TIMEVAL_TO_TIMESPEC(&tv, &ts);
50 1.1 pooka
51 1.1 pooka vap->va_type = type;
52 1.1 pooka if (type == VDIR) {
53 1.1 pooka vap->va_mode = 0777;
54 1.1 pooka vap->va_nlink = 1; /* n + 1 after adding dent */
55 1.1 pooka } else {
56 1.1 pooka vap->va_mode = 0666;
57 1.1 pooka vap->va_nlink = 0; /* n + 1 */
58 1.1 pooka }
59 1.1 pooka vap->va_uid = 0;
60 1.1 pooka vap->va_gid = 0;
61 1.1 pooka vap->va_fileid = id;
62 1.1 pooka vap->va_size = 0;
63 1.1 pooka vap->va_blocksize = getpagesize();
64 1.1 pooka vap->va_gen = random();
65 1.1 pooka vap->va_flags = 0;
66 1.1 pooka vap->va_rdev = PUFFS_VNOVAL;
67 1.1 pooka vap->va_bytes = 0;
68 1.1 pooka vap->va_filerev = 1;
69 1.1 pooka vap->va_vaflags = 0;
70 1.1 pooka
71 1.1 pooka vap->va_atime = vap->va_mtime = vap->va_ctime = vap->va_birthtime = ts;
72 1.1 pooka }
73 1.1 pooka
74 1.1 pooka /*
75 1.1 pooka * Well, as you can probably see, this interface has the slight problem
76 1.1 pooka * of assuming file creation will always be succesful, or at least not
77 1.1 pooka * giving a reason for the failure. Be sure to do better when you
78 1.1 pooka * implement your own fs.
79 1.1 pooka */
80 1.1 pooka struct puffs_node *
81 1.1 pooka dtfs_genfile(struct puffs_node *dir, const struct puffs_cn *pcn,
82 1.1 pooka enum vtype type)
83 1.1 pooka {
84 1.1 pooka struct dtfs_file *df_dir, *dff;
85 1.1 pooka struct dtfs_dirent *dfd;
86 1.1 pooka struct dtfs_mount *dtm;
87 1.1 pooka struct puffs_node *newpn;
88 1.1 pooka uid_t uid;
89 1.1 pooka int rv;
90 1.1 pooka
91 1.1 pooka assert(dir->pn_va.va_type == VDIR);
92 1.1 pooka assert(dir->pn_mnt != NULL);
93 1.1 pooka
94 1.1 pooka uid = 0;
95 1.1 pooka rv = puffs_cred_getuid(pcn->pcn_cred, &uid);
96 1.1 pooka assert(rv == 0);
97 1.1 pooka
98 1.1 pooka if (type == VDIR) {
99 1.1 pooka dff = dtfs_newdir();
100 1.1 pooka dff->df_dotdot = dir;
101 1.1 pooka } else
102 1.1 pooka dff = dtfs_newfile();
103 1.1 pooka
104 1.1 pooka dtm = puffs_pn_getmntspecific(dir);
105 1.1 pooka newpn = puffs_pn_new(dir->pn_mnt, dff);
106 1.1 pooka if (newpn == NULL)
107 1.1 pooka errx(1, "getnewpnode");
108 1.1 pooka dtfs_baseattrs(&newpn->pn_va, type, dtm->dtm_nextfileid++);
109 1.1 pooka
110 1.1 pooka df_dir = dir->pn_data;
111 1.1 pooka dfd = emalloc(sizeof(struct dtfs_dirent));
112 1.1 pooka dfd->dfd_node = newpn;
113 1.1 pooka dfd->dfd_name = estrndup(pcn->pcn_name, pcn->pcn_namelen);
114 1.1 pooka dfd->dfd_namelen = strlen(dfd->dfd_name);
115 1.1 pooka dfd->dfd_parent = dir;
116 1.1 pooka dtfs_adddent(dir, dfd);
117 1.1 pooka
118 1.1 pooka newpn->pn_va.va_uid = uid;
119 1.1 pooka newpn->pn_va.va_gid = dir->pn_va.va_gid;
120 1.1 pooka
121 1.1 pooka return newpn;
122 1.1 pooka }
123 1.1 pooka
124 1.1 pooka struct dtfs_file *
125 1.1 pooka dtfs_newdir()
126 1.1 pooka {
127 1.1 pooka struct dtfs_file *dff;
128 1.1 pooka
129 1.1 pooka dff = emalloc(sizeof(struct dtfs_file));
130 1.1 pooka memset(dff, 0, sizeof(struct dtfs_file));
131 1.1 pooka LIST_INIT(&dff->df_dirents);
132 1.1 pooka
133 1.1 pooka return dff;
134 1.1 pooka }
135 1.1 pooka
136 1.1 pooka struct dtfs_file *
137 1.1 pooka dtfs_newfile()
138 1.1 pooka {
139 1.1 pooka struct dtfs_file *dff;
140 1.1 pooka
141 1.1 pooka dff = emalloc(sizeof(struct dtfs_file));
142 1.1 pooka memset(dff, 0, sizeof(struct dtfs_file));
143 1.1 pooka
144 1.1 pooka return dff;
145 1.1 pooka }
146 1.1 pooka
147 1.1 pooka struct dtfs_dirent *
148 1.1 pooka dtfs_dirgetnth(struct dtfs_file *searchdir, int n)
149 1.1 pooka {
150 1.1 pooka struct dtfs_dirent *dirent;
151 1.1 pooka int i;
152 1.1 pooka
153 1.1 pooka i = 0;
154 1.1 pooka LIST_FOREACH(dirent, &searchdir->df_dirents, dfd_entries) {
155 1.1 pooka if (i == n)
156 1.1 pooka return dirent;
157 1.1 pooka i++;
158 1.1 pooka }
159 1.1 pooka
160 1.1 pooka return NULL;
161 1.1 pooka }
162 1.1 pooka
163 1.1 pooka struct dtfs_dirent *
164 1.1 pooka dtfs_dirgetbyname(struct dtfs_file *searchdir, const char *fname, size_t fnlen)
165 1.1 pooka {
166 1.1 pooka struct dtfs_dirent *dirent;
167 1.1 pooka
168 1.1 pooka LIST_FOREACH(dirent, &searchdir->df_dirents, dfd_entries)
169 1.1 pooka if (dirent->dfd_namelen == fnlen
170 1.1 pooka && strncmp(dirent->dfd_name, fname, fnlen) == 0)
171 1.1 pooka return dirent;
172 1.1 pooka
173 1.1 pooka return NULL;
174 1.1 pooka }
175 1.1 pooka
176 1.1 pooka /*
177 1.1 pooka * common nuke, kill dirent from parent node
178 1.1 pooka */
179 1.1 pooka void
180 1.1 pooka dtfs_nukenode(struct puffs_node *nukeme, struct puffs_node *pn_parent,
181 1.1 pooka const char *fname, size_t fnlen)
182 1.1 pooka {
183 1.1 pooka struct dtfs_dirent *dfd;
184 1.1 pooka struct dtfs_mount *dtm;
185 1.1 pooka
186 1.1 pooka assert(pn_parent->pn_va.va_type == VDIR);
187 1.1 pooka
188 1.1 pooka dfd = dtfs_dirgetbyname(DTFS_PTOF(pn_parent), fname, fnlen);
189 1.1 pooka assert(dfd);
190 1.1 pooka
191 1.1 pooka dtm = puffs_pn_getmntspecific(nukeme);
192 1.1 pooka dtm->dtm_nfiles--;
193 1.1 pooka assert(dtm->dtm_nfiles >= 1);
194 1.1 pooka
195 1.1 pooka dtfs_removedent(pn_parent, dfd);
196 1.1 pooka free(dfd);
197 1.1 pooka }
198 1.1 pooka
199 1.1 pooka /* free lingering information */
200 1.1 pooka void
201 1.1 pooka dtfs_freenode(struct puffs_node *pn)
202 1.1 pooka {
203 1.1 pooka struct dtfs_file *df = DTFS_PTOF(pn);
204 1.1 pooka struct dtfs_mount *dtm;
205 1.1 pooka int i;
206 1.1 pooka
207 1.1 pooka assert(pn->pn_va.va_nlink == 0);
208 1.1 pooka dtm = puffs_pn_getmntspecific(pn);
209 1.1 pooka
210 1.1 pooka switch (pn->pn_va.va_type) {
211 1.1 pooka case VREG:
212 1.1 pooka assert(dtm->dtm_fsizes >= pn->pn_va.va_size);
213 1.1 pooka dtm->dtm_fsizes -= pn->pn_va.va_size;
214 1.1 pooka for (i = 0; i < BLOCKNUM(df->df_datalen, DTFS_BLOCKSHIFT); i++)
215 1.1 pooka free(df->df_blocks[i]);
216 1.1 pooka if (df->df_datalen > i << DTFS_BLOCKSHIFT)
217 1.1 pooka free(df->df_blocks[i]);
218 1.1 pooka break;
219 1.1 pooka case VLNK:
220 1.1 pooka free(df->df_linktarget);
221 1.1 pooka break;
222 1.1 pooka case VCHR:
223 1.1 pooka case VBLK:
224 1.1 pooka case VDIR:
225 1.1 pooka case VSOCK:
226 1.1 pooka case VFIFO:
227 1.1 pooka break;
228 1.1 pooka default:
229 1.1 pooka assert(0);
230 1.1 pooka break;
231 1.1 pooka }
232 1.1 pooka
233 1.1 pooka free(df);
234 1.1 pooka puffs_pn_put(pn);
235 1.1 pooka }
236 1.1 pooka
237 1.1 pooka void
238 1.1 pooka dtfs_setsize(struct puffs_node *pn, off_t newsize)
239 1.1 pooka {
240 1.1 pooka struct dtfs_file *df = DTFS_PTOF(pn);
241 1.1 pooka struct dtfs_mount *dtm;
242 1.1 pooka size_t newblocks;
243 1.1 pooka int needalloc, shrinks;
244 1.1 pooka int i;
245 1.1 pooka
246 1.1 pooka needalloc = newsize > ROUNDUP(df->df_datalen, DTFS_BLOCKSIZE);
247 1.1 pooka shrinks = newsize < pn->pn_va.va_size;
248 1.1 pooka
249 1.1 pooka if (needalloc || shrinks) {
250 1.1 pooka newblocks = BLOCKNUM(newsize, DTFS_BLOCKSHIFT) + 1;
251 1.1 pooka
252 1.1 pooka if (shrinks)
253 1.1 pooka for (i = newblocks; i < df->df_numblocks; i++)
254 1.1 pooka free(df->df_blocks[i]);
255 1.1 pooka
256 1.1 pooka df->df_blocks = erealloc(df->df_blocks,
257 1.1 pooka newblocks * sizeof(uint8_t *));
258 1.1 pooka /*
259 1.1 pooka * if extended, set storage to zero
260 1.1 pooka * to match correct behaviour
261 1.1 pooka */
262 1.1 pooka if (!shrinks) {
263 1.1 pooka for (i = df->df_numblocks; i < newblocks; i++) {
264 1.1 pooka df->df_blocks[i] = emalloc(DTFS_BLOCKSIZE);
265 1.1 pooka memset(df->df_blocks[i], 0, DTFS_BLOCKSIZE);
266 1.1 pooka }
267 1.1 pooka }
268 1.1 pooka
269 1.1 pooka df->df_datalen = newsize;
270 1.1 pooka df->df_numblocks = newblocks;
271 1.1 pooka }
272 1.1 pooka
273 1.1 pooka dtm = puffs_pn_getmntspecific(pn);
274 1.1 pooka if (!shrinks) {
275 1.1 pooka dtm->dtm_fsizes += newsize - pn->pn_va.va_size;
276 1.1 pooka } else {
277 1.1 pooka dtm->dtm_fsizes -= pn->pn_va.va_size - newsize;
278 1.1 pooka }
279 1.1 pooka
280 1.1 pooka pn->pn_va.va_size = newsize;
281 1.1 pooka pn->pn_va.va_bytes = BLOCKNUM(newsize,DTFS_BLOCKSHIFT)>>DTFS_BLOCKSHIFT;
282 1.1 pooka }
283 1.1 pooka
284 1.1 pooka /* add & bump link count */
285 1.1 pooka void
286 1.1 pooka dtfs_adddent(struct puffs_node *pn_dir, struct dtfs_dirent *dent)
287 1.1 pooka {
288 1.1 pooka struct dtfs_file *dir = DTFS_PTOF(pn_dir);
289 1.1 pooka struct puffs_node *pn_file = dent->dfd_node;
290 1.1 pooka struct dtfs_file *file = DTFS_PTOF(pn_file);
291 1.1 pooka struct dtfs_mount *dtm;
292 1.1 pooka
293 1.1 pooka assert(pn_dir->pn_va.va_type == VDIR);
294 1.1 pooka LIST_INSERT_HEAD(&dir->df_dirents, dent, dfd_entries);
295 1.1 pooka pn_file->pn_va.va_nlink++;
296 1.1 pooka
297 1.1 pooka dtm = puffs_pn_getmntspecific(pn_file);
298 1.1 pooka dtm->dtm_nfiles++;
299 1.1 pooka
300 1.1 pooka dent->dfd_parent = pn_dir;
301 1.1 pooka if (dent->dfd_node->pn_va.va_type == VDIR) {
302 1.1 pooka file->df_dotdot = pn_dir;
303 1.1 pooka pn_dir->pn_va.va_nlink++;
304 1.1 pooka }
305 1.1 pooka
306 1.1 pooka dtfs_updatetimes(pn_dir, 0, 1, 1);
307 1.1 pooka }
308 1.1 pooka
309 1.1 pooka /* remove & lower link count */
310 1.1 pooka void
311 1.1 pooka dtfs_removedent(struct puffs_node *pn_dir, struct dtfs_dirent *dent)
312 1.1 pooka {
313 1.1 pooka struct puffs_node *pn_file = dent->dfd_node;
314 1.1 pooka
315 1.1 pooka assert(pn_dir->pn_va.va_type == VDIR);
316 1.1 pooka LIST_REMOVE(dent, dfd_entries);
317 1.1 pooka if (pn_file->pn_va.va_type == VDIR)
318 1.1 pooka pn_dir->pn_va.va_nlink--;
319 1.1 pooka pn_file->pn_va.va_nlink--;
320 1.1 pooka assert(pn_dir->pn_va.va_nlink >= 2);
321 1.1 pooka
322 1.1 pooka dtfs_updatetimes(pn_dir, 0, 1, 1);
323 1.1 pooka }
324 1.1 pooka
325 1.1 pooka void
326 1.1 pooka dtfs_updatetimes(struct puffs_node *pn, int doatime, int doctime, int domtime)
327 1.1 pooka {
328 1.1 pooka struct timeval tv;
329 1.1 pooka struct timespec ts;
330 1.1 pooka
331 1.1 pooka gettimeofday(&tv, NULL);
332 1.1 pooka TIMEVAL_TO_TIMESPEC(&tv, &ts);
333 1.1 pooka
334 1.1 pooka if (doatime)
335 1.1 pooka pn->pn_va.va_atime = ts;
336 1.1 pooka if (doctime)
337 1.1 pooka pn->pn_va.va_ctime = ts;
338 1.1 pooka if (domtime)
339 1.1 pooka pn->pn_va.va_mtime = ts;
340 1.1 pooka }
341 1.2 pooka
342 1.2 pooka bool
343 1.2 pooka dtfs_isunder(struct puffs_node *pn, struct puffs_node *pn_parent)
344 1.2 pooka {
345 1.2 pooka struct dtfs_file *df;
346 1.2 pooka
347 1.2 pooka while (pn) {
348 1.2 pooka if (pn == pn_parent)
349 1.2 pooka return true;
350 1.2 pooka df = DTFS_CTOF(pn);
351 1.2 pooka pn = df->df_dotdot;
352 1.2 pooka }
353 1.2 pooka
354 1.2 pooka return false;
355 1.2 pooka }
356