[BACK]Return to fatfs_node.c CVS log [TXT][DIR] Up to [local] / prex / usr / server / fs / fatfs

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