[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     ! 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