1 /* $NetBSD: dtfs_subr.c,v 1.20 2007/07/22 13:19:38 pooka Exp $ */
4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/types.h>
43 dtfs_baseattrs(struct vattr
*vap
, enum vtype type
, ino_t id
)
48 gettimeofday(&tv
, NULL
);
49 TIMEVAL_TO_TIMESPEC(&tv
, &ts
);
54 vap
->va_nlink
= 1; /* n + 1 after adding dent */
57 vap
->va_nlink
= 0; /* n + 1 */
63 vap
->va_blocksize
= getpagesize();
64 vap
->va_gen
= random();
66 vap
->va_rdev
= PUFFS_VNOVAL
;
71 vap
->va_atime
= vap
->va_mtime
= vap
->va_ctime
= vap
->va_birthtime
= ts
;
75 * Well, as you can probably see, this interface has the slight problem
76 * of assuming file creation will always be succesful, or at least not
77 * giving a reason for the failure. Be sure to do better when you
78 * implement your own fs.
81 dtfs_genfile(struct puffs_node
*dir
, const struct puffs_cn
*pcn
,
84 struct dtfs_file
*df_dir
, *dff
;
85 struct dtfs_dirent
*dfd
;
86 struct dtfs_mount
*dtm
;
87 struct puffs_node
*newpn
;
91 assert(dir
->pn_va
.va_type
== VDIR
);
92 assert(dir
->pn_mnt
!= NULL
);
95 rv
= puffs_cred_getuid(pcn
->pcn_cred
, &uid
);
100 dff
->df_dotdot
= dir
;
102 dff
= dtfs_newfile();
104 dtm
= puffs_pn_getmntspecific(dir
);
105 newpn
= puffs_pn_new(dir
->pn_mnt
, dff
);
107 errx(1, "getnewpnode");
108 dtfs_baseattrs(&newpn
->pn_va
, type
, dtm
->dtm_nextfileid
++);
110 df_dir
= dir
->pn_data
;
111 dfd
= emalloc(sizeof(struct dtfs_dirent
));
112 dfd
->dfd_node
= newpn
;
113 dfd
->dfd_name
= estrndup(pcn
->pcn_name
, pcn
->pcn_namelen
);
114 dfd
->dfd_namelen
= strlen(dfd
->dfd_name
);
115 dfd
->dfd_parent
= dir
;
116 dtfs_adddent(dir
, dfd
);
118 newpn
->pn_va
.va_uid
= uid
;
119 newpn
->pn_va
.va_gid
= dir
->pn_va
.va_gid
;
127 struct dtfs_file
*dff
;
129 dff
= emalloc(sizeof(struct dtfs_file
));
130 memset(dff
, 0, sizeof(struct dtfs_file
));
131 LIST_INIT(&dff
->df_dirents
);
139 struct dtfs_file
*dff
;
141 dff
= emalloc(sizeof(struct dtfs_file
));
142 memset(dff
, 0, sizeof(struct dtfs_file
));
148 dtfs_dirgetnth(struct dtfs_file
*searchdir
, int n
)
150 struct dtfs_dirent
*dirent
;
154 LIST_FOREACH(dirent
, &searchdir
->df_dirents
, dfd_entries
) {
164 dtfs_dirgetbyname(struct dtfs_file
*searchdir
, const char *fname
, size_t fnlen
)
166 struct dtfs_dirent
*dirent
;
168 LIST_FOREACH(dirent
, &searchdir
->df_dirents
, dfd_entries
)
169 if (dirent
->dfd_namelen
== fnlen
170 && strncmp(dirent
->dfd_name
, fname
, fnlen
) == 0)
177 * common nuke, kill dirent from parent node
180 dtfs_nukenode(struct puffs_node
*nukeme
, struct puffs_node
*pn_parent
,
181 const char *fname
, size_t fnlen
)
183 struct dtfs_dirent
*dfd
;
184 struct dtfs_mount
*dtm
;
186 assert(pn_parent
->pn_va
.va_type
== VDIR
);
188 dfd
= dtfs_dirgetbyname(DTFS_PTOF(pn_parent
), fname
, fnlen
);
191 dtm
= puffs_pn_getmntspecific(nukeme
);
193 assert(dtm
->dtm_nfiles
>= 1);
195 dtfs_removedent(pn_parent
, dfd
);
199 /* free lingering information */
201 dtfs_freenode(struct puffs_node
*pn
)
203 struct dtfs_file
*df
= DTFS_PTOF(pn
);
204 struct dtfs_mount
*dtm
;
207 assert(pn
->pn_va
.va_nlink
== 0);
208 dtm
= puffs_pn_getmntspecific(pn
);
210 switch (pn
->pn_va
.va_type
) {
212 assert(dtm
->dtm_fsizes
>= pn
->pn_va
.va_size
);
213 dtm
->dtm_fsizes
-= pn
->pn_va
.va_size
;
214 for (i
= 0; i
< BLOCKNUM(df
->df_datalen
, DTFS_BLOCKSHIFT
); i
++)
215 free(df
->df_blocks
[i
]);
216 if (df
->df_datalen
> i
<< DTFS_BLOCKSHIFT
)
217 free(df
->df_blocks
[i
]);
220 free(df
->df_linktarget
);
238 dtfs_setsize(struct puffs_node
*pn
, off_t newsize
)
240 struct dtfs_file
*df
= DTFS_PTOF(pn
);
241 struct dtfs_mount
*dtm
;
243 int needalloc
, shrinks
;
246 needalloc
= newsize
> ROUNDUP(df
->df_datalen
, DTFS_BLOCKSIZE
);
247 shrinks
= newsize
< pn
->pn_va
.va_size
;
249 if (needalloc
|| shrinks
) {
250 newblocks
= BLOCKNUM(newsize
, DTFS_BLOCKSHIFT
) + 1;
253 for (i
= newblocks
; i
< df
->df_numblocks
; i
++)
254 free(df
->df_blocks
[i
]);
256 df
->df_blocks
= erealloc(df
->df_blocks
,
257 newblocks
* sizeof(uint8_t *));
259 * if extended, set storage to zero
260 * to match correct behaviour
263 for (i
= df
->df_numblocks
; i
< newblocks
; i
++) {
264 df
->df_blocks
[i
] = emalloc(DTFS_BLOCKSIZE
);
265 memset(df
->df_blocks
[i
], 0, DTFS_BLOCKSIZE
);
269 df
->df_datalen
= newsize
;
270 df
->df_numblocks
= newblocks
;
273 dtm
= puffs_pn_getmntspecific(pn
);
275 dtm
->dtm_fsizes
+= newsize
- pn
->pn_va
.va_size
;
277 dtm
->dtm_fsizes
-= pn
->pn_va
.va_size
- newsize
;
280 pn
->pn_va
.va_size
= newsize
;
281 pn
->pn_va
.va_bytes
= BLOCKNUM(newsize
,DTFS_BLOCKSHIFT
)>>DTFS_BLOCKSHIFT
;
284 /* add & bump link count */
286 dtfs_adddent(struct puffs_node
*pn_dir
, struct dtfs_dirent
*dent
)
288 struct dtfs_file
*dir
= DTFS_PTOF(pn_dir
);
289 struct puffs_node
*pn_file
= dent
->dfd_node
;
290 struct dtfs_file
*file
= DTFS_PTOF(pn_file
);
291 struct dtfs_mount
*dtm
;
293 assert(pn_dir
->pn_va
.va_type
== VDIR
);
294 LIST_INSERT_HEAD(&dir
->df_dirents
, dent
, dfd_entries
);
295 pn_file
->pn_va
.va_nlink
++;
297 dtm
= puffs_pn_getmntspecific(pn_file
);
300 dent
->dfd_parent
= pn_dir
;
301 if (dent
->dfd_node
->pn_va
.va_type
== VDIR
) {
302 file
->df_dotdot
= pn_dir
;
303 pn_dir
->pn_va
.va_nlink
++;
306 dtfs_updatetimes(pn_dir
, 0, 1, 1);
309 /* remove & lower link count */
311 dtfs_removedent(struct puffs_node
*pn_dir
, struct dtfs_dirent
*dent
)
313 struct puffs_node
*pn_file
= dent
->dfd_node
;
315 assert(pn_dir
->pn_va
.va_type
== VDIR
);
316 LIST_REMOVE(dent
, dfd_entries
);
317 if (pn_file
->pn_va
.va_type
== VDIR
)
318 pn_dir
->pn_va
.va_nlink
--;
319 pn_file
->pn_va
.va_nlink
--;
320 assert(pn_dir
->pn_va
.va_nlink
>= 2);
322 dtfs_updatetimes(pn_dir
, 0, 1, 1);
326 dtfs_updatetimes(struct puffs_node
*pn
, int doatime
, int doctime
, int domtime
)
331 gettimeofday(&tv
, NULL
);
332 TIMEVAL_TO_TIMESPEC(&tv
, &ts
);
335 pn
->pn_va
.va_atime
= ts
;
337 pn
->pn_va
.va_ctime
= ts
;
339 pn
->pn_va
.va_mtime
= ts
;