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