Annotation of prex/usr/server/fs/fatfs/fatfs_node.c, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 2005-2008, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: #include <prex/prex.h>
31: #include <sys/buf.h>
32:
33: #include <ctype.h>
34: #include <string.h>
35: #include <unistd.h>
36: #include <errno.h>
37: #include <stdlib.h>
38:
39: #include "fatfs.h"
40:
41: /*
42: * Read directory entry to buffer, with cache.
43: */
44: static int
45: fat_read_dirent(struct fatfsmount *fmp, u_long sec)
46: {
47: struct buf *bp;
48: int err;
49:
50: if ((err = bread(fmp->dev, sec, &bp)) != 0)
51: return err;
52: memcpy(fmp->dir_buf, bp->b_data, SEC_SIZE);
53: brelse(bp);
54: return 0;
55: }
56:
57: /*
58: * Write directory entry from buffer.
59: */
60: static int
61: fat_write_dirent(struct fatfsmount *fmp, u_long sec)
62: {
63: struct buf *bp;
64:
65: bp = getblk(fmp->dev, sec);
66: memcpy(bp->b_data, fmp->dir_buf, SEC_SIZE);
67: return bwrite(bp);
68: }
69:
70: /*
71: * Find directory entry in specified sector.
72: * The fat vnode data is filled if success.
73: *
74: * @fmp: fatfs mount point
75: * @sec: sector#
76: * @name: file name
77: * @node: pointer to fat node
78: */
79: static int
80: fat_lookup_dirent(struct fatfsmount *fmp, u_long sec, char *name,
81: struct fatfs_node *np)
82: {
83: struct fat_dirent *de;
84: int err, i;
85:
86: err = fat_read_dirent(fmp, sec);
87: if (err)
88: return err;
89:
90: de = (struct fat_dirent *)fmp->dir_buf;
91:
92: for (i = 0; i < DIR_PER_SEC; i++) {
93: /* Find specific file or directory name */
94: if (IS_EMPTY(de))
95: return ENOENT;
96: if (!IS_VOL(de) &&
97: !fat_compare_name((char *)de->name, name)) {
98: /* Found. Fill the fat vnode data. */
99: *(&np->dirent) = *de;
100: np->sector = sec;
101: np->offset = sizeof(struct fat_dirent) * i;
102: DPRINTF(("fat_lookup_dirent: found sec=%d\n", sec));
103: return 0;
104: }
105: if (!IS_DELETED(de))
106: DPRINTF(("fat_lookup_dirent: %s\n", de->name));
107: de++;
108: }
109: return EAGAIN;
110: }
111:
112: /*
113: * Find directory entry for specified name in directory.
114: * The fat vnode data is filled if success.
115: *
116: * @dvp: vnode for directory.
117: * @name: file name
118: * @np: pointer to fat node
119: */
120: int
121: fatfs_lookup_node(vnode_t dvp, char *name, struct fatfs_node *np)
122: {
123: struct fatfsmount *fmp;
124: char fat_name[12];
125: u_long cl, sec;
126: int i, err;
127:
128: if (name == NULL)
129: return ENOENT;
130:
131: DPRINTF(("fat_lookup_denode: cl=%d name=%s\n", dvp->v_blkno, name));
132:
133: fat_convert_name(name, fat_name);
134: *(fat_name + 11) = '\0';
135:
136: fmp = (struct fatfsmount *)dvp->v_mount->m_data;
137: cl = dvp->v_blkno;
138: if (cl == CL_ROOT) {
139: /* Search entry in root directory */
140: for (sec = fmp->root_start; sec < fmp->data_start; sec++) {
141: err = fat_lookup_dirent(fmp, sec, fat_name, np);
142: if (err != EAGAIN)
143: return err;
144: }
145: } else {
146: /* Search entry in sub directory */
147: while (!IS_EOFCL(fmp, cl)) {
148: sec = cl_to_sec(fmp, cl);
149: for (i = 0; i < fmp->sec_per_cl; i++) {
150: err = fat_lookup_dirent(fmp, sec, fat_name,
151: np);
152: if (err != EAGAIN)
153: return err;
154: sec++;
155: }
156: err = fat_next_cluster(fmp, cl, &cl);
157: if (err)
158: return err;
159: }
160: }
161: return ENOENT;
162: }
163:
164: /*
165: * Get directory entry for specified index in sector.
166: * The directory entry is filled if success.
167: *
168: * @fmp: fatfs mount point
169: * @sec: sector#
170: * @target: target index
171: * @index: current index
172: * @np: pointer to fat node
173: */
174: static int
175: fat_get_dirent(struct fatfsmount *fmp, u_long sec, int target, int *index,
176: struct fatfs_node *np)
177: {
178: struct fat_dirent *de;
179: int err, i;
180:
181: err = fat_read_dirent(fmp, sec);
182: if (err)
183: return err;
184:
185: de = (struct fat_dirent *)fmp->dir_buf;
186: for (i = 0; i < DIR_PER_SEC; i++) {
187: if (IS_EMPTY(de))
188: return ENOENT;
189: if (!IS_DELETED(de) && !IS_VOL(de)) {
190: /* valid file */
191: if (*index == target) {
192: *(&np->dirent) = *de;
193: np->sector = sec;
194: np->offset = sizeof(struct fat_dirent) * i;
195: DPRINTF(("fat_get_dirent: found index=%d\n", *index));
196: return 0;
197: }
198: (*index)++;
199: }
200: DPRINTF(("fat_get_dirent: %s\n", de->name));
201: de++;
202: }
203: return EAGAIN;
204: }
205:
206: /*
207: * Get directory entry for specified index.
208: *
209: * @dvp: vnode for directory.
210: * @index: index of the entry
211: * @np: pointer to fat node
212: */
213: int
214: fatfs_get_node(vnode_t dvp, int index, struct fatfs_node *np)
215: {
216: struct fatfsmount *fmp;
217: u_long cl, sec;
218: int i, cur_index, err;
219:
220: fmp = (struct fatfsmount *)dvp->v_mount->m_data;
221: cl = dvp->v_blkno;
222: cur_index = 0;
223:
224: DPRINTF(("fatfs_get_node: index=%d\n", index));
225:
226: if (cl == CL_ROOT) {
227: /* Get entry from the root directory */
228: for (sec = fmp->root_start; sec < fmp->data_start; sec++) {
229: err = fat_get_dirent(fmp, sec, index, &cur_index, np);
230: if (err != EAGAIN)
231: return err;
232: }
233: } else {
234: /* Get entry from the sub directory */
235: while (!IS_EOFCL(fmp, cl)) {
236: sec = cl_to_sec(fmp, cl);
237: for (i = 0; i < fmp->sec_per_cl; i++) {
238: err = fat_get_dirent(fmp, sec, index,
239: &cur_index, np);
240: if (err != EAGAIN)
241: return err;
242: sec++;
243: }
244: err = fat_next_cluster(fmp, cl, &cl);
245: if (err)
246: return err;
247: }
248: }
249: return ENOENT;
250: }
251:
252: /*
253: * Find empty directory entry and put new entry on it.
254: *
255: * @fmp: fatfs mount point
256: * @sec: sector#
257: * @np: pointer to fat node
258: */
259: static int
260: fat_add_dirent(struct fatfsmount *fmp, u_long sec, struct fatfs_node *np)
261: {
262: struct fat_dirent *de;
263: int err, i;
264:
265: err = fat_read_dirent(fmp, sec);
266: if (err)
267: return err;
268:
269: de = (struct fat_dirent *)fmp->dir_buf;
270: for (i = 0; i < DIR_PER_SEC; i++) {
271: if (IS_DELETED(de) || IS_EMPTY(de))
272: goto found;
273: DPRINTF(("fat_add_dirent: scan %s\n", de->name));
274: de++;
275: }
276: return ENOENT;
277:
278: found:
279: DPRINTF(("fat_add_dirent: found. sec=%d\n", sec));
280: memcpy(de, &np->dirent, sizeof(struct fat_dirent));
281: err = fat_write_dirent(fmp, sec);
282: return err;
283: }
284:
285: /*
286: * Find empty directory entry and put new entry on it.
287: * This search is done only in directory of specified cluster.
288: * @dvp: vnode for directory.
289: * @np: pointer to fat node
290: */
291: int
292: fatfs_add_node(vnode_t dvp, struct fatfs_node *np)
293: {
294: struct fatfsmount *fmp;
295: u_long cl, sec;
296: int i, err;
297: u_long next;
298:
299: fmp = (struct fatfsmount *)dvp->v_mount->m_data;
300: cl = dvp->v_blkno;
301:
302: DPRINTF(("fatfs_add_node: cl=%d\n", cl));
303:
304: if (cl == CL_ROOT) {
305: /* Add entry in root directory */
306: for (sec = fmp->root_start; sec < fmp->data_start; sec++) {
307: err = fat_add_dirent(fmp, sec, np);
308: if (err != ENOENT)
309: return err;
310: }
311: } else {
312: /* Search entry in sub directory */
313: while (!IS_EOFCL(fmp, cl)) {
314: sec = cl_to_sec(fmp, cl);
315: for (i = 0; i < fmp->sec_per_cl; i++) {
316: err = fat_add_dirent(fmp, sec, np);
317: if (err != ENOENT)
318: return err;
319: sec++;
320: }
321: err = fat_next_cluster(fmp, cl, &next);
322: if (err)
323: return err;
324: cl = next;
325: }
326: /* No entry found, add one more free cluster for directory */
327: DPRINTF(("fatfs_add_node: expand dir\n"));
328: err = fat_expand_dir(fmp, cl, &next);
329: if (err)
330: return err;
331:
332: /* Initialize free cluster. */
333: memset(fmp->dir_buf, 0, SEC_SIZE);
334: sec = cl_to_sec(fmp, next);
335: for (i = 0; i < fmp->sec_per_cl; i++) {
336: err = fat_write_dirent(fmp, sec);
337: if (err)
338: return err;
339: sec++;
340: }
341: /* Try again */
342: sec = cl_to_sec(fmp, next);
343: err = fat_add_dirent(fmp, sec, np);
344: return err;
345: }
346: return ENOENT;
347: }
348:
349: /*
350: * Put directory entry.
351: * @fmp: fat mount data
352: * @np: pointer to fat node
353: */
354: int
355: fatfs_put_node(struct fatfsmount *fmp, struct fatfs_node *np)
356: {
357: int err;
358:
359: err = fat_read_dirent(fmp, np->sector);
360: if (err)
361: return err;
362:
363: memcpy(fmp->dir_buf + np->offset, &np->dirent,
364: sizeof(struct fat_dirent));
365:
366: err = fat_write_dirent(fmp, np->sector);
367: return err;
368: }
369:
CVSweb