|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/server/fs/fatfs/fatfs_node.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
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 <sys/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 error; 49 50 if ((error = bread(fmp->dev, sec, &bp)) != 0) 51 return error; 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 error, i; 85 86 error = fat_read_dirent(fmp, sec); 87 if (error) 88 return error; 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, error; 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 error = fat_lookup_dirent(fmp, sec, fat_name, np); 142 if (error != EAGAIN) 143 return error; 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 error = fat_lookup_dirent(fmp, sec, fat_name, 151 np); 152 if (error != EAGAIN) 153 return error; 154 sec++; 155 } 156 error = fat_next_cluster(fmp, cl, &cl); 157 if (error) 158 return error; 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 error, i; 180 181 error = fat_read_dirent(fmp, sec); 182 if (error) 183 return error; 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, error; 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 error = fat_get_dirent(fmp, sec, index, &cur_index, np); 230 if (error != EAGAIN) 231 return error; 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 error = fat_get_dirent(fmp, sec, index, 239 &cur_index, np); 240 if (error != EAGAIN) 241 return error; 242 sec++; 243 } 244 error = fat_next_cluster(fmp, cl, &cl); 245 if (error) 246 return error; 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 error, i; 264 265 error = fat_read_dirent(fmp, sec); 266 if (error) 267 return error; 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 error = fat_write_dirent(fmp, sec); 282 return error; 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, error; 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 error = fat_add_dirent(fmp, sec, np); 308 if (error != ENOENT) 309 return error; 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 error = fat_add_dirent(fmp, sec, np); 317 if (error != ENOENT) 318 return error; 319 sec++; 320 } 321 error = fat_next_cluster(fmp, cl, &next); 322 if (error) 323 return error; 324 cl = next; 325 } 326 /* No entry found, add one more free cluster for directory */ 327 DPRINTF(("fatfs_add_node: expand dir\n")); 328 error = fat_expand_dir(fmp, cl, &next); 329 if (error) 330 return error; 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 error = fat_write_dirent(fmp, sec); 337 if (error) 338 return error; 339 sec++; 340 } 341 /* Try again */ 342 sec = cl_to_sec(fmp, next); 343 error = fat_add_dirent(fmp, sec, np); 344 return error; 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 error; 358 359 error = fat_read_dirent(fmp, np->sector); 360 if (error) 361 return error; 362 363 memcpy(fmp->dir_buf + np->offset, &np->dirent, 364 sizeof(struct fat_dirent)); 365 366 error = fat_write_dirent(fmp, np->sector); 367 return error; 368 } 369 /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |