1 /* 2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. 3 * 4 * Copyright (C) 2002-2011 Aleph One Ltd. 5 * for Toby Churchill Ltd and Brightstar Engineering 6 * 7 * Created by Charles Manning <charles@aleph1.co.uk> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include "yaffsfs.h" 15 #include "yaffs_guts.h" 16 #include "yaffscfg.h" 17 #include "yportenv.h" 18 #include "yaffs_trace.h" 19 20 #define YAFFSFS_MAX_SYMLINK_DEREFERENCES 5 21 22 #ifndef NULL 23 #define NULL ((void *)0) 24 #endif 25 26 /* YAFFSFS_RW_SIZE must be a power of 2 */ 27 #define YAFFSFS_RW_SHIFT (13) 28 #define YAFFSFS_RW_SIZE (1<<YAFFSFS_RW_SHIFT) 29 30 /* Some forward references */ 31 static struct yaffs_obj *yaffsfs_FindObject(struct yaffs_obj *relativeDirectory, 32 const YCHAR *path, 33 int symDepth, int getEquiv, 34 struct yaffs_obj **dirOut, 35 int *notDir, int *loop); 36 37 static void yaffsfs_RemoveObjectCallback(struct yaffs_obj *obj); 38 39 unsigned int yaffs_wr_attempts; 40 41 /* 42 * Handle management. 43 * There are open inodes in struct yaffsfs_Inode. 44 * There are open file descriptors in yaffsfs_FileDes. 45 * There are open handles in yaffsfs_FileDes. 46 * 47 * Things are structured this way to be like the Linux VFS model 48 * so that interactions with the yaffs guts calls are similar. 49 * That means more common code paths and less special code. 50 * That means better testing etc. 51 * 52 * We have 3 layers because: 53 * A handle is different than an fd because you can use dup() 54 * to create a new handle that accesses the *same* fd. The two 55 * handles will use the same offset (part of the fd). We only close 56 * down the fd when there are no more handles accessing it. 57 * 58 * More than one fd can currently access one file, but each fd 59 * has its own permsiions and offset. 60 */ 61 62 struct yaffsfs_Inode { 63 int count; /* Number of handles accessing this inode */ 64 struct yaffs_obj *iObj; 65 }; 66 67 struct yaffsfs_FileDes { 68 u8 reading:1; 69 u8 writing:1; 70 u8 append:1; 71 u8 shareRead:1; 72 u8 shareWrite:1; 73 int inodeId:12; /* Index to corresponding yaffsfs_Inode */ 74 int handleCount:10; /* Number of handles for this fd */ 75 loff_t position; /* current position in file */ 76 }; 77 78 struct yaffsfs_Handle { 79 short int fdId; 80 short int useCount; 81 }; 82 83 84 struct yaffsfs_DirSearchContxt { 85 struct yaffs_dirent de; /* directory entry */ 86 YCHAR name[NAME_MAX + 1]; /* name of directory being searched */ 87 struct yaffs_obj *dirObj; /* ptr to directory being searched */ 88 struct yaffs_obj *nextReturn; /* obj returned by next readddir */ 89 struct list_head others; 90 int offset:20; 91 unsigned inUse:1; 92 }; 93 94 static struct yaffsfs_DirSearchContxt yaffsfs_dsc[YAFFSFS_N_DSC]; 95 static struct yaffsfs_Inode yaffsfs_inode[YAFFSFS_N_HANDLES]; 96 static struct yaffsfs_FileDes yaffsfs_fd[YAFFSFS_N_HANDLES]; 97 static struct yaffsfs_Handle yaffsfs_handle[YAFFSFS_N_HANDLES]; 98 99 static int yaffsfs_handlesInitialised; 100 101 unsigned yaffs_set_trace(unsigned tm) 102 { 103 yaffs_trace_mask = tm; 104 return yaffs_trace_mask; 105 } 106 107 unsigned yaffs_get_trace(void) 108 { 109 return yaffs_trace_mask; 110 } 111 112 /* 113 * yaffsfs_InitHandle 114 * Inilitalise handle management on start-up. 115 */ 116 117 static void yaffsfs_InitHandles(void) 118 { 119 int i; 120 if (yaffsfs_handlesInitialised) 121 return; 122 123 memset(yaffsfs_inode, 0, sizeof(yaffsfs_inode)); 124 memset(yaffsfs_fd, 0, sizeof(yaffsfs_fd)); 125 memset(yaffsfs_handle, 0, sizeof(yaffsfs_handle)); 126 memset(yaffsfs_dsc, 0, sizeof(yaffsfs_dsc)); 127 128 for (i = 0; i < YAFFSFS_N_HANDLES; i++) 129 yaffsfs_fd[i].inodeId = -1; 130 for (i = 0; i < YAFFSFS_N_HANDLES; i++) 131 yaffsfs_handle[i].fdId = -1; 132 } 133 134 static struct yaffsfs_Handle *yaffsfs_HandleToPointer(int h) 135 { 136 if (h >= 0 && h < YAFFSFS_N_HANDLES) 137 return &yaffsfs_handle[h]; 138 return NULL; 139 } 140 141 static struct yaffsfs_FileDes *yaffsfs_HandleToFileDes(int handle) 142 { 143 struct yaffsfs_Handle *h = yaffsfs_HandleToPointer(handle); 144 145 if (h && h->useCount > 0 && h->fdId >= 0 && h->fdId < YAFFSFS_N_HANDLES) 146 return &yaffsfs_fd[h->fdId]; 147 148 return NULL; 149 } 150 151 static struct yaffsfs_Inode *yaffsfs_HandleToInode(int handle) 152 { 153 struct yaffsfs_FileDes *fd = yaffsfs_HandleToFileDes(handle); 154 155 if (fd && fd->handleCount > 0 && 156 fd->inodeId >= 0 && fd->inodeId < YAFFSFS_N_HANDLES) 157 return &yaffsfs_inode[fd->inodeId]; 158 159 return NULL; 160 } 161 162 static struct yaffs_obj *yaffsfs_HandleToObject(int handle) 163 { 164 struct yaffsfs_Inode *in = yaffsfs_HandleToInode(handle); 165 166 if (in) 167 return in->iObj; 168 169 return NULL; 170 } 171 172 /* 173 * yaffsfs_FindInodeIdForObject 174 * Find the inode entry for an object, if it exists. 175 */ 176 177 static int yaffsfs_FindInodeIdForObject(struct yaffs_obj *obj) 178 { 179 int i; 180 int ret = -1; 181 182 if (obj) 183 obj = yaffs_get_equivalent_obj(obj); 184 185 /* Look for it in open inode table */ 186 for (i = 0; i < YAFFSFS_N_HANDLES && ret < 0; i++) { 187 if (yaffsfs_inode[i].iObj == obj) 188 ret = i; 189 } 190 return ret; 191 } 192 193 /* 194 * yaffsfs_GetInodeIdForObject 195 * Grab an inode entry when opening a new inode. 196 */ 197 static int yaffsfs_GetInodeIdForObject(struct yaffs_obj *obj) 198 { 199 int i; 200 int ret; 201 struct yaffsfs_Inode *in = NULL; 202 203 if (obj) 204 obj = yaffs_get_equivalent_obj(obj); 205 206 ret = yaffsfs_FindInodeIdForObject(obj); 207 208 for (i = 0; i < YAFFSFS_N_HANDLES && ret < 0; i++) { 209 if (!yaffsfs_inode[i].iObj) 210 ret = i; 211 } 212 213 if (ret >= 0) { 214 in = &yaffsfs_inode[ret]; 215 if (!in->iObj) 216 in->count = 0; 217 in->iObj = obj; 218 in->count++; 219 } 220 221 return ret; 222 } 223 224 static int yaffsfs_CountHandles(struct yaffs_obj *obj) 225 { 226 int i = yaffsfs_FindInodeIdForObject(obj); 227 228 if (i >= 0) 229 return yaffsfs_inode[i].count; 230 else 231 return 0; 232 } 233 234 static void yaffsfs_ReleaseInode(struct yaffsfs_Inode *in) 235 { 236 struct yaffs_obj *obj; 237 238 obj = in->iObj; 239 240 if (obj->unlinked) 241 yaffs_del_obj(obj); 242 243 obj->my_inode = NULL; 244 in->iObj = NULL; 245 246 } 247 248 static void yaffsfs_PutInode(int inodeId) 249 { 250 if (inodeId >= 0 && inodeId < YAFFSFS_N_HANDLES) { 251 struct yaffsfs_Inode *in = &yaffsfs_inode[inodeId]; 252 in->count--; 253 if (in->count <= 0) { 254 yaffsfs_ReleaseInode(in); 255 in->count = 0; 256 } 257 } 258 } 259 260 static int yaffsfs_NewHandle(struct yaffsfs_Handle **hptr) 261 { 262 int i; 263 struct yaffsfs_Handle *h; 264 265 for (i = 0; i < YAFFSFS_N_HANDLES; i++) { 266 h = &yaffsfs_handle[i]; 267 if (h->useCount < 1) { 268 memset(h, 0, sizeof(struct yaffsfs_Handle)); 269 h->fdId = -1; 270 h->useCount = 1; 271 if (hptr) 272 *hptr = h; 273 return i; 274 } 275 } 276 return -1; 277 } 278 279 static int yaffsfs_NewHandleAndFileDes(void) 280 { 281 int i; 282 struct yaffsfs_FileDes *fd; 283 struct yaffsfs_Handle *h = NULL; 284 int handle = yaffsfs_NewHandle(&h); 285 286 if (handle < 0) 287 return -1; 288 289 for (i = 0; i < YAFFSFS_N_HANDLES; i++) { 290 fd = &yaffsfs_fd[i]; 291 if (fd->handleCount < 1) { 292 memset(fd, 0, sizeof(struct yaffsfs_FileDes)); 293 fd->inodeId = -1; 294 fd->handleCount = 1; 295 h->fdId = i; 296 return handle; 297 } 298 } 299 300 /* Dump the handle because we could not get a fd */ 301 h->useCount = 0; 302 return -1; 303 } 304 305 /* 306 * yaffs_get_handle 307 * Increase use of handle when reading/writing a file 308 * Also gets the file descriptor. 309 */ 310 311 static int yaffsfs_GetHandle(int handle) 312 { 313 struct yaffsfs_Handle *h = yaffsfs_HandleToPointer(handle); 314 315 if (h && h->useCount > 0) { 316 h->useCount++; 317 return 0; 318 } 319 return -1; 320 } 321 322 /* 323 * yaffs_put_handle 324 * Let go of a handle when closing a file or aborting an open or 325 * ending a read or write. 326 */ 327 328 static int yaffsfs_PutFileDes(int fdId) 329 { 330 struct yaffsfs_FileDes *fd; 331 332 if (fdId >= 0 && fdId < YAFFSFS_N_HANDLES) { 333 fd = &yaffsfs_fd[fdId]; 334 fd->handleCount--; 335 if (fd->handleCount < 1) { 336 if (fd->inodeId >= 0) { 337 yaffsfs_PutInode(fd->inodeId); 338 fd->inodeId = -1; 339 } 340 } 341 } 342 return 0; 343 } 344 345 static int yaffsfs_PutHandle(int handle) 346 { 347 struct yaffsfs_Handle *h = yaffsfs_HandleToPointer(handle); 348 349 if (h && h->useCount > 0) { 350 h->useCount--; 351 if (h->useCount < 1) { 352 yaffsfs_PutFileDes(h->fdId); 353 h->fdId = -1; 354 } 355 } 356 357 return 0; 358 } 359 360 static void yaffsfs_BreakDeviceHandles(struct yaffs_dev *dev) 361 { 362 struct yaffsfs_FileDes *fd; 363 struct yaffsfs_Handle *h; 364 struct yaffs_obj *obj; 365 int i; 366 for (i = 0; i < YAFFSFS_N_HANDLES; i++) { 367 h = yaffsfs_HandleToPointer(i); 368 fd = yaffsfs_HandleToFileDes(i); 369 obj = yaffsfs_HandleToObject(i); 370 if (h && h->useCount > 0) { 371 h->useCount = 0; 372 h->fdId = 0; 373 } 374 if (fd && fd->handleCount > 0 && obj && obj->my_dev == dev) { 375 fd->handleCount = 0; 376 yaffsfs_PutInode(fd->inodeId); 377 fd->inodeId = -1; 378 } 379 } 380 } 381 382 /* 383 * Stuff to handle names. 384 */ 385 #ifdef CONFIG_YAFFS_CASE_INSENSITIVE 386 387 static int yaffs_toupper(YCHAR a) 388 { 389 if (a >= 'a' && a <= 'z') 390 return (a - 'a') + 'A'; 391 else 392 return a; 393 } 394 395 int yaffsfs_Match(YCHAR a, YCHAR b) 396 { 397 return (yaffs_toupper(a) == yaffs_toupper(b)); 398 } 399 #else 400 int yaffsfs_Match(YCHAR a, YCHAR b) 401 { 402 /* case sensitive */ 403 return (a == b); 404 } 405 #endif 406 407 int yaffsfs_IsPathDivider(YCHAR ch) 408 { 409 const YCHAR *str = YAFFS_PATH_DIVIDERS; 410 411 while (*str) { 412 if (*str == ch) 413 return 1; 414 str++; 415 } 416 417 return 0; 418 } 419 420 int yaffsfs_CheckNameLength(const char *name) 421 { 422 int retVal = 0; 423 424 int nameLength = yaffs_strnlen(name, YAFFS_MAX_NAME_LENGTH + 1); 425 426 if (nameLength == 0) { 427 yaffsfs_SetError(-ENOENT); 428 retVal = -1; 429 } else if (nameLength > YAFFS_MAX_NAME_LENGTH) { 430 yaffsfs_SetError(-ENAMETOOLONG); 431 retVal = -1; 432 } 433 434 return retVal; 435 } 436 437 static int yaffsfs_alt_dir_path(const YCHAR *path, YCHAR **ret_path) 438 { 439 YCHAR *alt_path = NULL; 440 int path_length; 441 int i; 442 443 /* 444 * We don't have a definition for max path length. 445 * We will use 3 * max name length instead. 446 */ 447 *ret_path = NULL; 448 path_length = yaffs_strnlen(path, (YAFFS_MAX_NAME_LENGTH + 1) * 3 + 1); 449 450 /* If the last character is a path divider, then we need to 451 * trim it back so that the name look-up works properly. 452 * eg. /foo/new_dir/ -> /foo/newdir 453 * Curveball: Need to handle multiple path dividers: 454 * eg. /foof/sdfse///// -> /foo/sdfse 455 */ 456 if (path_length > 0 && yaffsfs_IsPathDivider(path[path_length - 1])) { 457 alt_path = kmalloc(path_length + 1, 0); 458 if (!alt_path) 459 return -1; 460 yaffs_strcpy(alt_path, path); 461 for (i = path_length - 1; 462 i >= 0 && yaffsfs_IsPathDivider(alt_path[i]); i--) 463 alt_path[i] = (YCHAR) 0; 464 } 465 *ret_path = alt_path; 466 return 0; 467 } 468 469 LIST_HEAD(yaffsfs_deviceList); 470 471 /* 472 * yaffsfs_FindDevice 473 * yaffsfs_FindRoot 474 * Scan the configuration list to find the device 475 * Curveballs: Should match paths that end in '/' too 476 * Curveball2 Might have "/x/ and "/x/y". Need to return the longest match 477 */ 478 static struct yaffs_dev *yaffsfs_FindDevice(const YCHAR *path, 479 YCHAR **restOfPath) 480 { 481 struct list_head *cfg; 482 const YCHAR *leftOver; 483 const YCHAR *p; 484 struct yaffs_dev *retval = NULL; 485 struct yaffs_dev *dev = NULL; 486 int thisMatchLength; 487 int longestMatch = -1; 488 int matching; 489 490 /* 491 * Check all configs, choose the one that: 492 * 1) Actually matches a prefix (ie /a amd /abc will not match 493 * 2) Matches the longest. 494 */ 495 list_for_each(cfg, &yaffsfs_deviceList) { 496 dev = list_entry(cfg, struct yaffs_dev, dev_list); 497 leftOver = path; 498 p = dev->param.name; 499 thisMatchLength = 0; 500 matching = 1; 501 502 while (matching && *p && *leftOver) { 503 /* Skip over any /s */ 504 while (yaffsfs_IsPathDivider(*p)) 505 p++; 506 507 /* Skip over any /s */ 508 while (yaffsfs_IsPathDivider(*leftOver)) 509 leftOver++; 510 511 /* Now match the text part */ 512 while (matching && 513 *p && !yaffsfs_IsPathDivider(*p) && 514 *leftOver && !yaffsfs_IsPathDivider(*leftOver)) { 515 if (yaffsfs_Match(*p, *leftOver)) { 516 p++; 517 leftOver++; 518 thisMatchLength++; 519 } else { 520 matching = 0; 521 } 522 } 523 } 524 525 /* Skip over any /s in leftOver */ 526 while (yaffsfs_IsPathDivider(*leftOver)) 527 leftOver++; 528 529 /*Skip over any /s in p */ 530 while (yaffsfs_IsPathDivider(*p)) 531 p++; 532 533 /* p should now be at the end of the string if fully matched */ 534 if (*p) 535 matching = 0; 536 537 if (matching && (thisMatchLength > longestMatch)) { 538 /* Matched prefix */ 539 *restOfPath = (YCHAR *) leftOver; 540 retval = dev; 541 longestMatch = thisMatchLength; 542 } 543 544 } 545 return retval; 546 } 547 548 static int yaffsfs_CheckPath(const YCHAR *path) 549 { 550 int n = 0; 551 int divs = 0; 552 553 while (*path && n < YAFFS_MAX_NAME_LENGTH && divs < 100) { 554 if (yaffsfs_IsPathDivider(*path)) { 555 n = 0; 556 divs++; 557 } else 558 n++; 559 path++; 560 } 561 562 return (*path) ? -1 : 0; 563 } 564 565 /* FindMountPoint only returns a dev entry if the path is a mount point */ 566 static struct yaffs_dev *yaffsfs_FindMountPoint(const YCHAR *path) 567 { 568 struct yaffs_dev *dev; 569 YCHAR *restOfPath = NULL; 570 571 dev = yaffsfs_FindDevice(path, &restOfPath); 572 if (dev && restOfPath && *restOfPath) 573 dev = NULL; 574 return dev; 575 } 576 577 static struct yaffs_obj *yaffsfs_FindRoot(const YCHAR *path, 578 YCHAR **restOfPath) 579 { 580 struct yaffs_dev *dev; 581 582 dev = yaffsfs_FindDevice(path, restOfPath); 583 if (dev && dev->is_mounted) 584 return dev->root_dir; 585 586 return NULL; 587 } 588 589 static struct yaffs_obj *yaffsfs_FollowLink(struct yaffs_obj *obj, 590 int symDepth, int *loop) 591 { 592 593 if (obj) 594 obj = yaffs_get_equivalent_obj(obj); 595 596 while (obj && obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) { 597 YCHAR *alias = obj->variant.symlink_variant.alias; 598 599 if (yaffsfs_IsPathDivider(*alias)) 600 /* Starts with a /, need to scan from root up */ 601 obj = yaffsfs_FindObject(NULL, alias, symDepth++, 602 1, NULL, NULL, loop); 603 else 604 /* 605 * Relative to here so use the parent of the 606 * symlink as a start 607 */ 608 obj = yaffsfs_FindObject(obj->parent, alias, symDepth++, 609 1, NULL, NULL, loop); 610 } 611 return obj; 612 } 613 614 /* 615 * yaffsfs_FindDirectory 616 * Parse a path to determine the directory and the name within the directory. 617 * 618 * eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx" 619 */ 620 static struct yaffs_obj *yaffsfs_DoFindDirectory(struct yaffs_obj *startDir, 621 const YCHAR *path, 622 YCHAR **name, int symDepth, 623 int *notDir, int *loop) 624 { 625 struct yaffs_obj *dir; 626 YCHAR *restOfPath; 627 YCHAR str[YAFFS_MAX_NAME_LENGTH + 1]; 628 int i; 629 630 if (symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES) { 631 if (loop) 632 *loop = 1; 633 return NULL; 634 } 635 636 if (startDir) { 637 dir = startDir; 638 restOfPath = (YCHAR *) path; 639 } else 640 dir = yaffsfs_FindRoot(path, &restOfPath); 641 642 while (dir) { 643 /* 644 * parse off /. 645 * curve ball: also throw away surplus '/' 646 * eg. "/ram/x////ff" gets treated the same as "/ram/x/ff" 647 */ 648 while (yaffsfs_IsPathDivider(*restOfPath)) 649 restOfPath++; /* get rid of '/' */ 650 651 *name = restOfPath; 652 i = 0; 653 654 while (*restOfPath && !yaffsfs_IsPathDivider(*restOfPath)) { 655 if (i < YAFFS_MAX_NAME_LENGTH) { 656 str[i] = *restOfPath; 657 str[i + 1] = '\0'; 658 i++; 659 } 660 restOfPath++; 661 } 662 663 if (!*restOfPath) 664 /* got to the end of the string */ 665 return dir; 666 else { 667 if (yaffs_strcmp(str, _Y(".")) == 0) { 668 /* Do nothing */ 669 } else if (yaffs_strcmp(str, _Y("..")) == 0) { 670 dir = dir->parent; 671 } else { 672 dir = yaffs_find_by_name(dir, str); 673 674 dir = yaffsfs_FollowLink(dir, symDepth, loop); 675 676 if (dir && dir->variant_type != 677 YAFFS_OBJECT_TYPE_DIRECTORY) { 678 if (notDir) 679 *notDir = 1; 680 dir = NULL; 681 } 682 683 } 684 } 685 } 686 /* directory did not exist. */ 687 return NULL; 688 } 689 690 static struct yaffs_obj *yaffsfs_FindDirectory(struct yaffs_obj *relDir, 691 const YCHAR *path, 692 YCHAR **name, 693 int symDepth, 694 int *notDir, int *loop) 695 { 696 return yaffsfs_DoFindDirectory(relDir, path, name, symDepth, notDir, 697 loop); 698 } 699 700 /* 701 * yaffsfs_FindObject turns a path for an existing object into the object 702 */ 703 static struct yaffs_obj *yaffsfs_FindObject(struct yaffs_obj *relDir, 704 const YCHAR *path, int symDepth, 705 int getEquiv, 706 struct yaffs_obj **dirOut, 707 int *notDir, int *loop) 708 { 709 struct yaffs_obj *dir; 710 struct yaffs_obj *obj; 711 YCHAR *name; 712 713 dir = 714 yaffsfs_FindDirectory(relDir, path, &name, symDepth, notDir, loop); 715 716 if (dirOut) 717 *dirOut = dir; 718 719 if (dir && *name) 720 obj = yaffs_find_by_name(dir, name); 721 else 722 obj = dir; 723 724 if (getEquiv) 725 obj = yaffs_get_equivalent_obj(obj); 726 727 return obj; 728 } 729 730 /************************************************************************* 731 * Start of yaffsfs visible functions. 732 *************************************************************************/ 733 734 int yaffs_dup(int handle) 735 { 736 int newHandleNumber = -1; 737 struct yaffsfs_FileDes *existingFD = NULL; 738 struct yaffsfs_Handle *existingHandle = NULL; 739 struct yaffsfs_Handle *newHandle = NULL; 740 741 yaffsfs_Lock(); 742 existingHandle = yaffsfs_HandleToPointer(handle); 743 existingFD = yaffsfs_HandleToFileDes(handle); 744 if (existingFD) 745 newHandleNumber = yaffsfs_NewHandle(&newHandle); 746 if (newHandle) { 747 newHandle->fdId = existingHandle->fdId; 748 existingFD->handleCount++; 749 } 750 751 yaffsfs_Unlock(); 752 753 if (!existingFD) 754 yaffsfs_SetError(-EBADF); 755 else if (!newHandle) 756 yaffsfs_SetError(-ENOMEM); 757 758 return newHandleNumber; 759 760 } 761 762 static int yaffsfs_TooManyObjects(struct yaffs_dev *dev) 763 { 764 int current_objects = dev->n_obj - dev->n_deleted_files; 765 766 if (dev->param.max_objects && current_objects > dev->param.max_objects) 767 return 1; 768 else 769 return 0; 770 } 771 772 int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing) 773 { 774 struct yaffs_obj *obj = NULL; 775 struct yaffs_obj *dir = NULL; 776 YCHAR *name; 777 int handle = -1; 778 struct yaffsfs_FileDes *fd = NULL; 779 int openDenied = 0; 780 int symDepth = 0; 781 int errorReported = 0; 782 int rwflags = oflag & (O_RDWR | O_RDONLY | O_WRONLY); 783 u8 shareRead = (sharing & YAFFS_SHARE_READ) ? 1 : 0; 784 u8 shareWrite = (sharing & YAFFS_SHARE_WRITE) ? 1 : 0; 785 u8 sharedReadAllowed; 786 u8 sharedWriteAllowed; 787 u8 alreadyReading; 788 u8 alreadyWriting; 789 u8 readRequested; 790 u8 writeRequested; 791 int notDir = 0; 792 int loop = 0; 793 794 if (!path) { 795 yaffsfs_SetError(-EFAULT); 796 return -1; 797 } 798 799 if (yaffsfs_CheckPath(path) < 0) { 800 yaffsfs_SetError(-ENAMETOOLONG); 801 return -1; 802 } 803 804 /* O_EXCL only has meaning if O_CREAT is specified */ 805 if (!(oflag & O_CREAT)) 806 oflag &= ~(O_EXCL); 807 808 /* O_TRUNC has no meaning if (O_CREAT | O_EXCL) is specified */ 809 if ((oflag & O_CREAT) & (oflag & O_EXCL)) 810 oflag &= ~(O_TRUNC); 811 812 /* Todo: Are there any more flag combos to sanitise ? */ 813 814 /* Figure out if reading or writing is requested */ 815 816 readRequested = (rwflags == O_RDWR || rwflags == O_RDONLY) ? 1 : 0; 817 writeRequested = (rwflags == O_RDWR || rwflags == O_WRONLY) ? 1 : 0; 818 819 yaffsfs_Lock(); 820 821 handle = yaffsfs_NewHandleAndFileDes(); 822 823 if (handle < 0) { 824 yaffsfs_SetError(-ENFILE); 825 errorReported = 1; 826 } else { 827 828 fd = yaffsfs_HandleToFileDes(handle); 829 830 /* try to find the exisiting object */ 831 obj = yaffsfs_FindObject(NULL, path, 0, 1, NULL, NULL, NULL); 832 833 obj = yaffsfs_FollowLink(obj, symDepth++, &loop); 834 835 if (obj && 836 obj->variant_type != YAFFS_OBJECT_TYPE_FILE && 837 obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) 838 obj = NULL; 839 840 if (obj) { 841 842 /* The file already exists or it might be a directory */ 843 844 /* A directory can't be opened as a file */ 845 if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) { 846 openDenied = 1; 847 yaffsfs_SetError(-EISDIR); 848 errorReported = 1; 849 } 850 851 /* Open should fail if O_CREAT and O_EXCL are specified 852 * for a file that exists. 853 */ 854 if (!errorReported && 855 (oflag & O_EXCL) && (oflag & O_CREAT)) { 856 openDenied = 1; 857 yaffsfs_SetError(-EEXIST); 858 errorReported = 1; 859 } 860 861 /* Check file permissions */ 862 if (readRequested && !(obj->yst_mode & S_IREAD)) 863 openDenied = 1; 864 865 if (writeRequested && !(obj->yst_mode & S_IWRITE)) 866 openDenied = 1; 867 868 if (!errorReported && writeRequested && 869 obj->my_dev->read_only) { 870 openDenied = 1; 871 yaffsfs_SetError(-EROFS); 872 errorReported = 1; 873 } 874 875 if (openDenied && !errorReported) { 876 yaffsfs_SetError(-EACCES); 877 errorReported = 1; 878 } 879 880 /* Check sharing of an existing object. */ 881 if (!openDenied) { 882 struct yaffsfs_FileDes *fdx; 883 int i; 884 885 sharedReadAllowed = 1; 886 sharedWriteAllowed = 1; 887 alreadyReading = 0; 888 alreadyWriting = 0; 889 for (i = 0; i < YAFFSFS_N_HANDLES; i++) { 890 fdx = &yaffsfs_fd[i]; 891 if (fdx->handleCount > 0 && 892 fdx->inodeId >= 0 && 893 yaffsfs_inode[fdx->inodeId].iObj 894 == obj) { 895 if (!fdx->shareRead) 896 sharedReadAllowed = 0; 897 if (!fdx->shareWrite) 898 sharedWriteAllowed = 0; 899 if (fdx->reading) 900 alreadyReading = 1; 901 if (fdx->writing) 902 alreadyWriting = 1; 903 } 904 } 905 906 if ((!sharedReadAllowed && readRequested) || 907 (!shareRead && alreadyReading) || 908 (!sharedWriteAllowed && writeRequested) || 909 (!shareWrite && alreadyWriting)) { 910 openDenied = 1; 911 yaffsfs_SetError(-EBUSY); 912 errorReported = 1; 913 } 914 } 915 916 } 917 918 /* If we could not open an existing object, then let's see if 919 * the directory exists. If not, error. 920 */ 921 if (!obj && !errorReported) { 922 dir = yaffsfs_FindDirectory(NULL, path, &name, 0, 923 ¬Dir, &loop); 924 if (!dir && notDir) { 925 yaffsfs_SetError(-ENOTDIR); 926 errorReported = 1; 927 } else if (loop) { 928 yaffsfs_SetError(-ELOOP); 929 errorReported = 1; 930 } else if (!dir) { 931 yaffsfs_SetError(-ENOENT); 932 errorReported = 1; 933 } 934 } 935 936 if (!obj && dir && !errorReported && (oflag & O_CREAT)) { 937 /* Let's see if we can create this file */ 938 if (dir->my_dev->read_only) { 939 yaffsfs_SetError(-EROFS); 940 errorReported = 1; 941 } else if (yaffsfs_TooManyObjects(dir->my_dev)) { 942 yaffsfs_SetError(-ENFILE); 943 errorReported = 1; 944 } else 945 obj = yaffs_create_file(dir, name, mode, 0, 0); 946 947 if (!obj && !errorReported) { 948 yaffsfs_SetError(-ENOSPC); 949 errorReported = 1; 950 } 951 } 952 953 if (!obj && dir && !errorReported && !(oflag & O_CREAT)) { 954 yaffsfs_SetError(-ENOENT); 955 errorReported = 1; 956 } 957 958 if (obj && !openDenied) { 959 int inodeId = yaffsfs_GetInodeIdForObject(obj); 960 961 if (inodeId < 0) { 962 /* 963 * Todo: Fix any problem if inodes run out, 964 * That can't happen if the number of inode 965 * items >= number of handles. 966 */ 967 } 968 969 fd->inodeId = inodeId; 970 fd->reading = readRequested; 971 fd->writing = writeRequested; 972 fd->append = (oflag & O_APPEND) ? 1 : 0; 973 fd->position = 0; 974 fd->shareRead = shareRead; 975 fd->shareWrite = shareWrite; 976 977 /* Hook inode to object */ 978 obj->my_inode = (void *)&yaffsfs_inode[inodeId]; 979 980 if ((oflag & O_TRUNC) && fd->writing) 981 yaffs_resize_file(obj, 0); 982 } else { 983 yaffsfs_PutHandle(handle); 984 if (!errorReported) 985 yaffsfs_SetError(0); /* Problem */ 986 handle = -1; 987 } 988 } 989 990 yaffsfs_Unlock(); 991 992 return handle; 993 } 994 995 int yaffs_open(const YCHAR *path, int oflag, int mode) 996 { 997 return yaffs_open_sharing(path, oflag, mode, 998 YAFFS_SHARE_READ | YAFFS_SHARE_WRITE); 999 } 1000 1001 int yaffs_Dofsync(int handle, int datasync) 1002 { 1003 int retVal = -1; 1004 struct yaffs_obj *obj; 1005 1006 yaffsfs_Lock(); 1007 1008 obj = yaffsfs_HandleToObject(handle); 1009 1010 if (!obj) 1011 yaffsfs_SetError(-EBADF); 1012 else if (obj->my_dev->read_only) 1013 yaffsfs_SetError(-EROFS); 1014 else { 1015 yaffs_flush_file(obj, 1, datasync); 1016 retVal = 0; 1017 } 1018 1019 yaffsfs_Unlock(); 1020 1021 return retVal; 1022 } 1023 1024 int yaffs_fsync(int handle) 1025 { 1026 return yaffs_Dofsync(handle, 0); 1027 } 1028 1029 int yaffs_flush(int handle) 1030 { 1031 return yaffs_fsync(handle); 1032 } 1033 1034 int yaffs_fdatasync(int handle) 1035 { 1036 return yaffs_Dofsync(handle, 1); 1037 } 1038 1039 int yaffs_close(int handle) 1040 { 1041 struct yaffsfs_Handle *h = NULL; 1042 struct yaffs_obj *obj = NULL; 1043 int retVal = -1; 1044 1045 yaffsfs_Lock(); 1046 1047 h = yaffsfs_HandleToPointer(handle); 1048 obj = yaffsfs_HandleToObject(handle); 1049 1050 if (!h || !obj) 1051 yaffsfs_SetError(-EBADF); 1052 else { 1053 /* clean up */ 1054 yaffs_flush_file(obj, 1, 0); 1055 yaffsfs_PutHandle(handle); 1056 retVal = 0; 1057 } 1058 1059 yaffsfs_Unlock(); 1060 1061 return retVal; 1062 } 1063 1064 int yaffsfs_do_read(int handle, void *vbuf, unsigned int nbyte, 1065 int isPread, loff_t offset) 1066 { 1067 struct yaffsfs_FileDes *fd = NULL; 1068 struct yaffs_obj *obj = NULL; 1069 loff_t pos = 0; 1070 loff_t startPos = 0; 1071 loff_t endPos = 0; 1072 int nRead = 0; 1073 int nToRead = 0; 1074 int totalRead = 0; 1075 loff_t maxRead; 1076 u8 *buf = (u8 *) vbuf; 1077 1078 if (!vbuf) { 1079 yaffsfs_SetError(-EFAULT); 1080 return -1; 1081 } 1082 1083 yaffsfs_Lock(); 1084 fd = yaffsfs_HandleToFileDes(handle); 1085 obj = yaffsfs_HandleToObject(handle); 1086 1087 if (!fd || !obj) { 1088 /* bad handle */ 1089 yaffsfs_SetError(-EBADF); 1090 totalRead = -1; 1091 } else if (!fd->reading) { 1092 /* Not a reading handle */ 1093 yaffsfs_SetError(-EINVAL); 1094 totalRead = -1; 1095 } else if (nbyte > YAFFS_MAX_FILE_SIZE) { 1096 yaffsfs_SetError(-EINVAL); 1097 totalRead = -1; 1098 } else { 1099 if (isPread) 1100 startPos = offset; 1101 else 1102 startPos = fd->position; 1103 1104 pos = startPos; 1105 1106 if (yaffs_get_obj_length(obj) > pos) 1107 maxRead = yaffs_get_obj_length(obj) - pos; 1108 else 1109 maxRead = 0; 1110 1111 if (nbyte > maxRead) 1112 nbyte = maxRead; 1113 1114 yaffsfs_GetHandle(handle); 1115 1116 endPos = pos + nbyte; 1117 1118 if (pos < 0 || pos > YAFFS_MAX_FILE_SIZE || 1119 nbyte > YAFFS_MAX_FILE_SIZE || 1120 endPos < 0 || endPos > YAFFS_MAX_FILE_SIZE) { 1121 totalRead = -1; 1122 nbyte = 0; 1123 } 1124 1125 while (nbyte > 0) { 1126 nToRead = YAFFSFS_RW_SIZE - 1127 (pos & (YAFFSFS_RW_SIZE - 1)); 1128 if (nToRead > nbyte) 1129 nToRead = nbyte; 1130 1131 /* Tricky bit... 1132 * Need to reverify object in case the device was 1133 * unmounted in another thread. 1134 */ 1135 obj = yaffsfs_HandleToObject(handle); 1136 if (!obj) 1137 nRead = 0; 1138 else 1139 nRead = yaffs_file_rd(obj, buf, pos, nToRead); 1140 1141 if (nRead > 0) { 1142 totalRead += nRead; 1143 pos += nRead; 1144 buf += nRead; 1145 } 1146 1147 if (nRead == nToRead) 1148 nbyte -= nRead; 1149 else 1150 nbyte = 0; /* no more to read */ 1151 1152 if (nbyte > 0) { 1153 yaffsfs_Unlock(); 1154 yaffsfs_Lock(); 1155 } 1156 1157 } 1158 1159 yaffsfs_PutHandle(handle); 1160 1161 if (!isPread) { 1162 if (totalRead >= 0) 1163 fd->position = startPos + totalRead; 1164 else 1165 yaffsfs_SetError(-EINVAL); 1166 } 1167 1168 } 1169 1170 yaffsfs_Unlock(); 1171 1172 return (totalRead >= 0) ? totalRead : -1; 1173 1174 } 1175 1176 int yaffs_read(int handle, void *buf, unsigned int nbyte) 1177 { 1178 return yaffsfs_do_read(handle, buf, nbyte, 0, 0); 1179 } 1180 1181 int yaffs_pread(int handle, void *buf, unsigned int nbyte, loff_t offset) 1182 { 1183 return yaffsfs_do_read(handle, buf, nbyte, 1, offset); 1184 } 1185 1186 int yaffsfs_do_write(int handle, const void *vbuf, unsigned int nbyte, 1187 int isPwrite, loff_t offset) 1188 { 1189 struct yaffsfs_FileDes *fd = NULL; 1190 struct yaffs_obj *obj = NULL; 1191 loff_t pos = 0; 1192 loff_t startPos = 0; 1193 loff_t endPos; 1194 int nWritten = 0; 1195 int totalWritten = 0; 1196 int write_trhrough = 0; 1197 int nToWrite = 0; 1198 const u8 *buf = (const u8 *)vbuf; 1199 1200 if (!vbuf) { 1201 yaffsfs_SetError(-EFAULT); 1202 return -1; 1203 } 1204 1205 yaffsfs_Lock(); 1206 fd = yaffsfs_HandleToFileDes(handle); 1207 obj = yaffsfs_HandleToObject(handle); 1208 1209 if (!fd || !obj) { 1210 /* bad handle */ 1211 yaffsfs_SetError(-EBADF); 1212 totalWritten = -1; 1213 } else if (!fd->writing) { 1214 yaffsfs_SetError(-EINVAL); 1215 totalWritten = -1; 1216 } else if (obj->my_dev->read_only) { 1217 yaffsfs_SetError(-EROFS); 1218 totalWritten = -1; 1219 } else { 1220 if (fd->append) 1221 startPos = yaffs_get_obj_length(obj); 1222 else if (isPwrite) 1223 startPos = offset; 1224 else 1225 startPos = fd->position; 1226 1227 yaffsfs_GetHandle(handle); 1228 pos = startPos; 1229 endPos = pos + nbyte; 1230 1231 if (pos < 0 || pos > YAFFS_MAX_FILE_SIZE || 1232 nbyte > YAFFS_MAX_FILE_SIZE || 1233 endPos < 0 || endPos > YAFFS_MAX_FILE_SIZE) { 1234 totalWritten = -1; 1235 nbyte = 0; 1236 } 1237 1238 while (nbyte > 0) { 1239 1240 nToWrite = YAFFSFS_RW_SIZE - 1241 (pos & (YAFFSFS_RW_SIZE - 1)); 1242 if (nToWrite > nbyte) 1243 nToWrite = nbyte; 1244 1245 /* Tricky bit... 1246 * Need to reverify object in case the device was 1247 * remounted or unmounted in another thread. 1248 */ 1249 obj = yaffsfs_HandleToObject(handle); 1250 if (!obj || obj->my_dev->read_only) 1251 nWritten = 0; 1252 else 1253 nWritten = 1254 yaffs_wr_file(obj, buf, pos, nToWrite, 1255 write_trhrough); 1256 if (nWritten > 0) { 1257 totalWritten += nWritten; 1258 pos += nWritten; 1259 buf += nWritten; 1260 } 1261 1262 if (nWritten == nToWrite) 1263 nbyte -= nToWrite; 1264 else 1265 nbyte = 0; 1266 1267 if (nWritten < 1 && totalWritten < 1) { 1268 yaffsfs_SetError(-ENOSPC); 1269 totalWritten = -1; 1270 } 1271 1272 if (nbyte > 0) { 1273 yaffsfs_Unlock(); 1274 yaffsfs_Lock(); 1275 } 1276 } 1277 1278 yaffsfs_PutHandle(handle); 1279 1280 if (!isPwrite) { 1281 if (totalWritten > 0) 1282 fd->position = startPos + totalWritten; 1283 else 1284 yaffsfs_SetError(-EINVAL); 1285 } 1286 } 1287 1288 yaffsfs_Unlock(); 1289 1290 return (totalWritten >= 0) ? totalWritten : -1; 1291 } 1292 1293 int yaffs_write(int fd, const void *buf, unsigned int nbyte) 1294 { 1295 return yaffsfs_do_write(fd, buf, nbyte, 0, 0); 1296 } 1297 1298 int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, loff_t offset) 1299 { 1300 return yaffsfs_do_write(fd, buf, nbyte, 1, offset); 1301 } 1302 1303 int yaffs_truncate(const YCHAR *path, loff_t new_size) 1304 { 1305 struct yaffs_obj *obj = NULL; 1306 struct yaffs_obj *dir = NULL; 1307 int result = YAFFS_FAIL; 1308 int notDir = 0; 1309 int loop = 0; 1310 1311 if (!path) { 1312 yaffsfs_SetError(-EFAULT); 1313 return -1; 1314 } 1315 1316 if (yaffsfs_CheckPath(path) < 0) { 1317 yaffsfs_SetError(-ENAMETOOLONG); 1318 return -1; 1319 } 1320 1321 yaffsfs_Lock(); 1322 1323 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 1324 obj = yaffsfs_FollowLink(obj, 0, &loop); 1325 1326 if (!dir && notDir) 1327 yaffsfs_SetError(-ENOTDIR); 1328 else if (loop) 1329 yaffsfs_SetError(-ELOOP); 1330 else if (!dir || !obj) 1331 yaffsfs_SetError(-ENOENT); 1332 else if (obj->my_dev->read_only) 1333 yaffsfs_SetError(-EROFS); 1334 else if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE) 1335 yaffsfs_SetError(-EISDIR); 1336 else if (obj->my_dev->read_only) 1337 yaffsfs_SetError(-EROFS); 1338 else if (new_size < 0 || new_size > YAFFS_MAX_FILE_SIZE) 1339 yaffsfs_SetError(-EINVAL); 1340 else 1341 result = yaffs_resize_file(obj, new_size); 1342 1343 yaffsfs_Unlock(); 1344 1345 return (result) ? 0 : -1; 1346 } 1347 1348 int yaffs_ftruncate(int handle, loff_t new_size) 1349 { 1350 struct yaffsfs_FileDes *fd = NULL; 1351 struct yaffs_obj *obj = NULL; 1352 int result = 0; 1353 1354 yaffsfs_Lock(); 1355 fd = yaffsfs_HandleToFileDes(handle); 1356 obj = yaffsfs_HandleToObject(handle); 1357 1358 if (!fd || !obj) 1359 /* bad handle */ 1360 yaffsfs_SetError(-EBADF); 1361 else if (!fd->writing) 1362 yaffsfs_SetError(-EINVAL); 1363 else if (obj->my_dev->read_only) 1364 yaffsfs_SetError(-EROFS); 1365 else if (new_size < 0 || new_size > YAFFS_MAX_FILE_SIZE) 1366 yaffsfs_SetError(-EINVAL); 1367 else 1368 /* resize the file */ 1369 result = yaffs_resize_file(obj, new_size); 1370 yaffsfs_Unlock(); 1371 1372 return (result) ? 0 : -1; 1373 1374 } 1375 1376 loff_t yaffs_lseek(int handle, loff_t offset, int whence) 1377 { 1378 struct yaffsfs_FileDes *fd = NULL; 1379 struct yaffs_obj *obj = NULL; 1380 loff_t pos = -1; 1381 loff_t fSize = -1; 1382 1383 yaffsfs_Lock(); 1384 fd = yaffsfs_HandleToFileDes(handle); 1385 obj = yaffsfs_HandleToObject(handle); 1386 1387 if (!fd || !obj) 1388 yaffsfs_SetError(-EBADF); 1389 else if (offset > YAFFS_MAX_FILE_SIZE) 1390 yaffsfs_SetError(-EINVAL); 1391 else { 1392 if (whence == SEEK_SET) { 1393 if (offset >= 0) 1394 pos = offset; 1395 } else if (whence == SEEK_CUR) { 1396 if ((fd->position + offset) >= 0) 1397 pos = (fd->position + offset); 1398 } else if (whence == SEEK_END) { 1399 fSize = yaffs_get_obj_length(obj); 1400 if (fSize >= 0 && (fSize + offset) >= 0) 1401 pos = fSize + offset; 1402 } 1403 1404 if (pos >= 0 && pos <= YAFFS_MAX_FILE_SIZE) 1405 fd->position = pos; 1406 else { 1407 yaffsfs_SetError(-EINVAL); 1408 pos = -1; 1409 } 1410 } 1411 1412 yaffsfs_Unlock(); 1413 1414 return pos; 1415 } 1416 1417 int yaffsfs_DoUnlink(const YCHAR *path, int isDirectory) 1418 { 1419 struct yaffs_obj *dir = NULL; 1420 struct yaffs_obj *obj = NULL; 1421 YCHAR *name; 1422 int result = YAFFS_FAIL; 1423 int notDir = 0; 1424 int loop = 0; 1425 1426 if (!path) { 1427 yaffsfs_SetError(-EFAULT); 1428 return -1; 1429 } 1430 1431 if (yaffsfs_CheckPath(path) < 0) { 1432 yaffsfs_SetError(-ENAMETOOLONG); 1433 return -1; 1434 } 1435 1436 yaffsfs_Lock(); 1437 1438 obj = yaffsfs_FindObject(NULL, path, 0, 0, NULL, NULL, NULL); 1439 dir = yaffsfs_FindDirectory(NULL, path, &name, 0, ¬Dir, &loop); 1440 1441 if (!dir && notDir) 1442 yaffsfs_SetError(-ENOTDIR); 1443 else if (loop) 1444 yaffsfs_SetError(-ELOOP); 1445 else if (!dir) 1446 yaffsfs_SetError(-ENOENT); 1447 else if (yaffs_strncmp(name, _Y("."), 2) == 0) 1448 yaffsfs_SetError(-EINVAL); 1449 else if (!obj) 1450 yaffsfs_SetError(-ENOENT); 1451 else if (obj->my_dev->read_only) 1452 yaffsfs_SetError(-EROFS); 1453 else if (!isDirectory && 1454 obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) 1455 yaffsfs_SetError(-EISDIR); 1456 else if (isDirectory && 1457 obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) 1458 yaffsfs_SetError(-ENOTDIR); 1459 else if (isDirectory && obj == obj->my_dev->root_dir) 1460 yaffsfs_SetError(-EBUSY); /* Can't rmdir a root */ 1461 else { 1462 result = yaffs_unlinker(dir, name); 1463 1464 if (result == YAFFS_FAIL && isDirectory) 1465 yaffsfs_SetError(-ENOTEMPTY); 1466 } 1467 1468 yaffsfs_Unlock(); 1469 1470 return (result == YAFFS_FAIL) ? -1 : 0; 1471 } 1472 1473 int yaffs_unlink(const YCHAR *path) 1474 { 1475 return yaffsfs_DoUnlink(path, 0); 1476 } 1477 1478 int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath) 1479 { 1480 struct yaffs_obj *olddir = NULL; 1481 struct yaffs_obj *newdir = NULL; 1482 struct yaffs_obj *obj = NULL; 1483 struct yaffs_obj *newobj = NULL; 1484 YCHAR *oldname; 1485 YCHAR *newname; 1486 int result = YAFFS_FAIL; 1487 int rename_allowed = 1; 1488 int notOldDir = 0; 1489 int notNewDir = 0; 1490 int oldLoop = 0; 1491 int newLoop = 0; 1492 1493 YCHAR *alt_newpath = NULL; 1494 1495 if (!oldPath || !newPath) { 1496 yaffsfs_SetError(-EFAULT); 1497 return -1; 1498 } 1499 1500 if (yaffsfs_CheckPath(oldPath) < 0 || yaffsfs_CheckPath(newPath) < 0) { 1501 yaffsfs_SetError(-ENAMETOOLONG); 1502 return -1; 1503 } 1504 1505 if (yaffsfs_alt_dir_path(newPath, &alt_newpath) < 0) { 1506 yaffsfs_SetError(-ENOMEM); 1507 return -1; 1508 } 1509 if (alt_newpath) 1510 newPath = alt_newpath; 1511 1512 yaffsfs_Lock(); 1513 1514 olddir = yaffsfs_FindDirectory(NULL, oldPath, &oldname, 0, 1515 ¬OldDir, &oldLoop); 1516 newdir = yaffsfs_FindDirectory(NULL, newPath, &newname, 0, 1517 ¬NewDir, &newLoop); 1518 obj = yaffsfs_FindObject(NULL, oldPath, 0, 0, NULL, NULL, NULL); 1519 newobj = yaffsfs_FindObject(NULL, newPath, 0, 0, NULL, NULL, NULL); 1520 1521 /* If the object being renamed is a directory and the 1522 * path ended with a "/" then the olddir == obj. 1523 * We pass through NULL for the old name to tell the lower layers 1524 * to use olddir as the object. 1525 */ 1526 1527 if (olddir == obj) 1528 oldname = NULL; 1529 1530 if ((!olddir && notOldDir) || (!newdir && notNewDir)) { 1531 yaffsfs_SetError(-ENOTDIR); 1532 rename_allowed = 0; 1533 } else if (oldLoop || newLoop) { 1534 yaffsfs_SetError(-ELOOP); 1535 rename_allowed = 0; 1536 } else if (olddir && oldname && 1537 yaffs_strncmp(oldname, _Y("."), 2) == 0) { 1538 yaffsfs_SetError(-EINVAL); 1539 rename_allowed = 0; 1540 } else if (!olddir || !newdir || !obj) { 1541 yaffsfs_SetError(-ENOENT); 1542 rename_allowed = 0; 1543 } else if (obj->my_dev->read_only) { 1544 yaffsfs_SetError(-EROFS); 1545 rename_allowed = 0; 1546 } else if (yaffs_is_non_empty_dir(newobj)) { 1547 yaffsfs_SetError(-ENOTEMPTY); 1548 rename_allowed = 0; 1549 } else if (olddir->my_dev != newdir->my_dev) { 1550 /* Rename must be on same device */ 1551 yaffsfs_SetError(-EXDEV); 1552 rename_allowed = 0; 1553 } else if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) { 1554 /* 1555 * It is a directory, check that it is not being renamed to 1556 * being its own decendent. 1557 * Do this by tracing from the new directory back to the root, 1558 * checking for obj 1559 */ 1560 1561 struct yaffs_obj *xx = newdir; 1562 1563 while (rename_allowed && xx) { 1564 if (xx == obj) 1565 rename_allowed = 0; 1566 xx = xx->parent; 1567 } 1568 if (!rename_allowed) 1569 yaffsfs_SetError(-EINVAL); 1570 } 1571 1572 if (rename_allowed) 1573 result = yaffs_rename_obj(olddir, oldname, newdir, newname); 1574 1575 yaffsfs_Unlock(); 1576 1577 kfree(alt_newpath); 1578 1579 return (result == YAFFS_FAIL) ? -1 : 0; 1580 } 1581 1582 static int yaffsfs_DoStat(struct yaffs_obj *obj, struct yaffs_stat *buf) 1583 { 1584 int retVal = -1; 1585 1586 obj = yaffs_get_equivalent_obj(obj); 1587 1588 if (obj && buf) { 1589 buf->st_dev = (int)obj->my_dev->os_context; 1590 buf->st_ino = obj->obj_id; 1591 buf->st_mode = obj->yst_mode & ~S_IFMT; 1592 1593 if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) 1594 buf->st_mode |= S_IFDIR; 1595 else if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) 1596 buf->st_mode |= S_IFLNK; 1597 else if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) 1598 buf->st_mode |= S_IFREG; 1599 1600 buf->st_nlink = yaffs_get_obj_link_count(obj); 1601 buf->st_uid = 0; 1602 buf->st_gid = 0; 1603 buf->st_rdev = obj->yst_rdev; 1604 buf->st_size = yaffs_get_obj_length(obj); 1605 buf->st_blksize = obj->my_dev->data_bytes_per_chunk; 1606 buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / 1607 buf->st_blksize; 1608 #if CONFIG_YAFFS_WINCE 1609 buf->yst_wince_atime[0] = obj->win_atime[0]; 1610 buf->yst_wince_atime[1] = obj->win_atime[1]; 1611 buf->yst_wince_ctime[0] = obj->win_ctime[0]; 1612 buf->yst_wince_ctime[1] = obj->win_ctime[1]; 1613 buf->yst_wince_mtime[0] = obj->win_mtime[0]; 1614 buf->yst_wince_mtime[1] = obj->win_mtime[1]; 1615 #else 1616 buf->yst_atime = obj->yst_atime; 1617 buf->yst_ctime = obj->yst_ctime; 1618 buf->yst_mtime = obj->yst_mtime; 1619 #endif 1620 retVal = 0; 1621 } 1622 return retVal; 1623 } 1624 1625 static int yaffsfs_DoStatOrLStat(const YCHAR *path, 1626 struct yaffs_stat *buf, int doLStat) 1627 { 1628 struct yaffs_obj *obj = NULL; 1629 struct yaffs_obj *dir = NULL; 1630 int retVal = -1; 1631 int notDir = 0; 1632 int loop = 0; 1633 1634 if (!path || !buf) { 1635 yaffsfs_SetError(-EFAULT); 1636 return -1; 1637 } 1638 1639 if (yaffsfs_CheckPath(path) < 0) { 1640 yaffsfs_SetError(-ENAMETOOLONG); 1641 return -1; 1642 } 1643 1644 yaffsfs_Lock(); 1645 1646 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 1647 1648 if (!doLStat && obj) 1649 obj = yaffsfs_FollowLink(obj, 0, &loop); 1650 1651 if (!dir && notDir) 1652 yaffsfs_SetError(-ENOTDIR); 1653 else if (loop) 1654 yaffsfs_SetError(-ELOOP); 1655 else if (!dir || !obj) 1656 yaffsfs_SetError(-ENOENT); 1657 else 1658 retVal = yaffsfs_DoStat(obj, buf); 1659 1660 yaffsfs_Unlock(); 1661 1662 return retVal; 1663 1664 } 1665 1666 int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf) 1667 { 1668 return yaffsfs_DoStatOrLStat(path, buf, 0); 1669 } 1670 1671 int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf) 1672 { 1673 return yaffsfs_DoStatOrLStat(path, buf, 1); 1674 } 1675 1676 int yaffs_fstat(int fd, struct yaffs_stat *buf) 1677 { 1678 struct yaffs_obj *obj; 1679 1680 int retVal = -1; 1681 1682 if (!buf) { 1683 yaffsfs_SetError(-EFAULT); 1684 return -1; 1685 } 1686 1687 yaffsfs_Lock(); 1688 obj = yaffsfs_HandleToObject(fd); 1689 1690 if (obj) 1691 retVal = yaffsfs_DoStat(obj, buf); 1692 else 1693 /* bad handle */ 1694 yaffsfs_SetError(-EBADF); 1695 1696 yaffsfs_Unlock(); 1697 1698 return retVal; 1699 } 1700 1701 static int yaffsfs_DoUtime(struct yaffs_obj *obj, 1702 const struct yaffs_utimbuf *buf) 1703 { 1704 int retVal = -1; 1705 int result; 1706 1707 struct yaffs_utimbuf local; 1708 1709 obj = yaffs_get_equivalent_obj(obj); 1710 1711 if (obj && obj->my_dev->read_only) { 1712 yaffsfs_SetError(-EROFS); 1713 return -1; 1714 } 1715 1716 if (!buf) { 1717 local.actime = Y_CURRENT_TIME; 1718 local.modtime = local.actime; 1719 buf = &local; 1720 } 1721 1722 if (obj) { 1723 obj->yst_atime = buf->actime; 1724 obj->yst_mtime = buf->modtime; 1725 obj->dirty = 1; 1726 result = yaffs_flush_file(obj, 0, 0); 1727 retVal = result == YAFFS_OK ? 0 : -1; 1728 } 1729 1730 return retVal; 1731 } 1732 1733 int yaffs_utime(const YCHAR *path, const struct yaffs_utimbuf *buf) 1734 { 1735 struct yaffs_obj *obj = NULL; 1736 struct yaffs_obj *dir = NULL; 1737 int retVal = -1; 1738 int notDir = 0; 1739 int loop = 0; 1740 1741 if (!path) { 1742 yaffsfs_SetError(-EFAULT); 1743 return -1; 1744 } 1745 1746 if (yaffsfs_CheckPath(path) < 0) { 1747 yaffsfs_SetError(-ENAMETOOLONG); 1748 return -1; 1749 } 1750 1751 yaffsfs_Lock(); 1752 1753 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 1754 1755 if (!dir && notDir) 1756 yaffsfs_SetError(-ENOTDIR); 1757 else if (loop) 1758 yaffsfs_SetError(-ELOOP); 1759 else if (!dir || !obj) 1760 yaffsfs_SetError(-ENOENT); 1761 else 1762 retVal = yaffsfs_DoUtime(obj, buf); 1763 1764 yaffsfs_Unlock(); 1765 1766 return retVal; 1767 1768 } 1769 1770 int yaffs_futime(int fd, const struct yaffs_utimbuf *buf) 1771 { 1772 struct yaffs_obj *obj; 1773 1774 int retVal = -1; 1775 1776 yaffsfs_Lock(); 1777 obj = yaffsfs_HandleToObject(fd); 1778 1779 if (obj) 1780 retVal = yaffsfs_DoUtime(obj, buf); 1781 else 1782 /* bad handle */ 1783 yaffsfs_SetError(-EBADF); 1784 1785 yaffsfs_Unlock(); 1786 1787 return retVal; 1788 } 1789 1790 #ifndef CONFIG_YAFFS_WINCE 1791 /* xattrib functions */ 1792 1793 static int yaffs_do_setxattr(const YCHAR *path, const char *name, 1794 const void *data, int size, int flags, int follow) 1795 { 1796 struct yaffs_obj *obj; 1797 struct yaffs_obj *dir; 1798 int notDir = 0; 1799 int loop = 0; 1800 1801 int retVal = -1; 1802 1803 if (!path || !name || !data) { 1804 yaffsfs_SetError(-EFAULT); 1805 return -1; 1806 } 1807 1808 if (yaffsfs_CheckPath(path) < 0) { 1809 yaffsfs_SetError(-ENAMETOOLONG); 1810 return -1; 1811 } 1812 1813 yaffsfs_Lock(); 1814 1815 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 1816 1817 if (follow) 1818 obj = yaffsfs_FollowLink(obj, 0, &loop); 1819 1820 if (!dir && notDir) 1821 yaffsfs_SetError(-ENOTDIR); 1822 else if (loop) 1823 yaffsfs_SetError(-ELOOP); 1824 else if (!dir || !obj) 1825 yaffsfs_SetError(-ENOENT); 1826 else { 1827 retVal = yaffs_set_xattrib(obj, name, data, size, flags); 1828 if (retVal < 0) { 1829 yaffsfs_SetError(retVal); 1830 retVal = -1; 1831 } 1832 } 1833 1834 yaffsfs_Unlock(); 1835 1836 return retVal; 1837 1838 } 1839 1840 int yaffs_setxattr(const YCHAR *path, const char *name, 1841 const void *data, int size, int flags) 1842 { 1843 return yaffs_do_setxattr(path, name, data, size, flags, 1); 1844 } 1845 1846 int yaffs_lsetxattr(const YCHAR *path, const char *name, 1847 const void *data, int size, int flags) 1848 { 1849 return yaffs_do_setxattr(path, name, data, size, flags, 0); 1850 } 1851 1852 int yaffs_fsetxattr(int fd, const char *name, 1853 const void *data, int size, int flags) 1854 { 1855 struct yaffs_obj *obj; 1856 1857 int retVal = -1; 1858 1859 if (!name || !data) { 1860 yaffsfs_SetError(-EFAULT); 1861 return -1; 1862 } 1863 1864 yaffsfs_Lock(); 1865 obj = yaffsfs_HandleToObject(fd); 1866 1867 if (!obj) 1868 yaffsfs_SetError(-EBADF); 1869 else { 1870 retVal = yaffs_set_xattrib(obj, name, data, size, flags); 1871 if (retVal < 0) { 1872 yaffsfs_SetError(retVal); 1873 retVal = -1; 1874 } 1875 } 1876 1877 yaffsfs_Unlock(); 1878 1879 return retVal; 1880 } 1881 1882 static int yaffs_do_getxattr(const YCHAR *path, const char *name, 1883 void *data, int size, int follow) 1884 { 1885 struct yaffs_obj *obj; 1886 struct yaffs_obj *dir; 1887 int retVal = -1; 1888 int notDir = 0; 1889 int loop = 0; 1890 1891 if (!path || !name || !data) { 1892 yaffsfs_SetError(-EFAULT); 1893 return -1; 1894 } 1895 1896 if (yaffsfs_CheckPath(path) < 0) { 1897 yaffsfs_SetError(-ENAMETOOLONG); 1898 return -1; 1899 } 1900 1901 yaffsfs_Lock(); 1902 1903 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 1904 1905 if (follow) 1906 obj = yaffsfs_FollowLink(obj, 0, &loop); 1907 1908 if (!dir && notDir) 1909 yaffsfs_SetError(-ENOTDIR); 1910 else if (loop) 1911 yaffsfs_SetError(-ELOOP); 1912 else if (!dir || !obj) 1913 yaffsfs_SetError(-ENOENT); 1914 else { 1915 retVal = yaffs_get_xattrib(obj, name, data, size); 1916 if (retVal < 0) { 1917 yaffsfs_SetError(retVal); 1918 retVal = -1; 1919 } 1920 } 1921 yaffsfs_Unlock(); 1922 1923 return retVal; 1924 1925 } 1926 1927 int yaffs_getxattr(const YCHAR *path, const char *name, void *data, int size) 1928 { 1929 return yaffs_do_getxattr(path, name, data, size, 1); 1930 } 1931 1932 int yaffs_lgetxattr(const YCHAR *path, const char *name, void *data, int size) 1933 { 1934 return yaffs_do_getxattr(path, name, data, size, 0); 1935 } 1936 1937 int yaffs_fgetxattr(int fd, const char *name, void *data, int size) 1938 { 1939 struct yaffs_obj *obj; 1940 1941 int retVal = -1; 1942 1943 if (!name || !data) { 1944 yaffsfs_SetError(-EFAULT); 1945 return -1; 1946 } 1947 1948 yaffsfs_Lock(); 1949 obj = yaffsfs_HandleToObject(fd); 1950 1951 if (obj) { 1952 retVal = yaffs_get_xattrib(obj, name, data, size); 1953 if (retVal < 0) { 1954 yaffsfs_SetError(retVal); 1955 retVal = -1; 1956 } 1957 } else 1958 /* bad handle */ 1959 yaffsfs_SetError(-EBADF); 1960 1961 yaffsfs_Unlock(); 1962 1963 return retVal; 1964 } 1965 1966 static int yaffs_do_listxattr(const YCHAR *path, char *data, 1967 int size, int follow) 1968 { 1969 struct yaffs_obj *obj = NULL; 1970 struct yaffs_obj *dir = NULL; 1971 int retVal = -1; 1972 int notDir = 0; 1973 int loop = 0; 1974 1975 if (!path || !data) { 1976 yaffsfs_SetError(-EFAULT); 1977 return -1; 1978 } 1979 1980 if (yaffsfs_CheckPath(path) < 0) { 1981 yaffsfs_SetError(-ENAMETOOLONG); 1982 return -1; 1983 } 1984 1985 yaffsfs_Lock(); 1986 1987 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 1988 1989 if (follow) 1990 obj = yaffsfs_FollowLink(obj, 0, &loop); 1991 1992 if (!dir && notDir) 1993 yaffsfs_SetError(-ENOTDIR); 1994 else if (loop) 1995 yaffsfs_SetError(-ELOOP); 1996 else if (!dir || !obj) 1997 yaffsfs_SetError(-ENOENT); 1998 else { 1999 retVal = yaffs_list_xattrib(obj, data, size); 2000 if (retVal < 0) { 2001 yaffsfs_SetError(retVal); 2002 retVal = -1; 2003 } 2004 } 2005 2006 yaffsfs_Unlock(); 2007 2008 return retVal; 2009 2010 } 2011 2012 int yaffs_listxattr(const YCHAR *path, char *data, int size) 2013 { 2014 return yaffs_do_listxattr(path, data, size, 1); 2015 } 2016 2017 int yaffs_llistxattr(const YCHAR *path, char *data, int size) 2018 { 2019 return yaffs_do_listxattr(path, data, size, 0); 2020 } 2021 2022 int yaffs_flistxattr(int fd, char *data, int size) 2023 { 2024 struct yaffs_obj *obj; 2025 2026 int retVal = -1; 2027 2028 if (!data) { 2029 yaffsfs_SetError(-EFAULT); 2030 return -1; 2031 } 2032 2033 yaffsfs_Lock(); 2034 obj = yaffsfs_HandleToObject(fd); 2035 2036 if (obj) { 2037 retVal = yaffs_list_xattrib(obj, data, size); 2038 if (retVal < 0) { 2039 yaffsfs_SetError(retVal); 2040 retVal = -1; 2041 } 2042 } else 2043 /* bad handle */ 2044 yaffsfs_SetError(-EBADF); 2045 2046 yaffsfs_Unlock(); 2047 2048 return retVal; 2049 } 2050 2051 static int yaffs_do_removexattr(const YCHAR *path, const char *name, 2052 int follow) 2053 { 2054 struct yaffs_obj *obj = NULL; 2055 struct yaffs_obj *dir = NULL; 2056 int notDir = 0; 2057 int loop = 0; 2058 int retVal = -1; 2059 2060 if (!path || !name) { 2061 yaffsfs_SetError(-EFAULT); 2062 return -1; 2063 } 2064 2065 if (yaffsfs_CheckPath(path) < 0) { 2066 yaffsfs_SetError(-ENAMETOOLONG); 2067 return -1; 2068 } 2069 2070 yaffsfs_Lock(); 2071 2072 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 2073 2074 if (follow) 2075 obj = yaffsfs_FollowLink(obj, 0, &loop); 2076 2077 if (!dir && notDir) 2078 yaffsfs_SetError(-ENOTDIR); 2079 else if (loop) 2080 yaffsfs_SetError(-ELOOP); 2081 else if (!dir || !obj) 2082 yaffsfs_SetError(-ENOENT); 2083 else { 2084 retVal = yaffs_remove_xattrib(obj, name); 2085 if (retVal < 0) { 2086 yaffsfs_SetError(retVal); 2087 retVal = -1; 2088 } 2089 } 2090 2091 yaffsfs_Unlock(); 2092 2093 return retVal; 2094 2095 } 2096 2097 int yaffs_removexattr(const YCHAR *path, const char *name) 2098 { 2099 return yaffs_do_removexattr(path, name, 1); 2100 } 2101 2102 int yaffs_lremovexattr(const YCHAR *path, const char *name) 2103 { 2104 return yaffs_do_removexattr(path, name, 0); 2105 } 2106 2107 int yaffs_fremovexattr(int fd, const char *name) 2108 { 2109 struct yaffs_obj *obj; 2110 2111 int retVal = -1; 2112 2113 if (!name) { 2114 yaffsfs_SetError(-EFAULT); 2115 return -1; 2116 } 2117 2118 yaffsfs_Lock(); 2119 obj = yaffsfs_HandleToObject(fd); 2120 2121 if (obj) { 2122 retVal = yaffs_remove_xattrib(obj, name); 2123 if (retVal < 0) { 2124 yaffsfs_SetError(retVal); 2125 retVal = -1; 2126 } 2127 } else 2128 /* bad handle */ 2129 yaffsfs_SetError(-EBADF); 2130 2131 yaffsfs_Unlock(); 2132 2133 return retVal; 2134 } 2135 #endif 2136 2137 #ifdef CONFIG_YAFFS_WINCE 2138 int yaffs_get_wince_times(int fd, unsigned *wctime, 2139 unsigned *watime, unsigned *wmtime) 2140 { 2141 struct yaffs_obj *obj; 2142 2143 int retVal = -1; 2144 2145 yaffsfs_Lock(); 2146 obj = yaffsfs_HandleToObject(fd); 2147 2148 if (obj) { 2149 2150 if (wctime) { 2151 wctime[0] = obj->win_ctime[0]; 2152 wctime[1] = obj->win_ctime[1]; 2153 } 2154 if (watime) { 2155 watime[0] = obj->win_atime[0]; 2156 watime[1] = obj->win_atime[1]; 2157 } 2158 if (wmtime) { 2159 wmtime[0] = obj->win_mtime[0]; 2160 wmtime[1] = obj->win_mtime[1]; 2161 } 2162 2163 retVal = 0; 2164 } else 2165 /* bad handle */ 2166 yaffsfs_SetError(-EBADF); 2167 2168 yaffsfs_Unlock(); 2169 2170 return retVal; 2171 } 2172 2173 int yaffs_set_wince_times(int fd, 2174 const unsigned *wctime, 2175 const unsigned *watime, const unsigned *wmtime) 2176 { 2177 struct yaffs_obj *obj; 2178 int result; 2179 int retVal = -1; 2180 2181 yaffsfs_Lock(); 2182 obj = yaffsfs_HandleToObject(fd); 2183 2184 if (obj) { 2185 2186 if (wctime) { 2187 obj->win_ctime[0] = wctime[0]; 2188 obj->win_ctime[1] = wctime[1]; 2189 } 2190 if (watime) { 2191 obj->win_atime[0] = watime[0]; 2192 obj->win_atime[1] = watime[1]; 2193 } 2194 if (wmtime) { 2195 obj->win_mtime[0] = wmtime[0]; 2196 obj->win_mtime[1] = wmtime[1]; 2197 } 2198 2199 obj->dirty = 1; 2200 result = yaffs_flush_file(obj, 0, 0); 2201 retVal = 0; 2202 } else 2203 /* bad handle */ 2204 yaffsfs_SetError(-EBADF); 2205 2206 yaffsfs_Unlock(); 2207 2208 return retVal; 2209 } 2210 2211 #endif 2212 2213 static int yaffsfs_DoChMod(struct yaffs_obj *obj, mode_t mode) 2214 { 2215 int result = -1; 2216 2217 if (obj) 2218 obj = yaffs_get_equivalent_obj(obj); 2219 2220 if (obj) { 2221 obj->yst_mode = mode; 2222 obj->dirty = 1; 2223 result = yaffs_flush_file(obj, 0, 0); 2224 } 2225 2226 return result == YAFFS_OK ? 0 : -1; 2227 } 2228 2229 int yaffs_access(const YCHAR *path, int amode) 2230 { 2231 struct yaffs_obj *obj = NULL; 2232 struct yaffs_obj *dir = NULL; 2233 int notDir = 0; 2234 int loop = 0; 2235 int retval = -1; 2236 2237 if (!path) { 2238 yaffsfs_SetError(-EFAULT); 2239 return -1; 2240 } 2241 2242 if (yaffsfs_CheckPath(path) < 0) { 2243 yaffsfs_SetError(-ENAMETOOLONG); 2244 return -1; 2245 } 2246 2247 if (amode & ~(R_OK | W_OK | X_OK)) { 2248 yaffsfs_SetError(-EINVAL); 2249 return -1; 2250 } 2251 2252 yaffsfs_Lock(); 2253 2254 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 2255 obj = yaffsfs_FollowLink(obj, 0, &loop); 2256 2257 if (!dir && notDir) 2258 yaffsfs_SetError(-ENOTDIR); 2259 else if (loop) 2260 yaffsfs_SetError(-ELOOP); 2261 else if (!dir || !obj) 2262 yaffsfs_SetError(-ENOENT); 2263 else if ((amode & W_OK) && obj->my_dev->read_only) 2264 yaffsfs_SetError(-EROFS); 2265 else { 2266 int access_ok = 1; 2267 2268 if ((amode & R_OK) && !(obj->yst_mode & S_IREAD)) 2269 access_ok = 0; 2270 if ((amode & W_OK) && !(obj->yst_mode & S_IWRITE)) 2271 access_ok = 0; 2272 if ((amode & X_OK) && !(obj->yst_mode & S_IEXEC)) 2273 access_ok = 0; 2274 2275 if (!access_ok) 2276 yaffsfs_SetError(-EACCES); 2277 else 2278 retval = 0; 2279 } 2280 2281 yaffsfs_Unlock(); 2282 2283 return retval; 2284 2285 } 2286 2287 int yaffs_chmod(const YCHAR *path, mode_t mode) 2288 { 2289 struct yaffs_obj *obj = NULL; 2290 struct yaffs_obj *dir = NULL; 2291 int retVal = -1; 2292 int notDir = 0; 2293 int loop = 0; 2294 2295 if (!path) { 2296 yaffsfs_SetError(-EFAULT); 2297 return -1; 2298 } 2299 2300 if (yaffsfs_CheckPath(path) < 0) { 2301 yaffsfs_SetError(-ENAMETOOLONG); 2302 return -1; 2303 } 2304 2305 if (mode & ~(0777)) { 2306 yaffsfs_SetError(-EINVAL); 2307 return -1; 2308 } 2309 2310 yaffsfs_Lock(); 2311 2312 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 2313 obj = yaffsfs_FollowLink(obj, 0, &loop); 2314 2315 if (!dir && notDir) 2316 yaffsfs_SetError(-ENOTDIR); 2317 else if (loop) 2318 yaffsfs_SetError(-ELOOP); 2319 else if (!dir || !obj) 2320 yaffsfs_SetError(-ENOENT); 2321 else if (obj->my_dev->read_only) 2322 yaffsfs_SetError(-EROFS); 2323 else 2324 retVal = yaffsfs_DoChMod(obj, mode); 2325 2326 yaffsfs_Unlock(); 2327 2328 return retVal; 2329 2330 } 2331 2332 int yaffs_fchmod(int fd, mode_t mode) 2333 { 2334 struct yaffs_obj *obj; 2335 int retVal = -1; 2336 2337 if (mode & ~(0777)) { 2338 yaffsfs_SetError(-EINVAL); 2339 return -1; 2340 } 2341 2342 yaffsfs_Lock(); 2343 obj = yaffsfs_HandleToObject(fd); 2344 2345 if (!obj) 2346 yaffsfs_SetError(-EBADF); 2347 else if (obj->my_dev->read_only) 2348 yaffsfs_SetError(-EROFS); 2349 else 2350 retVal = yaffsfs_DoChMod(obj, mode); 2351 2352 yaffsfs_Unlock(); 2353 2354 return retVal; 2355 } 2356 2357 int yaffs_mkdir(const YCHAR *path, mode_t mode) 2358 { 2359 struct yaffs_obj *parent = NULL; 2360 struct yaffs_obj *dir = NULL; 2361 YCHAR *name; 2362 YCHAR *alt_path = NULL; 2363 int retVal = -1; 2364 int notDir = 0; 2365 int loop = 0; 2366 2367 if (!path) { 2368 yaffsfs_SetError(-EFAULT); 2369 return -1; 2370 } 2371 2372 if (yaffsfs_CheckPath(path) < 0) { 2373 yaffsfs_SetError(-ENAMETOOLONG); 2374 return -1; 2375 } 2376 2377 if (yaffsfs_alt_dir_path(path, &alt_path) < 0) { 2378 yaffsfs_SetError(-ENOMEM); 2379 return -1; 2380 } 2381 if (alt_path) 2382 path = alt_path; 2383 2384 yaffsfs_Lock(); 2385 parent = yaffsfs_FindDirectory(NULL, path, &name, 0, ¬Dir, &loop); 2386 if (!parent && notDir) 2387 yaffsfs_SetError(-ENOTDIR); 2388 else if (loop) 2389 yaffsfs_SetError(-ELOOP); 2390 else if (!parent) 2391 yaffsfs_SetError(-ENOENT); 2392 else if (yaffsfs_TooManyObjects(parent->my_dev)) 2393 yaffsfs_SetError(-ENFILE); 2394 else if (yaffs_strnlen(name, 5) == 0) { 2395 /* Trying to make the root itself */ 2396 yaffsfs_SetError(-EEXIST); 2397 } else if (parent->my_dev->read_only) 2398 yaffsfs_SetError(-EROFS); 2399 else { 2400 dir = yaffs_create_dir(parent, name, mode, 0, 0); 2401 if (dir) 2402 retVal = 0; 2403 else if (yaffs_find_by_name(parent, name)) 2404 yaffsfs_SetError(-EEXIST); /* name exists */ 2405 else 2406 yaffsfs_SetError(-ENOSPC); /* assume no space */ 2407 } 2408 2409 yaffsfs_Unlock(); 2410 2411 kfree(alt_path); 2412 2413 return retVal; 2414 } 2415 2416 int yaffs_rmdir(const YCHAR *path) 2417 { 2418 int result; 2419 YCHAR *alt_path; 2420 2421 if (!path) { 2422 yaffsfs_SetError(-EFAULT); 2423 return -1; 2424 } 2425 2426 if (yaffsfs_CheckPath(path) < 0) { 2427 yaffsfs_SetError(-ENAMETOOLONG); 2428 return -1; 2429 } 2430 2431 if (yaffsfs_alt_dir_path(path, &alt_path) < 0) { 2432 yaffsfs_SetError(-ENOMEM); 2433 return -1; 2434 } 2435 if (alt_path) 2436 path = alt_path; 2437 result = yaffsfs_DoUnlink(path, 1); 2438 2439 kfree(alt_path); 2440 2441 return result; 2442 } 2443 2444 void *yaffs_getdev(const YCHAR *path) 2445 { 2446 struct yaffs_dev *dev = NULL; 2447 YCHAR *dummy; 2448 dev = yaffsfs_FindDevice(path, &dummy); 2449 return (void *)dev; 2450 } 2451 2452 int yaffs_mount_common(const YCHAR *path, int read_only, int skip_checkpt) 2453 { 2454 int retVal = -1; 2455 int result = YAFFS_FAIL; 2456 struct yaffs_dev *dev = NULL; 2457 2458 if (!path) { 2459 yaffsfs_SetError(-EFAULT); 2460 return -1; 2461 } 2462 2463 yaffs_trace(YAFFS_TRACE_MOUNT, "yaffs: Mounting %s", path); 2464 2465 if (yaffsfs_CheckPath(path) < 0) { 2466 yaffsfs_SetError(-ENAMETOOLONG); 2467 return -1; 2468 } 2469 2470 yaffsfs_Lock(); 2471 2472 yaffsfs_InitHandles(); 2473 2474 dev = yaffsfs_FindMountPoint(path); 2475 if (dev) { 2476 if (!dev->is_mounted) { 2477 dev->read_only = read_only ? 1 : 0; 2478 if (skip_checkpt) { 2479 u8 skip = dev->param.skip_checkpt_rd; 2480 dev->param.skip_checkpt_rd = 1; 2481 result = yaffs_guts_initialise(dev); 2482 dev->param.skip_checkpt_rd = skip; 2483 } else { 2484 result = yaffs_guts_initialise(dev); 2485 } 2486 2487 if (result == YAFFS_FAIL) 2488 yaffsfs_SetError(-ENOMEM); 2489 retVal = result ? 0 : -1; 2490 2491 } else 2492 yaffsfs_SetError(-EBUSY); 2493 } else 2494 yaffsfs_SetError(-ENODEV); 2495 2496 yaffsfs_Unlock(); 2497 return retVal; 2498 2499 } 2500 2501 int yaffs_mount2(const YCHAR *path, int readonly) 2502 { 2503 return yaffs_mount_common(path, readonly, 0); 2504 } 2505 2506 int yaffs_mount(const YCHAR *path) 2507 { 2508 return yaffs_mount_common(path, 0, 0); 2509 } 2510 2511 int yaffs_sync(const YCHAR *path) 2512 { 2513 int retVal = -1; 2514 struct yaffs_dev *dev = NULL; 2515 YCHAR *dummy; 2516 2517 if (!path) { 2518 yaffsfs_SetError(-EFAULT); 2519 return -1; 2520 } 2521 2522 if (yaffsfs_CheckPath(path) < 0) { 2523 yaffsfs_SetError(-ENAMETOOLONG); 2524 return -1; 2525 } 2526 2527 yaffsfs_Lock(); 2528 dev = yaffsfs_FindDevice(path, &dummy); 2529 if (dev) { 2530 if (!dev->is_mounted) 2531 yaffsfs_SetError(-EINVAL); 2532 else if (dev->read_only) 2533 yaffsfs_SetError(-EROFS); 2534 else { 2535 2536 yaffs_flush_whole_cache(dev); 2537 yaffs_checkpoint_save(dev); 2538 retVal = 0; 2539 2540 } 2541 } else 2542 yaffsfs_SetError(-ENODEV); 2543 2544 yaffsfs_Unlock(); 2545 return retVal; 2546 } 2547 2548 static int yaffsfs_IsDevBusy(struct yaffs_dev *dev) 2549 { 2550 int i; 2551 struct yaffs_obj *obj; 2552 2553 for (i = 0; i < YAFFSFS_N_HANDLES; i++) { 2554 obj = yaffsfs_HandleToObject(i); 2555 if (obj && obj->my_dev == dev) 2556 return 1; 2557 } 2558 return 0; 2559 } 2560 2561 int yaffs_remount(const YCHAR *path, int force, int read_only) 2562 { 2563 int retVal = -1; 2564 struct yaffs_dev *dev = NULL; 2565 2566 if (!path) { 2567 yaffsfs_SetError(-EFAULT); 2568 return -1; 2569 } 2570 2571 if (yaffsfs_CheckPath(path) < 0) { 2572 yaffsfs_SetError(-ENAMETOOLONG); 2573 return -1; 2574 } 2575 2576 yaffsfs_Lock(); 2577 dev = yaffsfs_FindMountPoint(path); 2578 if (dev) { 2579 if (dev->is_mounted) { 2580 yaffs_flush_whole_cache(dev); 2581 2582 if (force || !yaffsfs_IsDevBusy(dev)) { 2583 if (read_only) 2584 yaffs_checkpoint_save(dev); 2585 dev->read_only = read_only ? 1 : 0; 2586 retVal = 0; 2587 } else 2588 yaffsfs_SetError(-EBUSY); 2589 2590 } else 2591 yaffsfs_SetError(-EINVAL); 2592 2593 } else 2594 yaffsfs_SetError(-ENODEV); 2595 2596 yaffsfs_Unlock(); 2597 return retVal; 2598 2599 } 2600 2601 int yaffs_unmount2(const YCHAR *path, int force) 2602 { 2603 int retVal = -1; 2604 struct yaffs_dev *dev = NULL; 2605 2606 if (!path) { 2607 yaffsfs_SetError(-EFAULT); 2608 return -1; 2609 } 2610 2611 if (yaffsfs_CheckPath(path) < 0) { 2612 yaffsfs_SetError(-ENAMETOOLONG); 2613 return -1; 2614 } 2615 2616 yaffsfs_Lock(); 2617 dev = yaffsfs_FindMountPoint(path); 2618 if (dev) { 2619 if (dev->is_mounted) { 2620 int inUse; 2621 yaffs_flush_whole_cache(dev); 2622 yaffs_checkpoint_save(dev); 2623 inUse = yaffsfs_IsDevBusy(dev); 2624 if (!inUse || force) { 2625 if (inUse) 2626 yaffsfs_BreakDeviceHandles(dev); 2627 yaffs_deinitialise(dev); 2628 2629 retVal = 0; 2630 } else 2631 yaffsfs_SetError(-EBUSY); 2632 2633 } else 2634 yaffsfs_SetError(-EINVAL); 2635 2636 } else 2637 yaffsfs_SetError(-ENODEV); 2638 2639 yaffsfs_Unlock(); 2640 return retVal; 2641 2642 } 2643 2644 int yaffs_unmount(const YCHAR *path) 2645 { 2646 return yaffs_unmount2(path, 0); 2647 } 2648 2649 loff_t yaffs_freespace(const YCHAR *path) 2650 { 2651 loff_t retVal = -1; 2652 struct yaffs_dev *dev = NULL; 2653 YCHAR *dummy; 2654 2655 if (!path) { 2656 yaffsfs_SetError(-EFAULT); 2657 return -1; 2658 } 2659 2660 if (yaffsfs_CheckPath(path) < 0) { 2661 yaffsfs_SetError(-ENAMETOOLONG); 2662 return -1; 2663 } 2664 2665 yaffsfs_Lock(); 2666 dev = yaffsfs_FindDevice(path, &dummy); 2667 if (dev && dev->is_mounted) { 2668 retVal = yaffs_get_n_free_chunks(dev); 2669 retVal *= dev->data_bytes_per_chunk; 2670 2671 } else 2672 yaffsfs_SetError(-EINVAL); 2673 2674 yaffsfs_Unlock(); 2675 return retVal; 2676 } 2677 2678 loff_t yaffs_totalspace(const YCHAR *path) 2679 { 2680 loff_t retVal = -1; 2681 struct yaffs_dev *dev = NULL; 2682 YCHAR *dummy; 2683 2684 if (!path) { 2685 yaffsfs_SetError(-EFAULT); 2686 return -1; 2687 } 2688 2689 if (yaffsfs_CheckPath(path) < 0) { 2690 yaffsfs_SetError(-ENAMETOOLONG); 2691 return -1; 2692 } 2693 2694 yaffsfs_Lock(); 2695 dev = yaffsfs_FindDevice(path, &dummy); 2696 if (dev && dev->is_mounted) { 2697 retVal = (dev->param.end_block - dev->param.start_block + 1) - 2698 dev->param.n_reserved_blocks; 2699 retVal *= dev->param.chunks_per_block; 2700 retVal *= dev->data_bytes_per_chunk; 2701 2702 } else 2703 yaffsfs_SetError(-EINVAL); 2704 2705 yaffsfs_Unlock(); 2706 return retVal; 2707 } 2708 2709 int yaffs_inodecount(const YCHAR *path) 2710 { 2711 loff_t retVal = -1; 2712 struct yaffs_dev *dev = NULL; 2713 YCHAR *dummy; 2714 2715 if (!path) { 2716 yaffsfs_SetError(-EFAULT); 2717 return -1; 2718 } 2719 2720 if (yaffsfs_CheckPath(path) < 0) { 2721 yaffsfs_SetError(-ENAMETOOLONG); 2722 return -1; 2723 } 2724 2725 yaffsfs_Lock(); 2726 dev = yaffsfs_FindDevice(path, &dummy); 2727 if (dev && dev->is_mounted) { 2728 int n_obj = dev->n_obj; 2729 if (n_obj > dev->n_hardlinks) 2730 retVal = n_obj - dev->n_hardlinks; 2731 } 2732 2733 if (retVal < 0) 2734 yaffsfs_SetError(-EINVAL); 2735 2736 yaffsfs_Unlock(); 2737 return retVal; 2738 } 2739 2740 void yaffs_add_device(struct yaffs_dev *dev) 2741 { 2742 struct list_head *cfg; 2743 /* First check that the device is not in the list. */ 2744 2745 list_for_each(cfg, &yaffsfs_deviceList) { 2746 if (dev == list_entry(cfg, struct yaffs_dev, dev_list)) 2747 return; 2748 } 2749 2750 dev->is_mounted = 0; 2751 dev->param.remove_obj_fn = yaffsfs_RemoveObjectCallback; 2752 2753 if (!dev->dev_list.next) 2754 INIT_LIST_HEAD(&dev->dev_list); 2755 2756 list_add(&dev->dev_list, &yaffsfs_deviceList); 2757 } 2758 2759 void yaffs_remove_device(struct yaffs_dev *dev) 2760 { 2761 list_del_init(&dev->dev_list); 2762 } 2763 2764 /* Functions to iterate through devices. NB Use with extreme care! */ 2765 2766 static struct list_head *dev_iterator; 2767 void yaffs_dev_rewind(void) 2768 { 2769 dev_iterator = yaffsfs_deviceList.next; 2770 } 2771 2772 struct yaffs_dev *yaffs_next_dev(void) 2773 { 2774 struct yaffs_dev *retval; 2775 2776 if (!dev_iterator) 2777 return NULL; 2778 if (dev_iterator == &yaffsfs_deviceList) 2779 return NULL; 2780 2781 retval = list_entry(dev_iterator, struct yaffs_dev, dev_list); 2782 dev_iterator = dev_iterator->next; 2783 return retval; 2784 } 2785 2786 /* Directory search stuff. */ 2787 2788 static struct list_head search_contexts; 2789 2790 static void yaffsfs_SetDirRewound(struct yaffsfs_DirSearchContxt *dsc) 2791 { 2792 if (dsc && 2793 dsc->dirObj && 2794 dsc->dirObj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) { 2795 2796 dsc->offset = 0; 2797 2798 if (list_empty(&dsc->dirObj->variant.dir_variant.children)) 2799 dsc->nextReturn = NULL; 2800 else 2801 dsc->nextReturn = 2802 list_entry(dsc->dirObj->variant.dir_variant. 2803 children.next, struct yaffs_obj, 2804 siblings); 2805 } else { 2806 /* Hey someone isn't playing nice! */ 2807 } 2808 } 2809 2810 static void yaffsfs_DirAdvance(struct yaffsfs_DirSearchContxt *dsc) 2811 { 2812 if (dsc && 2813 dsc->dirObj && 2814 dsc->dirObj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) { 2815 2816 if (dsc->nextReturn == NULL || 2817 list_empty(&dsc->dirObj->variant.dir_variant.children)) 2818 dsc->nextReturn = NULL; 2819 else { 2820 struct list_head *next = dsc->nextReturn->siblings.next; 2821 2822 if (next == &dsc->dirObj->variant.dir_variant.children) 2823 dsc->nextReturn = NULL; /* end of list */ 2824 else 2825 dsc->nextReturn = list_entry(next, 2826 struct yaffs_obj, 2827 siblings); 2828 } 2829 } else { 2830 /* Hey someone isn't playing nice! */ 2831 } 2832 } 2833 2834 static void yaffsfs_RemoveObjectCallback(struct yaffs_obj *obj) 2835 { 2836 2837 struct list_head *i; 2838 struct yaffsfs_DirSearchContxt *dsc; 2839 2840 /* if search contexts not initilised then skip */ 2841 if (!search_contexts.next) 2842 return; 2843 2844 /* Iterate through the directory search contexts. 2845 * If any are the one being removed, then advance the dsc to 2846 * the next one to prevent a hanging ptr. 2847 */ 2848 list_for_each(i, &search_contexts) { 2849 if (i) { 2850 dsc = list_entry(i, struct yaffsfs_DirSearchContxt, 2851 others); 2852 if (dsc->nextReturn == obj) 2853 yaffsfs_DirAdvance(dsc); 2854 } 2855 } 2856 2857 } 2858 2859 yaffs_DIR *yaffs_opendir(const YCHAR *dirname) 2860 { 2861 yaffs_DIR *dir = NULL; 2862 struct yaffs_obj *obj = NULL; 2863 struct yaffsfs_DirSearchContxt *dsc = NULL; 2864 int notDir = 0; 2865 int loop = 0; 2866 2867 if (!dirname) { 2868 yaffsfs_SetError(-EFAULT); 2869 return NULL; 2870 } 2871 2872 if (yaffsfs_CheckPath(dirname) < 0) { 2873 yaffsfs_SetError(-ENAMETOOLONG); 2874 return NULL; 2875 } 2876 2877 yaffsfs_Lock(); 2878 2879 obj = yaffsfs_FindObject(NULL, dirname, 0, 1, NULL, ¬Dir, &loop); 2880 2881 if (!obj && notDir) 2882 yaffsfs_SetError(-ENOTDIR); 2883 else if (loop) 2884 yaffsfs_SetError(-ELOOP); 2885 else if (!obj) 2886 yaffsfs_SetError(-ENOENT); 2887 else if (obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) 2888 yaffsfs_SetError(-ENOTDIR); 2889 else { 2890 int i; 2891 2892 for (i = 0, dsc = NULL; i < YAFFSFS_N_DSC && !dsc; i++) { 2893 if (!yaffsfs_dsc[i].inUse) 2894 dsc = &yaffsfs_dsc[i]; 2895 } 2896 2897 dir = (yaffs_DIR *) dsc; 2898 2899 if (dsc) { 2900 memset(dsc, 0, sizeof(struct yaffsfs_DirSearchContxt)); 2901 dsc->inUse = 1; 2902 dsc->dirObj = obj; 2903 yaffs_strncpy(dsc->name, dirname, NAME_MAX); 2904 INIT_LIST_HEAD(&dsc->others); 2905 2906 if (!search_contexts.next) 2907 INIT_LIST_HEAD(&search_contexts); 2908 2909 list_add(&dsc->others, &search_contexts); 2910 yaffsfs_SetDirRewound(dsc); 2911 } 2912 2913 } 2914 2915 yaffsfs_Unlock(); 2916 2917 return dir; 2918 } 2919 2920 struct yaffs_dirent *yaffs_readdir(yaffs_DIR * dirp) 2921 { 2922 struct yaffsfs_DirSearchContxt *dsc; 2923 struct yaffs_dirent *retVal = NULL; 2924 2925 dsc = (struct yaffsfs_DirSearchContxt *) dirp; 2926 yaffsfs_Lock(); 2927 2928 if (dsc && dsc->inUse) { 2929 yaffsfs_SetError(0); 2930 if (dsc->nextReturn) { 2931 dsc->de.d_ino = 2932 yaffs_get_equivalent_obj(dsc->nextReturn)->obj_id; 2933 dsc->de.d_dont_use = (unsigned)dsc->nextReturn; 2934 dsc->de.d_off = dsc->offset++; 2935 yaffs_get_obj_name(dsc->nextReturn, 2936 dsc->de.d_name, NAME_MAX); 2937 if (yaffs_strnlen(dsc->de.d_name, NAME_MAX + 1) == 0) { 2938 /* this should not happen! */ 2939 yaffs_strcpy(dsc->de.d_name, _Y("zz")); 2940 } 2941 dsc->de.d_reclen = sizeof(struct yaffs_dirent); 2942 retVal = &dsc->de; 2943 yaffsfs_DirAdvance(dsc); 2944 } else 2945 retVal = NULL; 2946 } else 2947 yaffsfs_SetError(-EBADF); 2948 2949 yaffsfs_Unlock(); 2950 2951 return retVal; 2952 2953 } 2954 2955 void yaffs_rewinddir(yaffs_DIR *dirp) 2956 { 2957 struct yaffsfs_DirSearchContxt *dsc; 2958 2959 dsc = (struct yaffsfs_DirSearchContxt *) dirp; 2960 2961 yaffsfs_Lock(); 2962 2963 yaffsfs_SetDirRewound(dsc); 2964 2965 yaffsfs_Unlock(); 2966 } 2967 2968 int yaffs_closedir(yaffs_DIR *dirp) 2969 { 2970 struct yaffsfs_DirSearchContxt *dsc; 2971 2972 dsc = (struct yaffsfs_DirSearchContxt *) dirp; 2973 2974 if (!dsc) { 2975 yaffsfs_SetError(-EFAULT); 2976 return -1; 2977 } 2978 2979 yaffsfs_Lock(); 2980 dsc->inUse = 0; 2981 list_del(&dsc->others); /* unhook from list */ 2982 yaffsfs_Unlock(); 2983 return 0; 2984 } 2985 2986 /* End of directory stuff */ 2987 2988 int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath) 2989 { 2990 struct yaffs_obj *parent = NULL; 2991 struct yaffs_obj *obj; 2992 YCHAR *name; 2993 int retVal = -1; 2994 int mode = 0; /* ignore for now */ 2995 int notDir = 0; 2996 int loop = 0; 2997 2998 if (!oldpath || !newpath) { 2999 yaffsfs_SetError(-EFAULT); 3000 return -1; 3001 } 3002 3003 if (yaffsfs_CheckPath(newpath) < 0 || yaffsfs_CheckPath(oldpath) < 0) { 3004 yaffsfs_SetError(-ENAMETOOLONG); 3005 return -1; 3006 } 3007 3008 yaffsfs_Lock(); 3009 parent = yaffsfs_FindDirectory(NULL, newpath, &name, 0, ¬Dir, &loop); 3010 if (!parent && notDir) 3011 yaffsfs_SetError(-ENOTDIR); 3012 else if (loop) 3013 yaffsfs_SetError(-ELOOP); 3014 else if (!parent || yaffs_strnlen(name, 5) < 1) 3015 yaffsfs_SetError(-ENOENT); 3016 else if (yaffsfs_TooManyObjects(parent->my_dev)) 3017 yaffsfs_SetError(-ENFILE); 3018 else if (parent->my_dev->read_only) 3019 yaffsfs_SetError(-EROFS); 3020 else if (parent) { 3021 obj = yaffs_create_symlink(parent, name, mode, 0, 0, oldpath); 3022 if (obj) 3023 retVal = 0; 3024 else if (yaffsfs_FindObject 3025 (NULL, newpath, 0, 0, NULL, NULL, NULL)) 3026 yaffsfs_SetError(-EEXIST); 3027 else 3028 yaffsfs_SetError(-ENOSPC); 3029 } 3030 3031 yaffsfs_Unlock(); 3032 3033 return retVal; 3034 3035 } 3036 3037 int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz) 3038 { 3039 struct yaffs_obj *obj = NULL; 3040 struct yaffs_obj *dir = NULL; 3041 int retVal = -1; 3042 int notDir = 0; 3043 int loop = 0; 3044 3045 if (!path || !buf) { 3046 yaffsfs_SetError(-EFAULT); 3047 return -1; 3048 } 3049 3050 yaffsfs_Lock(); 3051 3052 obj = yaffsfs_FindObject(NULL, path, 0, 1, &dir, ¬Dir, &loop); 3053 3054 if (!dir && notDir) 3055 yaffsfs_SetError(-ENOTDIR); 3056 else if (loop) 3057 yaffsfs_SetError(-ELOOP); 3058 else if (!dir || !obj) 3059 yaffsfs_SetError(-ENOENT); 3060 else if (obj->variant_type != YAFFS_OBJECT_TYPE_SYMLINK) 3061 yaffsfs_SetError(-EINVAL); 3062 else { 3063 YCHAR *alias = obj->variant.symlink_variant.alias; 3064 memset(buf, 0, bufsiz); 3065 yaffs_strncpy(buf, alias, bufsiz - 1); 3066 retVal = 0; 3067 } 3068 yaffsfs_Unlock(); 3069 return retVal; 3070 } 3071 3072 int yaffs_link(const YCHAR *oldpath, const YCHAR *linkpath) 3073 { 3074 /* Creates a link called newpath to existing oldpath */ 3075 struct yaffs_obj *obj = NULL; 3076 struct yaffs_obj *lnk = NULL; 3077 struct yaffs_obj *obj_dir = NULL; 3078 struct yaffs_obj *lnk_dir = NULL; 3079 int retVal = -1; 3080 int notDirObj = 0; 3081 int notDirLnk = 0; 3082 int objLoop = 0; 3083 int lnkLoop = 0; 3084 YCHAR *newname; 3085 3086 if (!oldpath || !linkpath) { 3087 yaffsfs_SetError(-EFAULT); 3088 return -1; 3089 } 3090 3091 if (yaffsfs_CheckPath(linkpath) < 0 || yaffsfs_CheckPath(oldpath) < 0) { 3092 yaffsfs_SetError(-ENAMETOOLONG); 3093 return -1; 3094 } 3095 3096 yaffsfs_Lock(); 3097 3098 obj = yaffsfs_FindObject(NULL, oldpath, 0, 1, 3099 &obj_dir, ¬DirObj, &objLoop); 3100 lnk = yaffsfs_FindObject(NULL, linkpath, 0, 0, NULL, NULL, NULL); 3101 lnk_dir = yaffsfs_FindDirectory(NULL, linkpath, &newname, 3102 0, ¬DirLnk, &lnkLoop); 3103 3104 if ((!obj_dir && notDirObj) || (!lnk_dir && notDirLnk)) 3105 yaffsfs_SetError(-ENOTDIR); 3106 else if (objLoop || lnkLoop) 3107 yaffsfs_SetError(-ELOOP); 3108 else if (!obj_dir || !lnk_dir || !obj) 3109 yaffsfs_SetError(-ENOENT); 3110 else if (obj->my_dev->read_only) 3111 yaffsfs_SetError(-EROFS); 3112 else if (yaffsfs_TooManyObjects(obj->my_dev)) 3113 yaffsfs_SetError(-ENFILE); 3114 else if (lnk) 3115 yaffsfs_SetError(-EEXIST); 3116 else if (lnk_dir->my_dev != obj->my_dev) 3117 yaffsfs_SetError(-EXDEV); 3118 else { 3119 retVal = yaffsfs_CheckNameLength(newname); 3120 3121 if (retVal == 0) { 3122 lnk = yaffs_link_obj(lnk_dir, newname, obj); 3123 if (lnk) 3124 retVal = 0; 3125 else { 3126 yaffsfs_SetError(-ENOSPC); 3127 retVal = -1; 3128 } 3129 } 3130 } 3131 yaffsfs_Unlock(); 3132 3133 return retVal; 3134 } 3135 3136 int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev) 3137 { 3138 pathname = pathname; 3139 mode = mode; 3140 dev = dev; 3141 3142 yaffsfs_SetError(-EINVAL); 3143 return -1; 3144 } 3145 3146 /* 3147 * D E B U G F U N C T I O N S 3148 */ 3149 3150 /* 3151 * yaffs_n_handles() 3152 * Returns number of handles attached to the object 3153 */ 3154 int yaffs_n_handles(const YCHAR *path) 3155 { 3156 struct yaffs_obj *obj; 3157 3158 if (!path) { 3159 yaffsfs_SetError(-EFAULT); 3160 return -1; 3161 } 3162 3163 if (yaffsfs_CheckPath(path) < 0) { 3164 yaffsfs_SetError(-ENAMETOOLONG); 3165 return -1; 3166 } 3167 3168 obj = yaffsfs_FindObject(NULL, path, 0, 1, NULL, NULL, NULL); 3169 3170 if (obj) 3171 return yaffsfs_CountHandles(obj); 3172 else 3173 return -1; 3174 } 3175 3176 int yaffs_get_error(void) 3177 { 3178 return yaffsfs_GetLastError(); 3179 } 3180 3181 int yaffs_set_error(int error) 3182 { 3183 yaffsfs_SetError(error); 3184 return 0; 3185 } 3186 3187 int yaffs_dump_dev(const YCHAR *path) 3188 { 3189 #if 1 3190 path = path; 3191 #else 3192 YCHAR *rest; 3193 3194 struct yaffs_obj *obj = yaffsfs_FindRoot(path, &rest); 3195 3196 if (obj) { 3197 struct yaffs_dev *dev = obj->my_dev; 3198 3199 printf("\n" 3200 "n_page_writes.......... %d\n" 3201 "n_page_reads........... %d\n" 3202 "n_erasures....... %d\n" 3203 "n_gc_copies............ %d\n" 3204 "garbageCollections... %d\n" 3205 "passiveGarbageColl'ns %d\n" 3206 "\n", 3207 dev->n_page_writes, 3208 dev->n_page_reads, 3209 dev->n_erasures, 3210 dev->n_gc_copies, 3211 dev->garbageCollections, dev->passiveGarbageCollections); 3212 3213 } 3214 #endif 3215 return 0; 3216 } 3217