1 /* 2 * JFFS2 -- Journalling Flash File System, Version 2. 3 * 4 * Copyright (C) 2001-2003 Free Software Foundation, Inc. 5 * 6 * Created by Dominic Ostrowski <[email protected]> 7 * Contributors: David Woodhouse, Nick Garnett, Richard Panton. 8 * 9 * For licensing information, see the file 'LICENCE' in this directory. 10 * 11 * $Id: fs-ecos.c,v 1.44 2005/07/24 15:29:57 dedekind Exp $ 12 * 13 */ 14 15 #include <stdio.h> //prife for SEEK_SET SEEK_CUR SEEK_END 16 #include <linux/kernel.h> 17 #include "nodelist.h" 18 #include <linux/pagemap.h> 19 #include <linux/crc32.h> 20 #include "compr.h" 21 #include <string.h> 22 23 #include <rtdevice.h> 24 25 //-------------------------------------------- 26 cyg_mtab_entry *cyg_cdir_mtab_entry = NULL; 27 cyg_dir cyg_cdir_dir = CYG_DIR_NULL; 28 //========================================================================== 29 // Default functions 30 31 __externC int cyg_fileio_enosys() { return ENOSYS; } 32 __externC int cyg_fileio_erofs() { return EROFS; } 33 __externC int cyg_fileio_enoerr() { return ENOERR; } 34 __externC int cyg_fileio_enotdir() { return ENOTDIR; } 35 36 __externC cyg_bool cyg_fileio_seltrue (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info) 37 { return 1; } 38 39 //-------------------------------------------- 40 //========================================================================== 41 // Forward definitions 42 43 // Filesystem operations 44 int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte); 45 static int jffs2_umount(cyg_mtab_entry * mte); 46 int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 47 int mode, cyg_file * fte); 48 #ifdef CYGOPT_FS_JFFS2_WRITE 49 static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, 50 const char *name); 51 static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name); 52 static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name); 53 static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1, 54 const char *name1, cyg_dir dir2, const char *name2); 55 static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1, 56 cyg_dir dir2, const char *name2, int type); 57 #endif 58 static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 59 cyg_file * fte); 60 static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 61 cyg_dir * dir_out); 62 static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 63 struct stat *buf); 64 static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 65 int key, void *buf, int len); 66 static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 67 int key, void *buf, int len); 68 69 // File operations 70 int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); 71 #ifdef CYGOPT_FS_JFFS2_WRITE 72 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); 73 #endif 74 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence); 75 static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, 76 CYG_ADDRWORD data); 77 static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode); 78 static int jffs2_fo_close(struct CYG_FILE_TAG *fp); 79 static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf); 80 static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, 81 int len); 82 static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, 83 int len); 84 85 // Directory operations 86 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); 87 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence); 88 89 90 static int jffs2_read_inode (struct _inode *inode); 91 static void jffs2_clear_inode (struct _inode *inode); 92 static int jffs2_truncate_file (struct _inode *inode); 93 94 //========================================================================== 95 // Filesystem table entries 96 97 // ------------------------------------------------------------------------- 98 // Fstab entry. 99 // This defines the entry in the filesystem table. 100 // For simplicity we use _FILESYSTEM synchronization for all accesses since 101 // we should never block in any filesystem operations. 102 103 #ifdef CYGOPT_FS_JFFS2_WRITE 104 FSTAB_ENTRY(jffs2_fste, "jffs2", 0, 105 CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM, 106 jffs2_mount, 107 jffs2_umount, 108 jffs2_open, 109 jffs2_ops_unlink, 110 jffs2_ops_mkdir, 111 jffs2_ops_rmdir, 112 jffs2_ops_rename, 113 jffs2_ops_link, 114 jffs2_opendir, 115 jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo); 116 #else 117 FSTAB_ENTRY(jffs2_fste, "jffs2", 0, 118 CYG_SYNCMODE_FILE_FILESYSTEM | CYG_SYNCMODE_IO_FILESYSTEM, 119 jffs2_mount, 120 jffs2_umount, 121 jffs2_open, 122 (cyg_fsop_unlink *)cyg_fileio_erofs, 123 (cyg_fsop_mkdir *)cyg_fileio_erofs, 124 (cyg_fsop_rmdir *)cyg_fileio_erofs, 125 (cyg_fsop_rename *)cyg_fileio_erofs, 126 (cyg_fsop_link *)cyg_fileio_erofs, 127 jffs2_opendir, 128 jffs2_chdir, jffs2_stat, jffs2_getinfo, jffs2_setinfo); 129 #endif 130 131 // ------------------------------------------------------------------------- 132 // File operations. 133 // This set of file operations are used for normal open files. 134 135 cyg_fileops jffs2_fileops = { 136 jffs2_fo_read, 137 #ifdef CYGOPT_FS_JFFS2_WRITE 138 jffs2_fo_write, 139 #else 140 (cyg_fileop_write *) cyg_fileio_erofs, 141 #endif 142 jffs2_fo_lseek, 143 jffs2_fo_ioctl, 144 cyg_fileio_seltrue, 145 jffs2_fo_fsync, 146 jffs2_fo_close, 147 jffs2_fo_fstat, 148 jffs2_fo_getinfo, 149 jffs2_fo_setinfo 150 }; 151 152 // ------------------------------------------------------------------------- 153 // Directory file operations. 154 // This set of operations are used for open directories. Most entries 155 // point to error-returning stub functions. Only the read, lseek and 156 // close entries are functional. 157 158 cyg_fileops jffs2_dirops = { 159 jffs2_fo_dirread, 160 (cyg_fileop_write *) cyg_fileio_enosys, 161 jffs2_fo_dirlseek, 162 (cyg_fileop_ioctl *) cyg_fileio_enosys, 163 cyg_fileio_seltrue, 164 (cyg_fileop_fsync *) cyg_fileio_enosys, 165 jffs2_fo_close, 166 (cyg_fileop_fstat *) cyg_fileio_enosys, 167 (cyg_fileop_getinfo *) cyg_fileio_enosys, 168 (cyg_fileop_setinfo *) cyg_fileio_enosys 169 }; 170 171 //========================================================================== 172 // STATIC VARIABLES !!! 173 174 static unsigned char gc_buffer[PAGE_CACHE_SIZE]; //avoids malloc when user may be under memory pressure 175 static unsigned char n_fs_mounted = 0; // a counter to track the number of jffs2 instances mounted 176 177 //========================================================================== 178 // Directory operations 179 180 struct jffs2_dirsearch { 181 struct _inode *dir; // directory to search 182 const unsigned char *path; // path to follow 183 struct _inode *node; // Node found 184 const unsigned char *name; // last name fragment used 185 int namelen; // name fragment length 186 cyg_bool last; // last name in path? 187 }; 188 189 typedef struct jffs2_dirsearch jffs2_dirsearch; 190 191 //========================================================================== 192 // Ref count and nlink management 193 194 195 // FIXME: This seems like real cruft. Wouldn't it be better just to do the 196 // right thing? 197 static void icache_evict(struct _inode *root_i, struct _inode *i) 198 { 199 struct _inode *this = root_i, *next; 200 201 restart: 202 D2(printf("icache_evict\n")); 203 // If this is an absolute search path from the root, 204 // remove all cached inodes with i_count of zero (these are only 205 // held where needed for dotdot filepaths) 206 while (this) { 207 next = this->i_cache_next; 208 if (this != i && this->i_count == 0) { 209 struct _inode *parent = this->i_parent; 210 if (this->i_cache_next) 211 this->i_cache_next->i_cache_prev = this->i_cache_prev; 212 if (this->i_cache_prev) 213 this->i_cache_prev->i_cache_next = this->i_cache_next; 214 jffs2_clear_inode(this); 215 memset(this, 0x5a, sizeof(*this)); 216 rt_free(this); 217 if (parent && parent != this) { 218 parent->i_count--; 219 this = root_i; 220 goto restart; 221 } 222 } 223 this = next; 224 } 225 } 226 227 //========================================================================== 228 // Directory search 229 230 // ------------------------------------------------------------------------- 231 // init_dirsearch() 232 // Initialize a dirsearch object to start a search 233 234 static void init_dirsearch(jffs2_dirsearch * ds, 235 struct _inode *dir, const unsigned char *name) 236 { 237 D2(printf("init_dirsearch name = %s\n", name)); 238 D2(printf("init_dirsearch dir = %x\n", dir)); 239 240 dir->i_count++; 241 ds->dir = dir; 242 ds->path = name; 243 ds->node = dir; 244 ds->name = name; 245 ds->namelen = 0; 246 ds->last = false; 247 } 248 249 // ------------------------------------------------------------------------- 250 // find_entry() 251 // Search a single directory for the next name in a path and update the 252 // dirsearch object appropriately. 253 254 static int find_entry(jffs2_dirsearch * ds) 255 { 256 struct _inode *dir = ds->dir; 257 const unsigned char *name = ds->path; 258 const unsigned char *n = name; 259 char namelen = 0; 260 struct _inode *d; 261 262 D2(printf("find_entry\n")); 263 264 // check that we really have a directory 265 if (!S_ISDIR(dir->i_mode)) 266 return ENOTDIR; 267 268 // Isolate the next element of the path name. 269 while (*n != '\0' && *n != '/') 270 n++, namelen++; 271 272 // Check if this is the last path element. 273 while( *n == '/') n++; 274 if (*n == '\0') 275 ds->last = true; 276 277 // update name in dirsearch object 278 ds->name = name; 279 ds->namelen = namelen; 280 281 if (name[0] == '.') 282 switch (namelen) { 283 default: 284 break; 285 case 2: 286 // Dot followed by not Dot, treat as any other name 287 if (name[1] != '.') 288 break; 289 // Dot Dot 290 // Move back up the search path 291 D2(printf("find_entry found ..\n")); 292 ds->dir = ds->node; 293 ds->node = ds->dir->i_parent; 294 ds->node->i_count++; 295 return ENOERR; 296 case 1: 297 // Dot is consumed 298 D2(printf("find_entry found .\n")); 299 ds->node = ds->dir; 300 ds->dir->i_count++; 301 return ENOERR; 302 } 303 304 // Here we have the name and its length set up. 305 // Search the directory for a matching entry 306 307 D2(printf("find_entry for name = %s\n", ds->path)); 308 d = jffs2_lookup(dir, name, namelen); 309 D2(printf("find_entry got dir = %x\n", d)); 310 311 if (d == NULL) 312 return ENOENT; 313 if (IS_ERR(d)) 314 return -PTR_ERR(d); 315 316 // If it's a new directory inode, increase refcount on its parent 317 if (S_ISDIR(d->i_mode) && !d->i_parent) { 318 d->i_parent = dir; 319 dir->i_count++; 320 } 321 322 // pass back the node we have found 323 ds->node = d; 324 return ENOERR; 325 326 } 327 328 // ------------------------------------------------------------------------- 329 // jffs2_find() 330 // Main interface to directory search code. This is used in all file 331 // level operations to locate the object named by the pathname. 332 333 // Returns with use count incremented on both the sought object and 334 // the directory it was found in 335 static int jffs2_find(jffs2_dirsearch * d) 336 { 337 int err; 338 339 D2(printf("jffs2_find for path =%s\n", d->path)); 340 341 // Short circuit empty paths 342 if (*(d->path) == '\0') { 343 d->node->i_count++; 344 return ENOERR; 345 } 346 347 // iterate down directory tree until we find the object 348 // we want. 349 for (;;) { 350 err = find_entry(d); 351 352 if (err != ENOERR) 353 return err; 354 355 if (d->last) 356 return ENOERR; 357 358 /* We're done with it, although it we found a subdir that 359 will have caused the refcount to have been increased */ 360 jffs2_iput(d->dir); 361 362 // Update dirsearch object to search next directory. 363 d->dir = d->node; 364 d->path += d->namelen; 365 while (*(d->path) == '/') 366 d->path++; // skip dirname separators 367 } 368 } 369 370 //========================================================================== 371 // Pathconf support 372 // This function provides support for pathconf() and fpathconf(). 373 374 static int jffs2_pathconf(struct _inode *node, struct cyg_pathconf_info *info) 375 { 376 int err = ENOERR; 377 D2(printf("jffs2_pathconf\n")); 378 379 switch (info->name) { 380 case _PC_LINK_MAX: 381 info->value = LINK_MAX; 382 break; 383 384 case _PC_MAX_CANON: 385 info->value = -1; // not supported 386 err = EINVAL; 387 break; 388 389 case _PC_MAX_INPUT: 390 info->value = -1; // not supported 391 err = EINVAL; 392 break; 393 394 case _PC_NAME_MAX: 395 info->value = JFFS2_NAME_MAX; 396 break; 397 398 case _PC_PATH_MAX: 399 info->value = JFFS2_PATH_MAX; 400 break; 401 402 case _PC_PIPE_BUF: 403 info->value = -1; // not supported 404 err = EINVAL; 405 break; 406 407 case _PC_ASYNC_IO: 408 info->value = -1; // not supported 409 err = EINVAL; 410 break; 411 412 case _PC_CHOWN_RESTRICTED: 413 info->value = -1; // not supported 414 err = EINVAL; 415 break; 416 417 case _PC_NO_TRUNC: 418 info->value = 0; 419 break; 420 421 case _PC_PRIO_IO: 422 info->value = 0; 423 break; 424 425 case _PC_SYNC_IO: 426 info->value = 0; 427 break; 428 429 case _PC_VDISABLE: 430 info->value = -1; // not supported 431 err = EINVAL; 432 break; 433 434 default: 435 err = EINVAL; 436 break; 437 } 438 439 return err; 440 } 441 442 //========================================================================== 443 // Filesystem operations 444 // ------------------------------------------------------------------------- 445 // jffs2_mount() 446 // Process a mount request. This mainly creates a root for the 447 // filesystem. 448 static int jffs2_read_super(struct super_block *sb) 449 { 450 Cyg_ErrNo err; 451 struct jffs2_sb_info *c; 452 struct rt_mtd_nor_device *device; 453 454 c = JFFS2_SB_INFO(sb); 455 device = RT_MTD_NOR_DEVICE(sb->s_dev); 456 457 /* initialize mutex lock */ 458 init_MUTEX(&c->alloc_sem); 459 init_MUTEX(&c->erase_free_sem); 460 461 /* sector size is the erase block size */ 462 c->sector_size = device->block_size; 463 c->flash_size = (device->block_end - device->block_start) * device->block_size; 464 c->cleanmarker_size = sizeof(struct jffs2_unknown_node); 465 466 err = jffs2_do_mount_fs(c); 467 if (err) return -err; 468 469 D1(printk(KERN_DEBUG "jffs2_read_super(): Getting root inode\n")); 470 sb->s_root = jffs2_iget(sb, 1); 471 if (IS_ERR(sb->s_root)) { 472 D1(printk(KERN_WARNING "get root inode failed\n")); 473 err = PTR_ERR(sb->s_root); 474 sb->s_root = NULL; 475 goto out_nodes; 476 } 477 return 0; 478 479 out_nodes: 480 jffs2_free_ino_caches(c); 481 jffs2_free_raw_node_refs(c); 482 rt_free(c->blocks); 483 484 return err; 485 } 486 487 int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte) 488 { 489 // extern cyg_mtab_entry cyg_mtab[], cyg_mtab_end; 490 struct super_block *jffs2_sb = NULL; 491 struct jffs2_sb_info *c; 492 // cyg_mtab_entry *m; 493 cyg_io_handle_t t; 494 Cyg_ErrNo err; 495 496 D2(printf("jffs2_mount\n")); 497 498 //prife 499 // err = cyg_io_lookup(mte->devname, &t); 500 // if (err != ENOERR) 501 // return -err; 502 503 // // Iterate through the mount table to see if we're mounted 504 // // FIXME: this should be done better - perhaps if the superblock 505 // // can be stored as an inode in the icache. 506 // for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) { 507 // // stop if there are more than the configured maximum 508 // if (m - &cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) { 509 // m = &cyg_mtab_end; 510 // break; 511 // } 512 // if (m->valid && strcmp(m->fsname, "jffs2") == 0 && 513 // strcmp(m->devname, mte->devname) == 0) { 514 // jffs2_sb = (struct super_block *) m->data; 515 // } 516 // } 517 jffs2_sb = NULL; 518 t = (cyg_io_handle_t)mte->data; //get from dfs_jffs2; 519 if (jffs2_sb == NULL) { 520 jffs2_sb = rt_malloc(sizeof (struct super_block)); 521 522 if (jffs2_sb == NULL) 523 return ENOMEM; 524 525 c = JFFS2_SB_INFO(jffs2_sb); 526 memset(jffs2_sb, 0, sizeof (struct super_block)); 527 jffs2_sb->s_dev = t; 528 529 c->inocache_list = rt_malloc(sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE); 530 if (!c->inocache_list) { 531 rt_free(jffs2_sb); 532 return ENOMEM; 533 } 534 memset(c->inocache_list, 0, sizeof(struct jffs2_inode_cache *) * INOCACHE_HASHSIZE); 535 if (n_fs_mounted++ == 0) { 536 jffs2_create_slab_caches(); // No error check, cannot fail 537 jffs2_compressors_init(); 538 } 539 540 err = jffs2_read_super(jffs2_sb); 541 542 if (err) { 543 if (--n_fs_mounted == 0) { 544 jffs2_destroy_slab_caches(); 545 jffs2_compressors_exit(); 546 } 547 548 rt_free(jffs2_sb); 549 rt_free(c->inocache_list); 550 return err; 551 } 552 553 jffs2_sb->s_root->i_parent = jffs2_sb->s_root; // points to itself, no dotdot paths above mountpoint 554 jffs2_sb->s_root->i_cache_prev = NULL; // root inode, so always null 555 jffs2_sb->s_root->i_cache_next = NULL; 556 jffs2_sb->s_root->i_count = 1; // Ensures the root inode is always in ram until umount 557 558 D2(printf("jffs2_mount erasing pending blocks\n")); 559 #ifdef CYGOPT_FS_JFFS2_WRITE 560 if (!jffs2_is_readonly(c)) 561 jffs2_erase_pending_blocks(c,0); 562 #endif 563 #ifdef CYGOPT_FS_JFFS2_GCTHREAD 564 jffs2_start_garbage_collect_thread(c); 565 #endif 566 } 567 mte->data = (CYG_ADDRWORD) jffs2_sb; 568 569 jffs2_sb->s_mount_count++; 570 mte->root = (cyg_dir) jffs2_sb->s_root; 571 D2(printf("jffs2_mounted superblock at %x\n", mte->root)); 572 573 return ENOERR; 574 } 575 576 extern cyg_dir cyg_cdir_dir; 577 extern cyg_mtab_entry *cyg_cdir_mtab_entry; 578 579 // ------------------------------------------------------------------------- 580 // jffs2_umount() 581 // Unmount the filesystem. 582 583 static int jffs2_umount(cyg_mtab_entry * mte) 584 { 585 struct _inode *root = (struct _inode *) mte->root; 586 struct super_block *jffs2_sb = root->i_sb; 587 struct jffs2_sb_info *c = JFFS2_SB_INFO(jffs2_sb); 588 struct jffs2_full_dirent *fd, *next; 589 590 D2(printf("jffs2_umount\n")); 591 592 // Only really umount if this is the only mount 593 if (jffs2_sb->s_mount_count == 1) { 594 icache_evict(root, NULL); 595 if (root->i_cache_next != NULL) { 596 struct _inode *inode = root; 597 printf("Refuse to unmount.\n"); 598 while (inode) { 599 printf("Ino #%u has use count %d\n", 600 inode->i_ino, inode->i_count); 601 inode = inode->i_cache_next; 602 } 603 // root icount was set to 1 on mount 604 return EBUSY; 605 } 606 if (root->i_count == 2 && 607 cyg_cdir_mtab_entry == mte && 608 cyg_cdir_dir == (cyg_dir)root && 609 !strcmp(mte->name, "/")) { 610 /* If we were mounted on root, there's no 611 way for the cwd to change out and free 612 the file system for unmounting. So we hack 613 it -- if cwd is '/' we unset it. Perhaps 614 we should allow chdir(NULL) to unset 615 cyg_cdir_dir? */ 616 cyg_cdir_dir = CYG_DIR_NULL; 617 jffs2_iput(root); 618 } 619 /* Argh. The fileio code sets this; never clears it */ 620 if (cyg_cdir_mtab_entry == mte) 621 cyg_cdir_mtab_entry = NULL; 622 623 if (root->i_count != 1) { 624 printf("Ino #1 has use count %d\n", 625 root->i_count); 626 return EBUSY; 627 } 628 #ifdef CYGOPT_FS_JFFS2_GCTHREAD 629 jffs2_stop_garbage_collect_thread(c); 630 #endif 631 jffs2_iput(root); // Time to free the root inode 632 633 // free directory entries 634 for (fd = root->jffs2_i.dents; fd; fd = next) { 635 next=fd->next; 636 jffs2_free_full_dirent(fd); 637 } 638 639 rt_free(root); 640 //Clear root inode 641 //root_i = NULL; 642 643 // Clean up the super block and root inode 644 jffs2_free_ino_caches(c); 645 jffs2_free_raw_node_refs(c); 646 rt_free(c->blocks); 647 rt_free(c->inocache_list); 648 rt_free(jffs2_sb); 649 // Clear superblock & root pointer 650 mte->root = CYG_DIR_NULL; 651 mte->data = 0; 652 mte->fs->data = 0; // fstab entry, visible to all mounts. No current mount 653 // That's all folks. 654 D2(printf("jffs2_umount No current mounts\n")); 655 } else { 656 jffs2_sb->s_mount_count--; 657 } 658 if (--n_fs_mounted == 0) { 659 jffs2_destroy_slab_caches(); 660 jffs2_compressors_exit(); 661 } 662 return ENOERR; 663 } 664 665 // ------------------------------------------------------------------------- 666 // jffs2_open() 667 // Open a file for reading or writing. 668 669 int jffs2_open(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 670 int mode, cyg_file * file) 671 { 672 673 jffs2_dirsearch ds; 674 struct _inode *node = NULL; 675 int err; 676 677 D2(printf("jffs2_open\n")); 678 679 /* If no chdir has been called and we were the first file system 680 mounted, we get called with dir == NULL. Deal with it */ 681 if (!dir) 682 dir = mte->root; 683 684 #ifndef CYGOPT_FS_JFFS2_WRITE 685 if (mode & (O_CREAT|O_TRUNC|O_WRONLY)) 686 return EROFS; 687 #endif 688 init_dirsearch(&ds, (struct _inode *) dir, 689 (const unsigned char *) name); 690 691 err = jffs2_find(&ds); 692 693 if (err == ENOENT) { 694 #ifdef CYGOPT_FS_JFFS2_WRITE 695 if (ds.last && (mode & O_CREAT)) { 696 697 // No node there, if the O_CREAT bit is set then we must 698 // create a new one. The dir and name fields of the dirsearch 699 // object will have been updated so we know where to put it. 700 701 err = jffs2_create(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR|S_IFREG, &node); 702 703 if (err != 0) { 704 //Possible orphaned inode on the flash - but will be gc'd 705 jffs2_iput(ds.dir); 706 return -err; 707 } 708 709 err = ENOERR; 710 } 711 #endif 712 } else if (err == ENOERR) { 713 // The node exists. If the O_CREAT and O_EXCL bits are set, we 714 // must fail the open. 715 716 if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { 717 jffs2_iput(ds.node); 718 err = EEXIST; 719 } else 720 node = ds.node; 721 } 722 723 // Finished with the directory now 724 jffs2_iput(ds.dir); 725 726 if (err != ENOERR) 727 return err; 728 729 // Check that we actually have a file here 730 if (S_ISDIR(node->i_mode)) { 731 jffs2_iput(node); 732 return EISDIR; 733 } 734 735 // If the O_TRUNC bit is set we must clean out the file data. 736 if (mode & O_TRUNC) { 737 #ifdef CYGOPT_FS_JFFS2_WRITE 738 err = jffs2_truncate_file(node); 739 if (err) { 740 jffs2_iput(node); 741 return err; 742 } 743 #else 744 jffs2_iput(node); 745 return EROFS; 746 #endif 747 } 748 749 // Initialise the file object 750 file->f_flag = mode & CYG_FILE_MODE_MASK; 751 file->f_type = CYG_FILE_TYPE_FILE; 752 file->f_ops = &jffs2_fileops; 753 file->f_offset = (mode & O_APPEND) ? node->i_size : 0; 754 file->f_data = (CYG_ADDRWORD) node; 755 file->f_xops = 0; 756 757 return ENOERR; 758 } 759 760 #ifdef CYGOPT_FS_JFFS2_WRITE 761 // ------------------------------------------------------------------------- 762 // jffs2_ops_unlink() 763 // Remove a file link from its directory. 764 765 static int jffs2_ops_unlink(cyg_mtab_entry * mte, cyg_dir dir, const char *name) 766 { 767 jffs2_dirsearch ds; 768 int err; 769 770 D2(printf("jffs2_ops_unlink\n")); 771 772 init_dirsearch(&ds, (struct _inode *) dir, 773 (const unsigned char *)name); 774 775 err = jffs2_find(&ds); 776 777 if (err != ENOERR) { 778 jffs2_iput(ds.dir); 779 return err; 780 } 781 782 // Cannot unlink directories, use rmdir() instead 783 if (S_ISDIR(ds.node->i_mode)) { 784 jffs2_iput(ds.dir); 785 jffs2_iput(ds.node); 786 return EPERM; 787 } 788 789 // Delete it from its directory 790 791 err = jffs2_unlink(ds.dir, ds.node, ds.name); 792 jffs2_iput(ds.dir); 793 jffs2_iput(ds.node); 794 795 return -err; 796 } 797 798 // ------------------------------------------------------------------------- 799 // jffs2_ops_mkdir() 800 // Create a new directory. 801 802 static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name) 803 { 804 jffs2_dirsearch ds; 805 int err; 806 807 D2(printf("jffs2_ops_mkdir\n")); 808 809 init_dirsearch(&ds, (struct _inode *) dir, 810 (const unsigned char *)name); 811 812 err = jffs2_find(&ds); 813 814 if (err == ENOENT) { 815 if (ds.last) { 816 // The entry does not exist, and it is the last element in 817 // the pathname, so we can create it here. 818 819 err = -jffs2_mkdir(ds.dir, ds.name, S_IRUGO|S_IXUGO|S_IWUSR); 820 } 821 // If this was not the last element, then an intermediate 822 // directory does not exist. 823 } else { 824 // If there we no error, something already exists with that 825 // name, so we cannot create another one. 826 if (err == ENOERR) { 827 jffs2_iput(ds.node); 828 err = EEXIST; 829 } 830 } 831 jffs2_iput(ds.dir); 832 return err; 833 } 834 835 // ------------------------------------------------------------------------- 836 // jffs2_ops_rmdir() 837 // Remove a directory. 838 839 static int jffs2_ops_rmdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name) 840 { 841 jffs2_dirsearch ds; 842 int err; 843 844 D2(printf("jffs2_ops_rmdir\n")); 845 846 init_dirsearch(&ds, (struct _inode *) dir, 847 (const unsigned char *)name); 848 849 err = jffs2_find(&ds); 850 851 if (err != ENOERR) { 852 jffs2_iput(ds.dir); 853 return err; 854 } 855 856 // Check that this is actually a directory. 857 if (!S_ISDIR(ds.node->i_mode)) { 858 jffs2_iput(ds.dir); 859 jffs2_iput(ds.node); 860 return EPERM; 861 } 862 863 err = jffs2_rmdir(ds.dir, ds.node, ds.name); 864 865 jffs2_iput(ds.dir); 866 jffs2_iput(ds.node); 867 return -err; 868 } 869 870 // ------------------------------------------------------------------------- 871 // jffs2_ops_rename() 872 // Rename a file/dir. 873 874 static int jffs2_ops_rename(cyg_mtab_entry * mte, cyg_dir dir1, 875 const char *name1, cyg_dir dir2, const char *name2) 876 { 877 jffs2_dirsearch ds1, ds2; 878 int err; 879 880 D2(printf("jffs2_ops_rename\n")); 881 882 init_dirsearch(&ds1, (struct _inode *) dir1, 883 (const unsigned char *)name1); 884 885 err = jffs2_find(&ds1); 886 887 if (err != ENOERR) { 888 jffs2_iput(ds1.dir); 889 return err; 890 } 891 892 init_dirsearch(&ds2, (struct _inode *) dir2, 893 (const unsigned char *)name2); 894 895 err = jffs2_find(&ds2); 896 897 // Allow through renames to non-existent objects. 898 if (ds2.last && err == ENOENT) { 899 ds2.node = NULL; 900 err = ENOERR; 901 } 902 903 if (err != ENOERR) { 904 jffs2_iput(ds1.dir); 905 jffs2_iput(ds1.node); 906 jffs2_iput(ds2.dir); 907 return err; 908 } 909 910 // Null rename, just return 911 if (ds1.node == ds2.node) { 912 err = ENOERR; 913 goto out; 914 } 915 916 // First deal with any entry that is at the destination 917 if (ds2.node) { 918 // Check that we are renaming like-for-like 919 920 if (!S_ISDIR(ds1.node->i_mode) && S_ISDIR(ds2.node->i_mode)) { 921 err = EISDIR; 922 goto out; 923 } 924 925 if (S_ISDIR(ds1.node->i_mode) && !S_ISDIR(ds2.node->i_mode)) { 926 err = ENOTDIR; 927 goto out; 928 } 929 930 // Now delete the destination directory entry 931 /* Er, what happened to atomicity of rename()? */ 932 err = -jffs2_unlink(ds2.dir, ds2.node, ds2.name); 933 934 if (err != 0) 935 goto out; 936 937 } 938 // Now we know that there is no clashing node at the destination, 939 // make a new direntry at the destination and delete the old entry 940 // at the source. 941 942 err = -jffs2_rename(ds1.dir, ds1.node, ds1.name, ds2.dir, ds2.name); 943 944 // Update directory times 945 if (!err) 946 ds1.dir->i_ctime = 947 ds1.dir->i_mtime = 948 ds2.dir->i_ctime = ds2.dir->i_mtime = jffs2_get_timestamp(); 949 out: 950 jffs2_iput(ds1.dir); 951 if (S_ISDIR(ds1.node->i_mode)) { 952 /* Renamed a directory to elsewhere... so fix up its 953 i_parent pointer and the i_counts of its old and 954 new parents. */ 955 jffs2_iput(ds1.node->i_parent); 956 ds1.node->i_parent = ds2.dir; 957 /* We effectively increase its use count by not... */ 958 } else { 959 jffs2_iput(ds2.dir); /* ... doing this */ 960 } 961 jffs2_iput(ds1.node); 962 if (ds2.node) 963 jffs2_iput(ds2.node); 964 965 return err; 966 } 967 968 // ------------------------------------------------------------------------- 969 // jffs2_ops_link() 970 // Make a new directory entry for a file. 971 972 static int jffs2_ops_link(cyg_mtab_entry * mte, cyg_dir dir1, const char *name1, 973 cyg_dir dir2, const char *name2, int type) 974 { 975 jffs2_dirsearch ds1, ds2; 976 int err; 977 978 D2(printf("jffs2_ops_link\n")); 979 980 // Only do hard links for now in this filesystem 981 if (type != CYG_FSLINK_HARD) 982 return EINVAL; 983 984 init_dirsearch(&ds1, (struct _inode *) dir1, 985 (const unsigned char *) name1); 986 987 err = jffs2_find(&ds1); 988 989 if (err != ENOERR) { 990 jffs2_iput(ds1.dir); 991 return err; 992 } 993 994 init_dirsearch(&ds2, (struct _inode *) dir2, 995 (const unsigned char *) name2); 996 997 err = jffs2_find(&ds2); 998 999 // Don't allow links to existing objects 1000 if (err == ENOERR) { 1001 jffs2_iput(ds1.dir); 1002 jffs2_iput(ds1.node); 1003 jffs2_iput(ds2.dir); 1004 jffs2_iput(ds2.node); 1005 return EEXIST; 1006 } 1007 1008 // Allow through links to non-existing terminal objects 1009 if (ds2.last && err == ENOENT) { 1010 ds2.node = NULL; 1011 err = ENOERR; 1012 } 1013 1014 if (err != ENOERR) { 1015 jffs2_iput(ds1.dir); 1016 jffs2_iput(ds1.node); 1017 jffs2_iput(ds2.dir); 1018 return err; 1019 } 1020 1021 // Now we know that there is no existing node at the destination, 1022 // make a new direntry at the destination. 1023 1024 err = jffs2_link(ds1.node, ds2.dir, ds2.name); 1025 1026 if (err == 0) 1027 ds1.node->i_ctime = 1028 ds2.dir->i_ctime = ds2.dir->i_mtime = jffs2_get_timestamp(); 1029 1030 jffs2_iput(ds1.dir); 1031 jffs2_iput(ds1.node); 1032 jffs2_iput(ds2.dir); 1033 1034 return -err; 1035 } 1036 #endif /* CYGOPT_FS_JFFS2_WRITE */ 1037 // ------------------------------------------------------------------------- 1038 // jffs2_opendir() 1039 // Open a directory for reading. 1040 1041 static int jffs2_opendir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 1042 cyg_file * file) 1043 { 1044 jffs2_dirsearch ds; 1045 int err; 1046 1047 D2(printf("jffs2_opendir\n")); 1048 1049 init_dirsearch(&ds, (struct _inode *) dir, 1050 (const unsigned char *) name); 1051 1052 err = jffs2_find(&ds); 1053 1054 jffs2_iput(ds.dir); 1055 1056 if (err != ENOERR) 1057 return err; 1058 1059 // check it is really a directory. 1060 if (!S_ISDIR(ds.node->i_mode)) { 1061 jffs2_iput(ds.node); 1062 return ENOTDIR; 1063 } 1064 1065 // Initialize the file object, setting the f_ops field to a 1066 // special set of file ops. 1067 1068 file->f_flag = 0; 1069 file->f_type = CYG_FILE_TYPE_FILE; 1070 file->f_ops = &jffs2_dirops; 1071 file->f_offset = 0; 1072 file->f_data = (CYG_ADDRWORD) ds.node; 1073 file->f_xops = 0; 1074 1075 return ENOERR; 1076 1077 } 1078 1079 // ------------------------------------------------------------------------- 1080 // jffs2_chdir() 1081 // Change directory support. 1082 1083 static int jffs2_chdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 1084 cyg_dir * dir_out) 1085 { 1086 D2(printf("jffs2_chdir\n")); 1087 1088 if (dir_out != NULL) { 1089 // This is a request to get a new directory pointer in 1090 // *dir_out. 1091 1092 jffs2_dirsearch ds; 1093 int err; 1094 1095 init_dirsearch(&ds, (struct _inode *) dir, 1096 (const unsigned char *) name); 1097 1098 err = jffs2_find(&ds); 1099 jffs2_iput(ds.dir); 1100 1101 if (err != ENOERR) 1102 return err; 1103 1104 // check it is a directory 1105 if (!S_ISDIR(ds.node->i_mode)) { 1106 jffs2_iput(ds.node); 1107 return ENOTDIR; 1108 } 1109 1110 // Pass it out 1111 *dir_out = (cyg_dir) ds.node; 1112 } else { 1113 // If no output dir is required, this means that the mte and 1114 // dir arguments are the current cdir setting and we should 1115 // forget this fact. 1116 1117 struct _inode *node = (struct _inode *) dir; 1118 1119 // Just decrement directory reference count. 1120 jffs2_iput(node); 1121 } 1122 1123 return ENOERR; 1124 } 1125 1126 // ------------------------------------------------------------------------- 1127 // jffs2_stat() 1128 // Get struct stat info for named object. 1129 1130 static int jffs2_stat(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 1131 struct stat *buf) 1132 { 1133 jffs2_dirsearch ds; 1134 int err; 1135 1136 D2(printf("jffs2_stat\n")); 1137 1138 init_dirsearch(&ds, (struct _inode *) dir, 1139 (const unsigned char *) name); 1140 1141 err = jffs2_find(&ds); 1142 jffs2_iput(ds.dir); 1143 1144 if (err != ENOERR) 1145 return err; 1146 1147 // Fill in the status 1148 buf->st_mode = ds.node->i_mode; 1149 buf->st_ino = ds.node->i_ino; 1150 buf->st_dev = 0; 1151 buf->st_nlink = ds.node->i_nlink; 1152 buf->st_uid = ds.node->i_uid; 1153 buf->st_gid = ds.node->i_gid; 1154 buf->st_size = ds.node->i_size; 1155 buf->st_atime = ds.node->i_atime; 1156 buf->st_mtime = ds.node->i_mtime; 1157 buf->st_ctime = ds.node->i_ctime; 1158 1159 jffs2_iput(ds.node); 1160 1161 return ENOERR; 1162 } 1163 1164 // ------------------------------------------------------------------------- 1165 // jffs2_getinfo() 1166 // Getinfo. Currently only support pathconf(). 1167 1168 static int jffs2_getinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 1169 int key, void *buf, int len) 1170 { 1171 jffs2_dirsearch ds; 1172 int err; 1173 1174 D2(printf("jffs2_getinfo\n")); 1175 1176 init_dirsearch(&ds, (struct _inode *) dir, 1177 (const unsigned char *) name); 1178 1179 err = jffs2_find(&ds); 1180 jffs2_iput(ds.dir); 1181 1182 if (err != ENOERR) 1183 return err; 1184 1185 switch (key) { 1186 case FS_INFO_CONF: 1187 err = jffs2_pathconf(ds.node, (struct cyg_pathconf_info *) buf); 1188 break; 1189 1190 default: 1191 err = EINVAL; 1192 } 1193 1194 jffs2_iput(ds.node); 1195 return err; 1196 } 1197 1198 // ------------------------------------------------------------------------- 1199 // jffs2_setinfo() 1200 // Setinfo. Nothing to support here at present. 1201 1202 static int jffs2_setinfo(cyg_mtab_entry * mte, cyg_dir dir, const char *name, 1203 int key, void *buf, int len) 1204 { 1205 // No setinfo keys supported at present 1206 1207 D2(printf("jffs2_setinfo\n")); 1208 1209 return EINVAL; 1210 } 1211 1212 //========================================================================== 1213 // File operations 1214 1215 // ------------------------------------------------------------------------- 1216 // jffs2_fo_read() 1217 // Read data from the file. 1218 1219 int jffs2_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) 1220 { 1221 struct _inode *inode = (struct _inode *) fp->f_data; 1222 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 1223 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 1224 int i; 1225 ssize_t resid = uio->uio_resid; 1226 off_t pos = fp->f_offset; 1227 1228 down(&f->sem); 1229 1230 // Loop over the io vectors until there are none left 1231 for (i = 0; i < uio->uio_iovcnt && pos < inode->i_size; i++) { 1232 int ret; 1233 cyg_iovec *iov = &uio->uio_iov[i]; 1234 off_t len = min(iov->iov_len, inode->i_size - pos); 1235 1236 D2(printf("jffs2_fo_read inode size %d\n", inode->i_size)); 1237 1238 ret = 1239 jffs2_read_inode_range(c, f, 1240 (unsigned char *) iov->iov_base, pos, 1241 len); 1242 if (ret) { 1243 D1(printf 1244 ("jffs2_fo_read(): read_inode_range failed %d\n", 1245 ret)); 1246 uio->uio_resid = resid; 1247 up(&f->sem); 1248 return -ret; 1249 } 1250 resid -= len; 1251 pos += len; 1252 } 1253 1254 // We successfully read some data, update the node's access time 1255 // and update the file offset and transfer residue. 1256 1257 inode->i_atime = jffs2_get_timestamp(); 1258 1259 uio->uio_resid = resid; 1260 fp->f_offset = pos; 1261 1262 up(&f->sem); 1263 1264 return ENOERR; 1265 } 1266 1267 1268 #ifdef CYGOPT_FS_JFFS2_WRITE 1269 // ------------------------------------------------------------------------- 1270 // jffs2_fo_write() 1271 // Write data to file. 1272 static int jffs2_extend_file (struct _inode *inode, struct jffs2_raw_inode *ri, 1273 unsigned long offset) 1274 { 1275 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 1276 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 1277 struct jffs2_full_dnode *fn; 1278 uint32_t phys_ofs, alloc_len; 1279 int ret = 0; 1280 1281 /* Make new hole frag from old EOF to new page */ 1282 D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", 1283 (unsigned int)inode->i_size, offset)); 1284 1285 ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloc_len, ALLOC_NORMAL); 1286 if (ret) 1287 return ret; 1288 1289 down(&f->sem); 1290 1291 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 1292 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); 1293 ri->totlen = cpu_to_je32(sizeof(*ri)); 1294 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); 1295 1296 ri->version = cpu_to_je32(++f->highest_version); 1297 ri->isize = cpu_to_je32(max((uint32_t)inode->i_size, offset)); 1298 1299 ri->offset = cpu_to_je32(inode->i_size); 1300 ri->dsize = cpu_to_je32(offset - inode->i_size); 1301 ri->csize = cpu_to_je32(0); 1302 ri->compr = JFFS2_COMPR_ZERO; 1303 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 1304 ri->data_crc = cpu_to_je32(0); 1305 1306 fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); 1307 jffs2_complete_reservation(c); 1308 if (IS_ERR(fn)) { 1309 ret = PTR_ERR(fn); 1310 up(&f->sem); 1311 return ret; 1312 } 1313 ret = jffs2_add_full_dnode_to_inode(c, f, fn); 1314 if (f->metadata) { 1315 jffs2_mark_node_obsolete(c, f->metadata->raw); 1316 jffs2_free_full_dnode(f->metadata); 1317 f->metadata = NULL; 1318 } 1319 if (ret) { 1320 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in prepare_write, returned %d\n", ret)); 1321 jffs2_mark_node_obsolete(c, fn->raw); 1322 jffs2_free_full_dnode(fn); 1323 up(&f->sem); 1324 return ret; 1325 } 1326 inode->i_size = offset; 1327 up(&f->sem); 1328 return 0; 1329 } 1330 1331 // jffs2_fo_open() 1332 // Truncate a file 1333 static int jffs2_truncate_file (struct _inode *inode) 1334 { 1335 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 1336 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 1337 struct jffs2_full_dnode *new_metadata, * old_metadata; 1338 struct jffs2_raw_inode *ri; 1339 uint32_t phys_ofs, alloclen; 1340 int err; 1341 1342 ri = jffs2_alloc_raw_inode(); 1343 if (!ri) { 1344 return ENOMEM; 1345 } 1346 err = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); 1347 1348 if (err) { 1349 jffs2_free_raw_inode(ri); 1350 return err; 1351 } 1352 down(&f->sem); 1353 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 1354 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); 1355 ri->totlen = cpu_to_je32(sizeof(*ri)); 1356 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); 1357 1358 ri->ino = cpu_to_je32(inode->i_ino); 1359 ri->version = cpu_to_je32(++f->highest_version); 1360 1361 ri->uid = cpu_to_je16(inode->i_uid); 1362 ri->gid = cpu_to_je16(inode->i_gid); 1363 ri->mode = cpu_to_jemode(inode->i_mode); 1364 ri->isize = cpu_to_je32(0); 1365 ri->atime = cpu_to_je32(inode->i_atime); 1366 ri->mtime = cpu_to_je32(jffs2_get_timestamp()); 1367 ri->offset = cpu_to_je32(0); 1368 ri->csize = ri->dsize = cpu_to_je32(0); 1369 ri->compr = JFFS2_COMPR_NONE; 1370 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 1371 ri->data_crc = cpu_to_je32(0); 1372 new_metadata = jffs2_write_dnode(c, f, ri, NULL, 0, 1373 phys_ofs, ALLOC_NORMAL); 1374 if (IS_ERR(new_metadata)) { 1375 jffs2_complete_reservation(c); 1376 jffs2_free_raw_inode(ri); 1377 up(&f->sem); 1378 return PTR_ERR(new_metadata); 1379 } 1380 1381 /* It worked. Update the inode */ 1382 inode->i_mtime = jffs2_get_timestamp(); 1383 inode->i_size = 0; 1384 old_metadata = f->metadata; 1385 jffs2_truncate_fragtree (c, &f->fragtree, 0); 1386 f->metadata = new_metadata; 1387 if (old_metadata) { 1388 jffs2_mark_node_obsolete(c, old_metadata->raw); 1389 jffs2_free_full_dnode(old_metadata); 1390 } 1391 jffs2_free_raw_inode(ri); 1392 1393 up(&f->sem); 1394 jffs2_complete_reservation(c); 1395 1396 return 0; 1397 } 1398 1399 static int jffs2_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) 1400 { 1401 struct _inode *inode = (struct _inode *) fp->f_data; 1402 off_t pos = fp->f_offset; 1403 ssize_t resid = uio->uio_resid; 1404 struct jffs2_raw_inode ri; 1405 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 1406 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 1407 int i; 1408 1409 // If the APPEND mode bit was supplied, force all writes to 1410 // the end of the file. 1411 if (fp->f_flag & CYG_FAPPEND) 1412 pos = fp->f_offset = inode->i_size; 1413 1414 if (pos < 0) 1415 return EINVAL; 1416 1417 memset(&ri, 0, sizeof(ri)); 1418 1419 ri.ino = cpu_to_je32(f->inocache->ino); 1420 ri.mode = cpu_to_jemode(inode->i_mode); 1421 ri.uid = cpu_to_je16(inode->i_uid); 1422 ri.gid = cpu_to_je16(inode->i_gid); 1423 ri.atime = ri.ctime = ri.mtime = cpu_to_je32(jffs2_get_timestamp()); 1424 1425 if (pos > inode->i_size) { 1426 int err; 1427 ri.version = cpu_to_je32(++f->highest_version); 1428 err = jffs2_extend_file(inode, &ri, pos); 1429 if (err) 1430 return -err; 1431 } 1432 ri.isize = cpu_to_je32(inode->i_size); 1433 1434 // Now loop over the iovecs until they are all done, or 1435 // we get an error. 1436 for (i = 0; i < uio->uio_iovcnt; i++) { 1437 cyg_iovec *iov = &uio->uio_iov[i]; 1438 unsigned char *buf = iov->iov_base; 1439 off_t len = iov->iov_len; 1440 1441 uint32_t writtenlen; 1442 int err; 1443 1444 D2(printf("jffs2_fo_write page_start_pos %d\n", pos)); 1445 D2(printf("jffs2_fo_write transfer size %d\n", len)); 1446 1447 err = jffs2_write_inode_range(c, f, &ri, buf, 1448 pos, len, &writtenlen); 1449 if (err) 1450 return -err; 1451 1452 if (writtenlen != len) 1453 return ENOSPC; 1454 1455 pos += len; 1456 resid -= len; 1457 } 1458 1459 // We wrote some data successfully, update the modified and access 1460 // times of the inode, increase its size appropriately, and update 1461 // the file offset and transfer residue. 1462 inode->i_mtime = inode->i_ctime = je32_to_cpu(ri.mtime); 1463 if (pos > inode->i_size) 1464 inode->i_size = pos; 1465 1466 uio->uio_resid = resid; 1467 fp->f_offset = pos; 1468 1469 return ENOERR; 1470 } 1471 #endif /* CYGOPT_FS_JFFS2_WRITE */ 1472 1473 // ------------------------------------------------------------------------- 1474 // jffs2_fo_lseek() 1475 // Seek to a new file position. 1476 1477 static int jffs2_fo_lseek(struct CYG_FILE_TAG *fp, off_t * apos, int whence) 1478 { 1479 struct _inode *node = (struct _inode *) fp->f_data; 1480 off_t pos = *apos; 1481 1482 D2(printf("jffs2_fo_lseek\n")); 1483 1484 switch (whence) { 1485 case SEEK_SET: 1486 // Pos is already where we want to be. 1487 break; 1488 1489 case SEEK_CUR: 1490 // Add pos to current offset. 1491 pos += fp->f_offset; 1492 break; 1493 1494 case SEEK_END: 1495 // Add pos to file size. 1496 pos += node->i_size; 1497 break; 1498 1499 default: 1500 return EINVAL; 1501 } 1502 1503 if (pos < 0 ) 1504 return EINVAL; 1505 1506 // All OK, set fp offset and return new position. 1507 *apos = fp->f_offset = pos; 1508 1509 return ENOERR; 1510 } 1511 1512 // ------------------------------------------------------------------------- 1513 // jffs2_fo_ioctl() 1514 // Handle ioctls. Currently none are defined. 1515 1516 static int jffs2_fo_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, 1517 CYG_ADDRWORD data) 1518 { 1519 // No Ioctls currenly defined. 1520 1521 D2(printf("jffs2_fo_ioctl\n")); 1522 1523 return EINVAL; 1524 } 1525 1526 // ------------------------------------------------------------------------- 1527 // jffs2_fo_fsync(). 1528 // Force the file out to data storage. 1529 1530 static int jffs2_fo_fsync(struct CYG_FILE_TAG *fp, int mode) 1531 { 1532 // Data is always permanently where it belongs, nothing to do 1533 // here. 1534 1535 D2(printf("jffs2_fo_fsync\n")); 1536 1537 return ENOERR; 1538 } 1539 1540 // ------------------------------------------------------------------------- 1541 // jffs2_fo_close() 1542 // Close a file. We just decrement the refcnt and let it go away if 1543 // that is all that is keeping it here. 1544 1545 static int jffs2_fo_close(struct CYG_FILE_TAG *fp) 1546 { 1547 struct _inode *node = (struct _inode *) fp->f_data; 1548 1549 D2(printf("jffs2_fo_close\n")); 1550 1551 jffs2_iput(node); 1552 1553 fp->f_data = 0; // zero data pointer 1554 1555 return ENOERR; 1556 } 1557 1558 // ------------------------------------------------------------------------- 1559 //jffs2_fo_fstat() 1560 // Get file status. 1561 1562 static int jffs2_fo_fstat(struct CYG_FILE_TAG *fp, struct stat *buf) 1563 { 1564 struct _inode *node = (struct _inode *) fp->f_data; 1565 1566 D2(printf("jffs2_fo_fstat\n")); 1567 1568 // Fill in the status 1569 buf->st_mode = node->i_mode; 1570 buf->st_ino = node->i_ino; 1571 buf->st_dev = 0; 1572 buf->st_nlink = node->i_nlink; 1573 buf->st_uid = node->i_uid; 1574 buf->st_gid = node->i_gid; 1575 buf->st_size = node->i_size; 1576 buf->st_atime = node->i_atime; 1577 buf->st_mtime = node->i_mtime; 1578 buf->st_ctime = node->i_ctime; 1579 1580 return ENOERR; 1581 } 1582 1583 // ------------------------------------------------------------------------- 1584 // jffs2_fo_getinfo() 1585 // Get info. Currently only supports fpathconf(). 1586 1587 static int jffs2_fo_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, 1588 int len) 1589 { 1590 struct _inode *node = (struct _inode *) fp->f_data; 1591 int err; 1592 1593 D2(printf("jffs2_fo_getinfo\n")); 1594 1595 switch (key) { 1596 case FS_INFO_CONF: 1597 err = jffs2_pathconf(node, (struct cyg_pathconf_info *) buf); 1598 break; 1599 1600 default: 1601 err = EINVAL; 1602 } 1603 return err; 1604 } 1605 1606 // ------------------------------------------------------------------------- 1607 // jffs2_fo_setinfo() 1608 // Set info. Nothing supported here. 1609 1610 static int jffs2_fo_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, 1611 int len) 1612 { 1613 // No setinfo key supported at present 1614 1615 D2(printf("jffs2_fo_setinfo\n")); 1616 1617 return ENOERR; 1618 } 1619 1620 //========================================================================== 1621 // Directory operations 1622 1623 // ------------------------------------------------------------------------- 1624 // jffs2_fo_dirread() 1625 // Read a single directory entry from a file. 1626 1627 static __inline void filldir(char *nbuf, int nlen, const unsigned char *name, int namlen) 1628 { 1629 int len = nlen < namlen ? nlen : namlen; 1630 memcpy(nbuf, name, len); 1631 nbuf[len] = '\0'; 1632 } 1633 1634 static int jffs2_fo_dirread(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio) 1635 { 1636 struct _inode *d_inode = (struct _inode *) fp->f_data; 1637 struct dirent *ent = (struct dirent *) uio->uio_iov[0].iov_base; 1638 char *nbuf = ent->d_name; 1639 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE 1640 struct _inode *c_ino; 1641 #endif 1642 int nlen = sizeof (ent->d_name) - 1; 1643 off_t len = uio->uio_iov[0].iov_len; 1644 struct jffs2_inode_info *f; 1645 struct _inode *inode = d_inode; 1646 struct jffs2_full_dirent *fd; 1647 unsigned long offset, curofs; 1648 int found = 1; 1649 1650 if (len < sizeof (struct dirent)) 1651 return EINVAL; 1652 1653 D1(printk 1654 (KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", d_inode->i_ino)); 1655 1656 f = JFFS2_INODE_INFO(inode); 1657 1658 offset = fp->f_offset; 1659 1660 if (offset == 0) { 1661 D1(printk 1662 (KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino)); 1663 filldir(nbuf, nlen, (const unsigned char *) ".", 1); 1664 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE 1665 // Flags here are the same as jffs2_mkdir. Make sure 1666 // d_type is the same as st_mode of calling stat. 1667 ent->d_type = 1668 jemode_to_cpu(cpu_to_jemode(S_IRUGO|S_IXUGO|S_IWUSR|S_IFDIR)); 1669 #endif 1670 goto out; 1671 } 1672 if (offset == 1) { 1673 filldir(nbuf, nlen, (const unsigned char *) "..", 2); 1674 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE 1675 // Flags here are the same as jffs2_mkdir. Make sure 1676 // d_type is the same as st_mode of calling stat. 1677 ent->d_type = 1678 jemode_to_cpu(cpu_to_jemode(S_IRUGO|S_IXUGO|S_IWUSR|S_IFDIR)); 1679 #endif 1680 goto out; 1681 } 1682 1683 curofs = 1; 1684 down(&f->sem); 1685 for (fd = f->dents; fd; fd = fd->next) { 1686 1687 curofs++; 1688 /* First loop: curofs = 2; offset = 2 */ 1689 if (curofs < offset) { 1690 D2(printk 1691 (KERN_DEBUG 1692 "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", 1693 fd->name, fd->ino, fd->type, curofs, offset)); 1694 continue; 1695 } 1696 if (!fd->ino) { 1697 D2(printk 1698 (KERN_DEBUG "Skipping deletion dirent \"%s\"\n", 1699 fd->name)); 1700 offset++; 1701 continue; 1702 } 1703 D2(printk 1704 (KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset, 1705 fd->name, fd->ino, fd->type)); 1706 filldir(nbuf, nlen, fd->name, strlen((char *)fd->name)); 1707 #ifdef CYGPKG_FS_JFFS2_RET_DIRENT_DTYPE 1708 c_ino = jffs2_iget(inode->i_sb, fd->ino); 1709 if(IS_ERR(c_ino)) { 1710 D1(printk(KERN_WARNING "get entry inode failed\n")); 1711 // fileio already set it to zero, so not needed here 1712 // ent->d_type = 0; 1713 } 1714 else { 1715 ent->d_type = c_ino->i_mode; 1716 jffs2_iput(c_ino); 1717 } 1718 #endif 1719 goto out_sem; 1720 } 1721 /* Reached the end of the directory */ 1722 found = 0; 1723 out_sem: 1724 up(&f->sem); 1725 out: 1726 fp->f_offset = ++offset; 1727 if (found) { 1728 uio->uio_resid -= sizeof (struct dirent); 1729 } 1730 return ENOERR; 1731 } 1732 1733 // ------------------------------------------------------------------------- 1734 // jffs2_fo_dirlseek() 1735 // Seek directory to start. 1736 1737 static int jffs2_fo_dirlseek(struct CYG_FILE_TAG *fp, off_t * pos, int whence) 1738 { 1739 // Only allow SEEK_SET to zero 1740 1741 D2(printf("jffs2_fo_dirlseek\n")); 1742 1743 if (whence != SEEK_SET || *pos != 0) 1744 return EINVAL; 1745 1746 *pos = fp->f_offset = 0; 1747 1748 return ENOERR; 1749 } 1750 1751 //========================================================================== 1752 // 1753 // Called by JFFS2 1754 // =============== 1755 // 1756 // 1757 //========================================================================== 1758 1759 unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, 1760 struct jffs2_inode_info *f, 1761 unsigned long offset, 1762 unsigned long *priv) 1763 { 1764 /* FIXME: This works only with one file system mounted at a time */ 1765 int ret; 1766 1767 ret = jffs2_read_inode_range(c, f, gc_buffer, 1768 offset & ~(PAGE_CACHE_SIZE-1), PAGE_CACHE_SIZE); 1769 if (ret) 1770 return ERR_PTR(ret); 1771 1772 return gc_buffer; 1773 } 1774 1775 void jffs2_gc_release_page(struct jffs2_sb_info *c, 1776 unsigned char *ptr, 1777 unsigned long *priv) 1778 { 1779 /* Do nothing */ 1780 } 1781 1782 static struct _inode *new_inode(struct super_block *sb) 1783 { 1784 struct _inode *inode; 1785 struct _inode *cached_inode; 1786 1787 inode = rt_malloc(sizeof (struct _inode)); 1788 if (inode == NULL) 1789 return 0; 1790 1791 D2(printf("malloc new_inode %x ####################################\n", 1792 inode)); 1793 1794 memset(inode, 0, sizeof (struct _inode)); 1795 inode->i_sb = sb; 1796 inode->i_ino = 1; 1797 inode->i_count = 1; 1798 inode->i_nlink = 1; // Let JFFS2 manage the link count 1799 inode->i_size = 0; 1800 1801 inode->i_cache_next = NULL; // Newest inode, about to be cached 1802 1803 // Add to the icache 1804 for (cached_inode = sb->s_root; cached_inode != NULL; 1805 cached_inode = cached_inode->i_cache_next) { 1806 if (cached_inode->i_cache_next == NULL) { 1807 cached_inode->i_cache_next = inode; // Current last in cache points to newcomer 1808 inode->i_cache_prev = cached_inode; // Newcomer points back to last 1809 break; 1810 } 1811 } 1812 return inode; 1813 } 1814 1815 static struct _inode *ilookup(struct super_block *sb, cyg_uint32 ino) 1816 { 1817 struct _inode *inode = NULL; 1818 1819 D2(printf("ilookup\n")); 1820 // Check for this inode in the cache 1821 for (inode = sb->s_root; inode != NULL; inode = inode->i_cache_next) { 1822 if (inode->i_ino == ino) { 1823 inode->i_count++; 1824 break; 1825 } 1826 } 1827 return inode; 1828 } 1829 1830 struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino) 1831 { 1832 // Called in super.c jffs2_read_super, dir.c jffs2_lookup, 1833 // and gc.c jffs2_garbage_collect_pass 1834 1835 // Must first check for cached inode 1836 // If this fails let new_inode create one 1837 1838 struct _inode *inode; 1839 int err; 1840 1841 D2(printf("jffs2_iget\n")); 1842 1843 inode = ilookup(sb, ino); 1844 if (inode) 1845 return inode; 1846 1847 // Not cached, so malloc it 1848 inode = new_inode(sb); 1849 if (inode == NULL) 1850 return ERR_PTR(-ENOMEM); 1851 1852 inode->i_ino = ino; 1853 1854 err = jffs2_read_inode(inode); 1855 if (err) { 1856 printf("jffs2_read_inode() failed\n"); 1857 inode->i_nlink = 0; // free _this_ bad inode right now 1858 jffs2_iput(inode); 1859 inode = NULL; 1860 return ERR_PTR(err); 1861 } 1862 return inode; 1863 } 1864 1865 // ------------------------------------------------------------------------- 1866 // Decrement the reference count on an inode. If this makes the ref count 1867 // zero, then this inode can be freed. 1868 1869 void jffs2_iput(struct _inode *i) 1870 { 1871 // Called in jffs2_find 1872 // (and jffs2_open and jffs2_ops_mkdir?) 1873 // super.c jffs2_read_super, 1874 // and gc.c jffs2_garbage_collect_pass 1875 recurse: 1876 if (!i) { 1877 printf("jffs2_iput() called with NULL inode\n"); 1878 // and let it fault... 1879 } 1880 1881 i->i_count--; 1882 1883 if (i->i_count < 0) 1884 BUG(); 1885 1886 if (i->i_count) 1887 return; 1888 1889 if (!i->i_nlink) { 1890 struct _inode *parent; 1891 1892 // Remove from the icache linked list and free immediately 1893 if (i->i_cache_prev) 1894 i->i_cache_prev->i_cache_next = i->i_cache_next; 1895 if (i->i_cache_next) 1896 i->i_cache_next->i_cache_prev = i->i_cache_prev; 1897 1898 parent = i->i_parent; 1899 jffs2_clear_inode(i); 1900 memset(i, 0x5a, sizeof(*i)); 1901 rt_free(i); 1902 1903 if (parent && parent != i) { 1904 i = parent; 1905 goto recurse; 1906 } 1907 1908 } else { 1909 // Evict some _other_ inode with i_count zero, leaving 1910 // this latest one in the cache for a while 1911 icache_evict(i->i_sb->s_root, i); 1912 } 1913 } 1914 1915 1916 // ------------------------------------------------------------------------- 1917 // EOF jffs2.c 1918 1919 1920 static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) 1921 { 1922 memset(f, 0, sizeof(*f)); 1923 init_MUTEX_LOCKED(&f->sem); 1924 } 1925 1926 static void jffs2_clear_inode (struct _inode *inode) 1927 { 1928 /* We can forget about this inode for now - drop all 1929 * the nodelists associated with it, etc. 1930 */ 1931 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 1932 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 1933 1934 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); 1935 1936 jffs2_do_clear_inode(c, f); 1937 } 1938 1939 1940 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, 1941 fill in the raw_inode while you're at it. */ 1942 struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri) 1943 { 1944 struct _inode *inode; 1945 struct super_block *sb = dir_i->i_sb; 1946 struct jffs2_sb_info *c; 1947 struct jffs2_inode_info *f; 1948 int ret; 1949 1950 D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); 1951 1952 c = JFFS2_SB_INFO(sb); 1953 1954 inode = new_inode(sb); 1955 1956 if (!inode) 1957 return ERR_PTR(-ENOMEM); 1958 1959 f = JFFS2_INODE_INFO(inode); 1960 jffs2_init_inode_info(f); 1961 1962 memset(ri, 0, sizeof(*ri)); 1963 /* Set OS-specific defaults for new inodes */ 1964 ri->uid = ri->gid = cpu_to_je16(0); 1965 ri->mode = cpu_to_jemode(mode); 1966 ret = jffs2_do_new_inode (c, f, mode, ri); 1967 if (ret) { 1968 // forceful evict: f->sem is locked already, and the 1969 // inode is bad. 1970 if (inode->i_cache_prev) 1971 inode->i_cache_prev->i_cache_next = inode->i_cache_next; 1972 if (inode->i_cache_next) 1973 inode->i_cache_next->i_cache_prev = inode->i_cache_prev; 1974 up(&(f->sem)); 1975 jffs2_clear_inode(inode); 1976 memset(inode, 0x6a, sizeof(*inode)); 1977 rt_free(inode); 1978 return ERR_PTR(ret); 1979 } 1980 inode->i_nlink = 1; 1981 inode->i_ino = je32_to_cpu(ri->ino); 1982 inode->i_mode = jemode_to_cpu(ri->mode); 1983 inode->i_gid = je16_to_cpu(ri->gid); 1984 inode->i_uid = je16_to_cpu(ri->uid); 1985 inode->i_atime = inode->i_ctime = inode->i_mtime = jffs2_get_timestamp(); 1986 ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime); 1987 1988 inode->i_size = 0; 1989 1990 return inode; 1991 } 1992 1993 1994 static int jffs2_read_inode (struct _inode *inode) 1995 { 1996 struct jffs2_inode_info *f; 1997 struct jffs2_sb_info *c; 1998 struct jffs2_raw_inode latest_node; 1999 int ret; 2000 2001 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); 2002 2003 f = JFFS2_INODE_INFO(inode); 2004 c = JFFS2_SB_INFO(inode->i_sb); 2005 2006 jffs2_init_inode_info(f); 2007 2008 ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); 2009 2010 if (ret) { 2011 up(&f->sem); 2012 return ret; 2013 } 2014 inode->i_mode = jemode_to_cpu(latest_node.mode); 2015 inode->i_uid = je16_to_cpu(latest_node.uid); 2016 inode->i_gid = je16_to_cpu(latest_node.gid); 2017 inode->i_size = je32_to_cpu(latest_node.isize); 2018 inode->i_atime = je32_to_cpu(latest_node.atime); 2019 inode->i_mtime = je32_to_cpu(latest_node.mtime); 2020 inode->i_ctime = je32_to_cpu(latest_node.ctime); 2021 2022 inode->i_nlink = f->inocache->nlink; 2023 up(&f->sem); 2024 2025 D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); 2026 return 0; 2027 } 2028 2029 2030 void jffs2_gc_release_inode(struct jffs2_sb_info *c, 2031 struct jffs2_inode_info *f) 2032 { 2033 jffs2_iput(OFNI_EDONI_2SFFJ(f)); 2034 } 2035 2036 struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, 2037 int inum, int nlink) 2038 { 2039 struct _inode *inode; 2040 struct jffs2_inode_cache *ic; 2041 if (!nlink) { 2042 /* The inode has zero nlink but its nodes weren't yet marked 2043 obsolete. This has to be because we're still waiting for 2044 the final (close() and) jffs2_iput() to happen. 2045 2046 There's a possibility that the final jffs2_iput() could have 2047 happened while we were contemplating. In order to ensure 2048 that we don't cause a new read_inode() (which would fail) 2049 for the inode in question, we use ilookup() in this case 2050 instead of jffs2_iget(). 2051 2052 The nlink can't _become_ zero at this point because we're 2053 holding the alloc_sem, and jffs2_do_unlink() would also 2054 need that while decrementing nlink on any inode. 2055 */ 2056 inode = ilookup(OFNI_BS_2SFFJ(c), inum); 2057 if (!inode) { 2058 D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n", 2059 inum)); 2060 2061 spin_lock(&c->inocache_lock); 2062 ic = jffs2_get_ino_cache(c, inum); 2063 if (!ic) { 2064 D1(printk(KERN_DEBUG "Inode cache for ino #%u is gone.\n", inum)); 2065 spin_unlock(&c->inocache_lock); 2066 return NULL; 2067 } 2068 if (ic->state != INO_STATE_CHECKEDABSENT) { 2069 /* Wait for progress. Don't just loop */ 2070 D1(printk(KERN_DEBUG "Waiting for ino #%u in state %d\n", 2071 ic->ino, ic->state)); 2072 sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); 2073 } else { 2074 spin_unlock(&c->inocache_lock); 2075 } 2076 2077 return NULL; 2078 } 2079 } else { 2080 /* Inode has links to it still; they're not going away because 2081 jffs2_do_unlink() would need the alloc_sem and we have it. 2082 Just jffs2_iget() it, and if read_inode() is necessary that's OK. 2083 */ 2084 inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum); 2085 if (IS_ERR(inode)) 2086 return (void *)inode; 2087 } 2088 2089 return JFFS2_INODE_INFO(inode); 2090 } 2091 2092 2093 2094 uint32_t jffs2_from_os_mode(uint32_t osmode) 2095 { 2096 uint32_t jmode = ((osmode & S_IRUSR)?00400:0) | 2097 ((osmode & S_IWUSR)?00200:0) | 2098 ((osmode & S_IXUSR)?00100:0) | 2099 ((osmode & S_IRGRP)?00040:0) | 2100 ((osmode & S_IWGRP)?00020:0) | 2101 ((osmode & S_IXGRP)?00010:0) | 2102 ((osmode & S_IROTH)?00004:0) | 2103 ((osmode & S_IWOTH)?00002:0) | 2104 ((osmode & S_IXOTH)?00001:0); 2105 2106 switch (osmode & S_IFMT) { 2107 // case S_IFSOCK: 2108 // return jmode | 0140000; 2109 // case S_IFLNK: 2110 // return jmode | 0120000; 2111 case S_IFREG: 2112 return jmode | 0100000; 2113 case S_IFBLK: 2114 return jmode | 0060000; 2115 case S_IFDIR: 2116 return jmode | 0040000; 2117 case S_IFCHR: 2118 return jmode | 0020000; 2119 case S_IFIFO: 2120 return jmode | 0010000; 2121 case S_ISUID: 2122 return jmode | 0004000; 2123 case S_ISGID: 2124 return jmode | 0002000; 2125 #ifdef S_ISVTX 2126 case S_ISVTX: 2127 return jmode | 0001000; 2128 #endif 2129 } 2130 printf("os_to_jffs2_mode() cannot convert 0x%x\n", osmode); 2131 BUG(); 2132 return 0; 2133 } 2134 2135 uint32_t jffs2_to_os_mode (uint32_t jmode) 2136 { 2137 uint32_t osmode = ((jmode & 00400)?S_IRUSR:0) | 2138 ((jmode & 00200)?S_IWUSR:0) | 2139 ((jmode & 00100)?S_IXUSR:0) | 2140 ((jmode & 00040)?S_IRGRP:0) | 2141 ((jmode & 00020)?S_IWGRP:0) | 2142 ((jmode & 00010)?S_IXGRP:0) | 2143 ((jmode & 00004)?S_IROTH:0) | 2144 ((jmode & 00002)?S_IWOTH:0) | 2145 ((jmode & 00001)?S_IXOTH:0); 2146 2147 switch(jmode & 00170000) { 2148 // case 0140000: prife 2149 // return osmode | S_IFSOCK; prife 2150 // case 0120000: prife 2151 // return osmode | S_IFLNK; prife 2152 case 0100000: 2153 return osmode | S_IFREG; 2154 case 0060000: 2155 return osmode | S_IFBLK; 2156 case 0040000: 2157 return osmode | S_IFDIR; 2158 case 0020000: 2159 return osmode | S_IFCHR; 2160 case 0010000: 2161 return osmode | S_IFIFO; 2162 case 0004000: 2163 return osmode | S_ISUID; 2164 case 0002000: 2165 return osmode | S_ISGID; 2166 #ifdef S_ISVTX 2167 case 0001000: 2168 return osmode | S_ISVTX; 2169 #endif 2170 } 2171 printf("jffs2_to_os_mode() cannot convert 0x%x\n", osmode); 2172 BUG(); 2173 return 0; 2174 } 2175