00001
00007 #include "uffs/uffs_fs.h"
00008 #include "uffs/uffs_config.h"
00009 #include "uffs/ubuffer.h"
00010 #include "uffs/uffs_ecc.h"
00011 #include "uffs/uffs_badblock.h"
00012 #include "uffs/uffs_os.h"
00013 #include <string.h>
00014
00015 #define PFX "fs:"
00016
00017 #define GET_SERIAL_FROM_NODE(obj) ((obj)->type == UFFS_TYPE_DIR ? (obj)->node->u.dir.serial : (obj)->node->u.file.serial)
00018 #define GET_BLOCK_FROM_NODE(obj) ((obj)->type == UFFS_TYPE_DIR ? (obj)->node->u.dir.block : (obj)->node->u.file.block)
00019
00020 static URET _PrepareOpenObj(uffs_Object *obj, const char *fullname, int oflag, int pmode);
00021 static URET _CreateObjectUnder(uffs_Object *obj);
00022 static void _ReleaseObjectResource(uffs_Object *obj);
00023
00024
00025 static int _object_buf[sizeof(uffs_Object) * MAX_OBJECT_HANDLE / sizeof(int)];
00026 static struct ubufm _object_dis = {
00027 _object_buf,
00028 sizeof(uffs_Object),
00029 MAX_OBJECT_HANDLE,
00030 NULL,
00031 };
00032
00033 URET uffs_InitObjectBuf(void)
00034 {
00035 if(uBufInit(&_object_dis) < 0) return U_FAIL;
00036 else return U_SUCC;
00037 }
00038
00039 uffs_Object * uffs_GetObject(void)
00040 {
00041 uffs_Object * obj;
00042 obj = (uffs_Object *)uBufGet(&_object_dis);
00043 if (obj) {
00044 memset(obj, 0, sizeof(uffs_Object));
00045 obj->openSucc = U_FALSE;
00046 }
00047 return obj;
00048 }
00049
00050 void uffs_PutObject(uffs_Object *obj)
00051 {
00052 uBufPut(obj, &_object_dis);
00053 }
00054
00055 int uffs_GetObjectIndex(uffs_Object *obj)
00056 {
00057 return uBufGetIndex(obj, &_object_dis);
00058 }
00059
00060 uffs_Object * uffs_GetObjectByIndex(int idx)
00061 {
00062 return (uffs_Object *) uBufGetBufByIndex(idx, &_object_dis);
00063 }
00064
00065 static void uffs_ObjectDevLock(uffs_Object *obj)
00066 {
00067 if (obj) {
00068 if (obj->dev) {
00069 if (obj->devLockCount == 0) {
00070 uffs_DeviceLock(obj->dev);
00071 }
00072 obj->devLockCount++;
00073 }
00074 }
00075 }
00076
00077 static void uffs_ObjectDevUnLock(uffs_Object *obj)
00078 {
00079 if (obj) {
00080 if (obj->dev) {
00081 obj->devLockCount--;
00082 if (obj->devLockCount == 0) {
00083 uffs_DeviceUnLock(obj->dev);
00084 }
00085 }
00086 }
00087 }
00088
00090 static int _getpath(const char *fullname, char *path)
00091 {
00092 int i;
00093 int len;
00094 int found = 0;
00095
00096 if(fullname[0] == 0) return 0;
00097 if(fullname[0] != '/') {
00098 path[0] = '/';
00099 strcpy(path + 1, fullname);
00100 }
00101 else {
00102 strcpy(path, fullname);
00103 }
00104
00105 len = strlen(path);
00106 for (i = len; i > 0 && path[i] != '/'; i--) {
00107 path[i] = '\0';
00108 }
00109
00110 return i + 1;
00111 }
00112
00113 static const char * _getfilename(const char *all)
00114 {
00115 int i;
00116 int len;
00117
00118 len = strlen(all);
00119
00120 for(i = len - 1; i >= 0; i--){
00121 if(all[i] == '/'){
00122 return all + i + 1;
00123 }
00124 }
00125 return all;
00126 }
00127
00128 URET uffs_CreateObject(uffs_Object *obj, const char *fullname, int oflag, int pmode)
00129 {
00130 URET ret = U_FAIL;
00131
00132 oflag |= UO_CREATE;
00133
00134 if (_PrepareOpenObj(obj, fullname, oflag, pmode) == U_SUCC) {
00135 uffs_ObjectDevLock(obj);
00136 ret = _CreateObjectUnder(obj);
00137 uffs_ObjectDevUnLock(obj);
00138 }
00139
00140 return ret;
00141 }
00142
00143
00144
00145 static int find_maxMatchedMountPoint(const char *path)
00146 {
00147 char buf[MAX_PATH_LENGTH+2] = {0};
00148 int pos;
00149 uffs_Device *dev;
00150
00151 pos = strlen(path);
00152 memcpy(buf, path, pos + 1);
00153
00154 while(pos > 0) {
00155 if ((dev = uffs_GetDevice(buf)) != NULL ) {
00156 uffs_PutDevice(dev);
00157 return pos;
00158 }
00159 else {
00160 buf[pos - 1] = '\0';
00161
00162
00163 for (; pos > 0 && buf[pos-1] != '/'; pos--)
00164 buf[pos-1] = '\0';
00165 }
00166 };
00167
00168 return pos;
00169 }
00170
00171 static URET _CreateObjectUnder(uffs_Object *obj)
00172 {
00176 uffs_Buf *buf = NULL;
00177 uffs_fileInfo fi, *pfi;
00178 URET ret;
00179
00180 TreeNode *node;
00181
00182 if (obj->type == UFFS_TYPE_DIR) {
00183
00184 node = uffs_FindFileNodeByName(obj->dev, obj->name, obj->nameLen, obj->sum, obj->father);
00185 if (node != NULL) {
00186 obj->err = UEEXIST;
00187 return U_FAIL;
00188 }
00189 obj->node = uffs_FindDirNodeByName(obj->dev, obj->name, obj->nameLen, obj->sum, obj->father);
00190 }
00191 else {
00192
00193 node = uffs_FindDirNodeByName(obj->dev, obj->name, obj->nameLen, obj->sum, obj->father);
00194 if (node != NULL) {
00195 obj->err = UEEXIST;
00196 return U_FAIL;
00197 }
00198 obj->node = uffs_FindFileNodeByName(obj->dev, obj->name, obj->nameLen, obj->sum, obj->father);
00199 }
00200
00201 if (obj->node) {
00202
00203 obj->serial = GET_SERIAL_FROM_NODE(obj);
00204
00205 buf = uffs_BufGetEx(obj->dev, obj->type, obj->node, 0);
00206
00207 if(buf == NULL) {
00208 uffs_Perror(UFFS_ERR_SERIOUS, PFX"found in tree, but can' load buffer ?\n");
00209 goto err;
00210 }
00211
00212 pfi = (uffs_fileInfo *)(buf->data);
00213 obj->access = pfi->access;
00214 obj->attr = pfi->attr;
00215 obj->createTime = pfi->createTime;
00216 obj->lastModify = pfi->lastModify;
00217 uffs_BufPut(obj->dev, buf);
00218
00219 obj->pos = 0;
00220
00221 obj->openSucc = U_TRUE;
00222 ret = uffs_TruncateObject(obj, 0);
00223 if (ret != U_SUCC) {
00224 obj->openSucc = U_FALSE;
00225 }
00226 return ret;
00227 }
00228
00229
00230 obj->serial = uffs_FindFreeFsnSerial(obj->dev);
00231
00232 if(obj->dev->tree.erasedCount < MINIMUN_ERASED_BLOCK) {
00233 uffs_Perror(UFFS_ERR_NOISY, PFX"insufficient block in create obj\n");
00234 goto err;
00235 }
00236
00237 buf = uffs_BufNew(obj->dev, obj->type, obj->father, obj->serial, 0);
00238 if(buf == NULL) {
00239 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Can't new buffer when create obj!\n");
00240 goto err;
00241 }
00242
00243 memset(&fi, 0, sizeof(uffs_fileInfo));
00244 memcpy(fi.name, obj->name, obj->nameLen);
00245 fi.name[obj->nameLen] = '\0';
00246 fi.name_len = obj->nameLen;
00247 fi.access = 0;
00248 fi.attr |= FILE_ATTR_WRITE;
00249 if (obj->type == UFFS_TYPE_DIR)
00250 fi.attr |= FILE_ATTR_DIR;
00251 fi.createTime = fi.lastModify = uffs_GetCurDateTime();
00252
00253 obj->createTime = fi.createTime;
00254 obj->lastModify = fi.lastModify;
00255 obj->attr = fi.attr;
00256 obj->access = fi.access;
00257
00258 uffs_BufWrite(obj->dev, buf, &fi, 0, sizeof(uffs_fileInfo));
00259 uffs_BufPut(obj->dev, buf);
00260
00261
00262 uffs_BufFlush(obj->dev);
00263
00264
00265 if (obj->type == UFFS_TYPE_DIR)
00266 obj->node = uffs_FindDirNodeFromTree(obj->dev, obj->serial);
00267 else
00268 obj->node = uffs_FindFileNodeFromTree(obj->dev, obj->serial);
00269
00270 if(obj->node == NULL) {
00271 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't find the node in the tree ?\n");
00272 goto err;
00273 }
00274
00275 if (obj->type == UFFS_TYPE_DIR) {
00276
00277 }
00278 else {
00279 obj->node->u.file.len = 0;
00280 }
00281
00282 if (HAVE_BADBLOCK(obj->dev)) uffs_RecoverBadBlock(obj->dev);
00283 obj->openSucc = U_TRUE;
00284
00285 return U_SUCC;
00286
00287 err:
00288 if (buf && obj->dev) {
00289 uffs_BufPut(obj->dev, buf);
00290 buf = NULL;
00291 }
00292
00293 return U_FAIL;
00294 }
00295
00296
00297 static URET _OpenObjectUnder(uffs_Object *obj)
00298 {
00299 uffs_Buf *buf = NULL;
00300 uffs_fileInfo *fi = NULL;
00301
00302 uffs_DeviceLock(obj->dev);
00303
00304
00305 if (obj->type == UFFS_TYPE_DIR) {
00306 obj->node = uffs_FindDirNodeByName(obj->dev, obj->name, obj->nameLen, obj->sum, obj->father);
00307 }
00308 else {
00309 obj->node = uffs_FindFileNodeByName(obj->dev, obj->name, obj->nameLen, obj->sum, obj->father);
00310 }
00311
00312 if(obj->node == NULL) {
00313
00314 if(obj->oflag & UO_CREATE){
00315
00316 return _CreateObjectUnder(obj);
00317 }
00318 else {
00319 obj->err = UENOENT;
00320
00321 goto err;
00322 }
00323 }
00324
00325 obj->serial = GET_SERIAL_FROM_NODE(obj);
00326
00327 buf = uffs_BufGetEx(obj->dev, obj->type, obj->node, 0);
00328
00329 if(buf == NULL) {
00330 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get buf when open!\n");
00331 goto err;
00332 }
00333
00334 fi = (uffs_fileInfo *)(buf->data);
00335 obj->attr = fi->attr;
00336 obj->createTime = fi->createTime;
00337 obj->lastModify = fi->lastModify;
00338 obj->access = fi->access;
00339 uffs_BufPut(obj->dev, buf);
00340
00341 if((obj->oflag & (UO_CREATE | UO_EXCL)) == (UO_CREATE | UO_EXCL)){
00342 obj->err = UEEXIST;
00343 goto err;
00344 }
00345
00346 if(obj->oflag & UO_TRUNC) {
00347 if(uffs_TruncateObject(obj, 0) == U_FAIL){
00348
00349 goto err;
00350 }
00351 }
00352
00353 obj->err = UENOERR;
00354
00355 obj->openSucc = U_TRUE;
00356 uffs_DeviceUnLock(obj->dev);
00357
00358 return U_SUCC;
00359
00360 err:
00361 if(obj->name) {
00362 uffs_MemFree(obj->dev, obj->name);
00363 obj->name = NULL;
00364 }
00365 if(obj->dev) {
00366 uffs_DeviceUnLock(obj->dev);
00367 uffs_PutDevice(obj->dev);
00368 obj->dev = NULL;
00369 }
00370
00371 return U_FAIL;
00372 }
00373
00374 static int getPathPart(const char *path, int *pos)
00375 {
00376 int len = 0;
00377
00378 for (len = 0; path[len+(*pos)] != '\0' && path[len+(*pos)] != '/'; len++) ;
00379
00380 *pos += len;
00381
00382 return len;
00383 }
00384
00385 static u16 _GetDirSerial(uffs_Device *dev, const char *path, u16 father)
00386 {
00387 int pos = 0;
00388 int pos_last = 0;
00389 int len = 0;
00390 char part[MAX_FILENAME_LENGTH+2] = {0};
00391 TreeNode * node;
00392 u16 sum;
00393 u16 serial = father;
00394
00395 while((len = getPathPart(path, &pos)) > 0) {
00396 memcpy(part, path + pos_last, len);
00397 part[len] = '\0';
00398 sum = uffs_MakeSum16(part, len);
00399 node = uffs_FindDirNodeByName(dev, part, len, sum, serial);
00400 if (node) {
00401 serial = node->u.dir.serial;
00402 pos_last = ++pos;
00403 }
00404 else {
00405 return INVALID_UFFS_SERIAL;
00406 }
00407 }
00408
00409 return serial;
00410 }
00411
00412
00413
00414
00415
00416
00417 static URET _PrepareOpenObj(uffs_Object *obj, const char *fullname, int oflag, int pmode)
00418 {
00419 URET ret = U_SUCC;
00420 char buf[MAX_PATH_LENGTH+2] = {0};
00421 char mount[MAX_PATH_LENGTH+2] = {0};
00422 char *start_path = mount;
00423 int pos;
00424 int len;
00425 char *name;
00426
00427 obj->dev = NULL;
00428 obj->name = NULL;
00429
00430 if((oflag & (UO_WRONLY | UO_RDWR)) == (UO_WRONLY | UO_RDWR)){
00431
00432 uffs_Perror(UFFS_ERR_NOISY, PFX"UO_WRONLY and UO_RDWR can't appear together\n");
00433 obj->err = UEINVAL;
00434 return U_FAIL;
00435 }
00436
00437 obj->pos = 0;
00438
00439
00440 obj->oflag = oflag;
00441 obj->pmode = pmode;
00442
00443
00444
00445 if (oflag & UO_DIR) {
00447 obj->type = UFFS_TYPE_DIR;
00448 len = strlen(fullname);
00449 memcpy(buf, fullname, len);
00450 if (buf[len - 1] != '/') {
00451 buf[len] = '/';
00452 buf[len+1] = '\0';
00453 }
00454
00455
00456 }
00457 else {
00459 obj->type = UFFS_TYPE_FILE;
00460
00461 _getpath(fullname, buf);
00462
00463 }
00464
00465 pos = find_maxMatchedMountPoint(buf);
00466 if (pos == 0) {
00467
00468
00469 obj->err = UENOENT;
00470 return U_FAIL;
00471 }
00472
00473
00474 memcpy(mount, buf, pos);
00475 mount[pos] = '\0';
00476
00477 obj->dev = uffs_GetDevice(mount);
00478 if (obj->dev == NULL) {
00479 obj->err = UENOENT;
00480 return U_FAIL;
00481 }
00482
00483 uffs_DeviceLock(obj->dev);
00484
00485
00486 if (HAVE_BADBLOCK(obj->dev)) uffs_RecoverBadBlock(obj->dev);
00487
00488
00489 len = strlen(fullname) - strlen(mount) + 1;
00490 memcpy(buf, fullname + strlen(mount) - 1, len);
00491 buf[len] = '\0';
00492
00493
00494 name = (char *) _getfilename(buf);
00495
00496
00497 _getpath(buf, start_path);
00498
00499
00500 obj->father = _GetDirSerial(obj->dev, start_path + 1, ROOT_DIR_ID);
00501 if (obj->father == INVALID_UFFS_SERIAL) {
00502 uffs_Perror(UFFS_ERR_NORMAL, PFX"can't open path %s\n", start_path);
00503 obj->err = UENOENT;
00504 goto err;
00505 }
00506
00507 obj->nameLen = strlen(name);
00508 obj->name = (char *) uffs_MemAlloc(obj->dev, obj->nameLen + 4);
00509 if(obj->name == NULL) {
00510 uffs_Perror(UFFS_ERR_SERIOUS, PFX"open, allocate mem fail when open\n");
00511 obj->err = UENOMEM;
00512 goto err;
00513 }
00514 memcpy(obj->name, name, obj->nameLen);
00515 obj->name[obj->nameLen] = '\0';
00516 obj->sum = uffs_MakeSum16(obj->name, obj->nameLen);
00517 obj->encode = UFFS_DEFAULT_ENCODE;
00518 obj->pagesOnHead = obj->dev->attr.pages_per_block - 1;
00519
00520 return U_SUCC;
00521
00522 err:
00523 if (obj->name) {
00524 uffs_MemFree(obj->dev, obj->name);
00525 obj->name = NULL;
00526 }
00527 if (obj->dev) {
00528 uffs_DeviceUnLock(obj->dev);
00529 uffs_PutDevice(obj->dev);
00530 obj->dev = NULL;
00531 }
00532
00533 return U_FAIL;
00534 }
00535
00536 URET uffs_OpenObject(uffs_Object *obj, const char *fullname, int oflag, int pmode)
00537 {
00538 URET ret = U_FAIL;
00539
00540 if (_PrepareOpenObj(obj, fullname, oflag, pmode) == U_SUCC)
00541 ret = _OpenObjectUnder(obj);
00542
00543 if(ret == U_FAIL)
00544 _ReleaseObjectResource(obj);
00545
00546 return ret;
00547 }
00548
00549 static void _ReleaseObjectResource(uffs_Object *obj)
00550 {
00551 if (obj) {
00552 if(obj->name) {
00553 uffs_MemFree(obj->dev, obj->name);
00554 obj->name = NULL;
00555 }
00556 if (obj->dev) {
00557 if (HAVE_BADBLOCK(obj->dev)) uffs_RecoverBadBlock(obj->dev);
00558 while (obj->devLockCount > 0) {
00559 uffs_ObjectDevUnLock(obj);
00560 }
00561 uffs_PutDevice(obj->dev);
00562 obj->dev = NULL;
00563 }
00564 }
00565 }
00566
00567 URET uffs_CloseObject(uffs_Object *obj)
00568 {
00569 uffs_Device *dev;
00570 uffs_Buf *buf;
00571 uffs_fileInfo fi;
00572
00573 if(obj == NULL || obj->dev == NULL) return U_FAIL;
00574 if (obj->openSucc != U_TRUE) goto out;
00575
00576 dev = obj->dev;
00577 uffs_ObjectDevLock(obj);
00578
00579 if(obj->oflag & (UO_WRONLY|UO_RDWR|UO_APPEND|UO_CREATE|UO_TRUNC)) {
00580
00581 #ifdef CHANGE_MODIFY_TIME
00582 if (obj->node) {
00583
00584 if (obj->type == UFFS_TYPE_DIR)
00585 buf = uffs_BufGetEx(dev, UFFS_TYPE_DIR, obj->node, 0);
00586 else
00587 buf = uffs_BufGetEx(dev, UFFS_TYPE_FILE, obj->node, 0);
00588
00589 if(buf == NULL) {
00590 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get file header\n");
00591 uffs_BufFlush(dev);
00592 goto out;
00593 }
00594 uffs_BufRead(dev, buf, &fi, 0, sizeof(uffs_fileInfo));
00595 fi.lastModify = uffs_GetCurDateTime();
00596 uffs_BufWrite(dev, buf, &fi, 0, sizeof(uffs_fileInfo));
00597 uffs_BufPut(dev, buf);
00598 }
00599 #endif
00600
00601 uffs_BufFlush(dev);
00602 }
00603 uffs_ObjectDevUnLock(obj);
00604
00605 out:
00606 _ReleaseObjectResource(obj);
00607
00608 return U_SUCC;
00609 }
00610
00611 static u16 _GetFdnByOfs(uffs_Object *obj, u32 ofs)
00612 {
00613 uffs_Device *dev = obj->dev;
00614 if(ofs < obj->pagesOnHead * dev->com.pgDataSize) {
00615 return 0;
00616 }
00617 else {
00618 ofs -= obj->pagesOnHead * dev->com.pgDataSize;
00619 return (ofs / (dev->com.pgDataSize * dev->attr.pages_per_block)) + 1;
00620 }
00621 }
00622
00623 static u16 _GetPageIdByOfs(uffs_Object *obj, u32 ofs)
00624 {
00625 uffs_Device *dev = obj->dev;
00626 if(ofs < obj->pagesOnHead * dev->com.pgDataSize) {
00627 return (ofs / dev->com.pgDataSize) + 1;
00628 }
00629 else {
00630 ofs -= (obj->pagesOnHead * dev->com.pgDataSize);
00631 ofs %= (dev->com.pgDataSize * dev->attr.pages_per_block);
00632 return ofs / dev->com.pgDataSize;
00633 }
00634 }
00635
00636 static UBOOL _IsAtTheStartOfBlock(uffs_Object *obj, u32 ofs)
00637 {
00638 uffs_Device *dev = obj->dev;
00639 int n;
00640
00641 if((ofs % dev->com.pgDataSize) != 0) return U_FALSE;
00642 if(ofs < obj->pagesOnHead * dev->com.pgDataSize) {
00643 return U_FALSE;
00644 }
00645 else {
00646 n = ofs - (obj->pagesOnHead * dev->com.pgDataSize);
00647 if(n % (dev->com.pgDataSize * dev->attr.pages_per_block) == 0) return U_TRUE;
00648 }
00649
00650 return U_FALSE;
00651 }
00652
00653 static u32 _GetStartOfDataBlock(uffs_Object *obj, u16 fdn)
00654 {
00655 if(fdn == 0) {
00656 return 0;
00657 }
00658 else {
00659 return (obj->pagesOnHead * obj->dev->com.pgDataSize) +
00660 (fdn - 1) * (obj->dev->com.pgDataSize * obj->dev->attr.pages_per_block);
00661 }
00662 }
00663
00664
00665 static int _WriteNewBlock(uffs_Object *obj,
00666 const void *data, u32 len,
00667 u16 father,
00668 u16 serial)
00669 {
00670 uffs_Device *dev = obj->dev;
00671 u16 pageID;
00672 int wroteSize = 0;
00673 int size;
00674 uffs_Buf *buf;
00675 URET ret;
00676
00677 for(pageID = 0; pageID < dev->attr.pages_per_block; pageID++) {
00678 size = (len - wroteSize) > dev->com.pgDataSize ?
00679 dev->com.pgDataSize : len - wroteSize;
00680 if(size <= 0) break;
00681
00682 buf = uffs_BufNew(dev, UFFS_TYPE_DATA, father, serial, pageID);
00683 if(buf == NULL) {
00684 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't create a new page ?\n");
00685 break;
00686 }
00687 ret = uffs_BufWrite(dev, buf, (u8 *)data + wroteSize, 0, size);
00688 uffs_BufPut(dev, buf);
00689
00690 if(ret != U_SUCC) {
00691 uffs_Perror(UFFS_ERR_SERIOUS, PFX"write data fail!\n");
00692 break;
00693 }
00694 wroteSize += size;
00695 obj->node->u.file.len += size;
00696 }
00697 return wroteSize;
00698 }
00699
00700 static int _WriteInternalBlock(uffs_Object *obj,
00701 TreeNode *node,
00702 u16 fdn,
00703 const void *data,
00704 u32 len,
00705 u32 blockOfs)
00706 {
00707 uffs_Device *dev = obj->dev;
00708 u16 maxPageID;
00709 u16 pageID;
00710 u32 size;
00711 u32 pageOfs;
00712 u32 wroteSize = 0;
00713 URET ret;
00714 uffs_Buf *buf;
00715 u32 startOfBlock;
00716 u8 type;
00717 u16 father, serial;
00718
00719 startOfBlock = _GetStartOfDataBlock(obj, fdn);
00720 if(fdn == 0) {
00721 type = UFFS_TYPE_FILE;
00722 father = node->u.file.father;
00723 serial = node->u.file.serial;
00724 }
00725 else {
00726 type = UFFS_TYPE_DATA;
00727 father = node->u.data.father;
00728 serial = fdn;
00729 }
00730
00731 if(fdn == 0) maxPageID = obj->pagesOnHead;
00732 else maxPageID = dev->attr.pages_per_block - 1;
00733
00734
00735 while(wroteSize < len) {
00736 pageID = blockOfs / dev->com.pgDataSize;
00737 if(fdn == 0) pageID++;
00738 if(pageID > maxPageID) break;
00739
00740 pageOfs = blockOfs % dev->com.pgDataSize;
00741 size = (len - wroteSize + pageOfs) > dev->com.pgDataSize ?
00742 (dev->com.pgDataSize - pageOfs) : (len - wroteSize);
00743
00744 if((obj->node->u.file.len % dev->com.pgDataSize) == 0 &&
00745 (blockOfs + startOfBlock) == obj->node->u.file.len) {
00746
00747 buf = uffs_BufNew(dev, type, father, serial, pageID);
00748 if(buf == NULL) {
00749 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can create a new buf!\n");
00750 break;
00751 }
00752 }
00753 else {
00754 buf = uffs_BufGetEx(dev, type, node, pageID);
00755 if(buf == NULL) {
00756 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get buffer ?\n");
00757 break;
00758 }
00759 }
00760
00761 ret = uffs_BufWrite(dev, buf, (u8 *)data + wroteSize, pageOfs, size);
00762 uffs_BufPut(dev, buf);
00763 if(ret == U_FAIL) {
00764 uffs_Perror(UFFS_ERR_SERIOUS, PFX"write inter data fail!\n");
00765 break;
00766 }
00767
00768 wroteSize += size;
00769 blockOfs += size;
00770
00771 if(startOfBlock + blockOfs > obj->node->u.file.len)
00772 obj->node->u.file.len = startOfBlock + blockOfs;
00773
00774 }
00775
00776 return wroteSize;
00777 }
00778
00779
00780
00788 int uffs_WriteObject(uffs_Object *obj, const void *data, int len)
00789 {
00790 uffs_Device *dev = obj->dev;
00791 TreeNode *fnode = obj->node;
00792 int remain = len;
00793 u16 fdn;
00794 u32 write_start;
00795 TreeNode *dnode;
00796 u32 size;
00797
00798 if (obj == NULL) return 0;
00799 if (obj->dev == NULL || obj->openSucc == U_FALSE) return 0;
00800
00801 if (obj->type == UFFS_TYPE_DIR) {
00802 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't write to an dir object!\n");
00803 return 0;
00804 }
00805
00806 if(obj->pos > fnode->u.file.len) return 0;
00807
00808 uffs_ObjectDevLock(obj);
00809
00810 if(obj->oflag == UO_RDONLY) return 0;
00811 if(obj->oflag & UO_APPEND) obj->pos = fnode->u.file.len;
00812
00813 while(remain > 0) {
00814
00815 write_start = obj->pos + len - remain;
00816 if(write_start > fnode->u.file.len) {
00817 uffs_Perror(UFFS_ERR_SERIOUS, PFX"write point out of file ?\n");
00818 break;
00819 }
00820
00821 fdn = _GetFdnByOfs(obj, write_start);
00822
00823 if(write_start == fnode->u.file.len && fdn > 0 &&
00824 write_start == _GetStartOfDataBlock(obj, fdn)) {
00825 if(dev->tree.erasedCount < MINIMUN_ERASED_BLOCK) {
00826 uffs_Perror(UFFS_ERR_NOISY, PFX"insufficient block in write obj, new block\n");
00827 break;
00828 }
00829 size = _WriteNewBlock(obj, (u8 *)data + len - remain, remain, fnode->u.file.serial, fdn);
00830
00831
00832 uffs_BufFlush(dev);
00833
00834 if(size == 0) break;
00835 remain -= size;
00836 }
00837 else {
00838
00839 if(fdn == 0)
00840 dnode = obj->node;
00841 else
00842 dnode = uffs_FindDataNode(dev, fnode->u.file.serial, fdn);
00843
00844 if(dnode == NULL) {
00845 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't find data node in tree ?\n");
00846 break;
00847 }
00848 size = _WriteInternalBlock(obj, dnode, fdn,
00849 (u8 *)data + len - remain, remain,
00850 write_start - _GetStartOfDataBlock(obj, fdn));
00851 #ifdef FLUSH_BUF_AFTER_WRITE
00852 uffs_BufFlush(dev);
00853 #endif
00854 if(size == 0) break;
00855 remain -= size;
00856 }
00857 }
00858
00859 obj->pos += (len - remain);
00860
00861 if (HAVE_BADBLOCK(dev)) uffs_RecoverBadBlock(dev);
00862
00863 uffs_ObjectDevUnLock(obj);
00864
00865 return len - remain;
00866 }
00867
00875 int uffs_ReadObject(uffs_Object *obj, void *data, int len)
00876 {
00877 uffs_Device *dev = obj->dev;
00878 TreeNode *fnode = obj->node;
00879 u32 remain = len;
00880 u16 fdn;
00881 u32 read_start;
00882 TreeNode *dnode;
00883 u32 size;
00884 uffs_Buf *buf;
00885 u32 blockOfs;
00886 u16 pageID;
00887 u8 type;
00888 u32 pageOfs;
00889
00890 if (obj == NULL) return 0;
00891 if (obj->dev == NULL || obj->openSucc == U_FALSE) return 0;
00892
00893
00894 if (obj->type == UFFS_TYPE_DIR) {
00895 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't read from a dir object!\n");
00896 return 0;
00897 }
00898
00899 if(obj->pos > fnode->u.file.len) return 0;
00900 if(obj->oflag & UO_WRONLY) return 0;
00901
00902 uffs_ObjectDevLock(obj);
00903
00904 while(remain > 0) {
00905 read_start = obj->pos + len - remain;
00906 if(read_start >= fnode->u.file.len) {
00907
00908 break;
00909 }
00910
00911 fdn = _GetFdnByOfs(obj, read_start);
00912 if(fdn == 0) {
00913 dnode = obj->node;
00914 type = UFFS_TYPE_FILE;
00915 }
00916 else {
00917 type = UFFS_TYPE_DATA;
00918 dnode = uffs_FindDataNode(dev, fnode->u.file.serial, fdn);
00919 if(dnode == NULL) {
00920 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get data node in entry!\n");
00921 break;
00922 }
00923 }
00924
00925 blockOfs = _GetStartOfDataBlock(obj, fdn);
00926 pageID = (read_start - blockOfs) / dev->com.pgDataSize;
00927
00928 if(fdn == 0) {
00933 pageID++;
00934 }
00935
00936 buf = uffs_BufGetEx(dev, type, dnode, (u16)pageID);
00937 if(buf == NULL) {
00938 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get buffer when read obj.\n");
00939 break;
00940 }
00941
00942 pageOfs = read_start % dev->com.pgDataSize;
00943 if(pageOfs >= buf->dataLen) {
00944
00945 uffs_BufPut(dev, buf);
00946 break;
00947 }
00948 size = (remain + pageOfs > buf->dataLen ? buf->dataLen - pageOfs: remain);
00949
00950 uffs_BufRead(dev, buf, (u8 *)data + len - remain, pageOfs, size);
00951 uffs_BufPut(dev, buf);
00952
00953 remain -= size;
00954 }
00955
00956 obj->pos += (len - remain);
00957
00958 if (HAVE_BADBLOCK(dev)) uffs_RecoverBadBlock(dev);
00959
00960 uffs_ObjectDevUnLock(obj);
00961
00962 return len - remain;
00963 }
00964
00972 long uffs_SeekObject(uffs_Object *obj, long offset, int origin)
00973 {
00974 if (obj->type == UFFS_TYPE_DIR) {
00975 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't seek a dir object!\n");
00976 return 0;
00977 }
00978
00979 uffs_ObjectDevLock(obj);
00980
00981 switch(origin) {
00982 case USEEK_CUR:
00983 if(obj->pos + offset > obj->node->u.file.len) {
00984 obj->pos = obj->node->u.file.len;
00985 }
00986 else {
00987 obj->pos += offset;
00988 }
00989 break;
00990 case USEEK_SET:
00991 if(offset > (long) obj->node->u.file.len) {
00992 obj->pos = obj->node->u.file.len;
00993 }
00994 else {
00995 obj->pos = offset;
00996 }
00997 break;
00998 case USEEK_END:
00999 if ( offset>0 ) {
01000 obj->pos = obj->node->u.file.len;
01001 }
01002 else if((offset >= 0 ? offset : -offset) > (long) obj->node->u.file.len) {
01003 obj->pos = 0;
01004 }
01005 else {
01006 obj->pos = obj->node->u.file.len + offset;
01007 }
01008 break;
01009 }
01010
01011 uffs_ObjectDevUnLock(obj);
01012
01013 return (long) obj->pos;
01014 }
01015
01021 int uffs_GetCurOffset(uffs_Object *obj)
01022 {
01023 if (obj) {
01024 if (obj->dev && obj->openSucc == U_TRUE)
01025 return obj->pos;
01026 }
01027 return -1;
01028 }
01029
01035 int uffs_EndOfFile(uffs_Object *obj)
01036 {
01037 if (obj) {
01038 if (obj->dev && obj->type == UFFS_TYPE_FILE && obj->openSucc == U_TRUE) {
01039 if (obj->pos >= obj->node->u.file.len) {
01040 return 1;
01041 }
01042 else {
01043 return 0;
01044 }
01045 }
01046 }
01047
01048 return -1;
01049 }
01050
01051 static URET _CoverOnePage(uffs_Device *dev,
01052 uffs_Tags *old,
01053 uffs_Tags *newTag,
01054 u16 newBlock,
01055 u16 page,
01056 int newTimeStamp,
01057 uffs_Buf *buf,
01058 u32 length)
01059 {
01060 newTag->father = buf->father;
01061 newTag->serial = buf->serial;
01062 newTag->type = buf->type;
01063 newTag->blockTimeStamp = newTimeStamp;
01064 newTag->dataLength = length;
01065 newTag->dataSum = old->dataSum;
01066 newTag->pageID = (u8)(buf->pageID);
01067
01068
01069 return uffs_WriteDataToNewPage(dev, newBlock, page, newTag, buf);
01070 }
01071
01072 static URET _TruncateInternalWithBlockRecover(uffs_Object *obj, u16 fdn, u32 remain)
01073 {
01074 uffs_Device *dev = obj->dev;
01075 TreeNode *fnode = obj->node;
01076 u16 pageID, maxPageID;
01077 TreeNode *node, *newNode;
01078 u16 block, newBlock;
01079 uffs_blockInfo *bc = NULL, *newBc = NULL;
01080 uffs_Buf *buf = NULL;
01081 uffs_Tags *tag, *newTag;
01082 URET ret = U_FAIL;
01083 u8 type;
01084 u32 startOfBlock;
01085 u32 end;
01086 int timeStamp;
01087 u16 page;
01088
01089 if(fdn == 0) {
01090 node = fnode;
01091 block = node->u.file.block;
01092 type = UFFS_TYPE_FILE;
01093 maxPageID = obj->pagesOnHead;
01094 }
01095 else {
01096 node = uffs_FindDataNode(dev, fnode->u.file.serial, fdn);
01097 if(node == NULL) {
01098 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't find data node when truncate obj\n");
01099 goto _err;
01100 }
01101 block = node->u.data.block;
01102 type = UFFS_TYPE_DATA;
01103 maxPageID = dev->attr.pages_per_block - 1;
01104 }
01105
01106
01107 bc = uffs_GetBlockInfo(dev, block);
01108 if(bc == NULL) {
01109 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get block info when truncate obj\n");
01110 goto _err;
01111 }
01112
01113 newNode = uffs_GetErased(dev);
01114 if(newNode == NULL) {
01115 uffs_Perror(UFFS_ERR_NOISY, PFX"insufficient erased block, can't truncate obj.\n");
01116 goto _err;
01117 }
01118 newBlock = newNode->u.list.block;
01119 newBc = uffs_GetBlockInfo(dev, newBlock);
01120 if(newBc == NULL) {
01121 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get block info when truncate obj\n");
01122 goto _err;
01123 }
01124
01125 startOfBlock = _GetStartOfDataBlock(obj, fdn);
01126 timeStamp = uffs_GetBlockTimeStamp(dev, bc);
01127 timeStamp = uffs_GetNextBlockTimeStamp(timeStamp);
01128
01129 for(pageID = 0; pageID <= maxPageID; pageID++) {
01130 page = uffs_FindPageInBlockWithPageId(dev, bc, pageID);
01131 if(page == UFFS_INVALID_PAGE) {
01132 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unknown error, truncate\n");
01133 break;
01134 }
01135 page = uffs_FindBestPageInBlock(dev, bc, page);
01136 buf = uffs_BufClone(dev, NULL);
01137 if(buf == NULL) {
01138 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't clone page buffer\n");
01139 goto _err;
01140 }
01141 tag = &(bc->spares[page].tag);
01142 uffs_LoadPhiDataToBuf(dev, buf, bc->blockNum, page);
01143
01144 buf->father = tag->father;
01145 buf->serial = tag->serial;
01146 buf->type = tag->type;
01147 buf->pageID = tag->pageID;
01148 buf->dataLen = tag->dataLength;
01149
01150 newTag = &(newBc->spares[pageID].tag);
01151 if(fdn == 0 && pageID == 0) {
01152
01153 ret = _CoverOnePage(dev, tag, newTag, newBlock, pageID, timeStamp, buf, buf->dataLen);
01154 if(ret != U_SUCC) break;
01155 }
01156 else {
01157 end = ((fdn == 0) ? (pageID - 1) * dev->com.pgDataSize :
01158 pageID * dev->com.pgDataSize);
01159 end += tag->dataLength;
01160 end += startOfBlock;
01161
01162 if(remain > end) {
01163 if(tag->dataLength != dev->com.pgDataSize) {
01164 uffs_Perror(UFFS_ERR_NOISY, PFX" ???? unknown error when truncate. \n");
01165 break;
01166 }
01167 ret = _CoverOnePage(dev, tag, newTag, newBlock, pageID, timeStamp, buf, buf->dataLen);
01168 if(ret != U_SUCC) break;
01169 }
01170 else if(remain == end) {
01171 ret = _CoverOnePage(dev, tag, newTag, newBlock, pageID, timeStamp, buf, buf->dataLen);
01172 if(ret != U_SUCC) break;
01173 }
01174 else if(remain < end) {
01175 buf->dataLen = tag->dataLength - (end - remain);
01176 if(buf->dataLen == 0) {
01177 ret = U_SUCC;
01178 break;
01179 }
01180 memset(buf->data + buf->dataLen, 0, dev->com.pgDataSize - buf->dataLen);
01181 ret = _CoverOnePage(dev, tag, newTag, newBlock, pageID, timeStamp, buf, buf->dataLen);
01182 break;
01183 }
01184 }
01185 uffs_BufFreeClone(dev, buf);
01186 buf = NULL;
01187 }
01188
01189 _err:
01190 if(buf != NULL) {
01191 uffs_BufFreeClone(dev, buf);
01192 buf = NULL;
01193 }
01194 if(ret == U_SUCC) {
01195
01196 uffs_SetTreeNodeBlock(type, node, newNode->u.list.block);
01197 newNode->u.list.block = block;
01198 dev->ops->EraseBlock(dev, newNode->u.list.block);
01199 uffs_InsertToErasedListTail(dev, newNode);
01200 }
01201 else {
01202
01203 dev->ops->EraseBlock(dev, newBlock);
01204 uffs_InsertToErasedListTail(dev, newNode);
01205 }
01206
01207 if(bc) uffs_ExpireBlockInfo(dev, bc, UFFS_ALL_PAGES);
01208 if(bc) uffs_PutBlockInfo(dev, bc);
01209 if(newBc) uffs_ExpireBlockInfo(dev, newBc, UFFS_ALL_PAGES);
01210 if(newBc) uffs_PutBlockInfo(dev, newBc);
01211
01212 return U_SUCC;
01213 }
01214
01215
01216 URET uffs_TruncateObject(uffs_Object *obj, u32 remain)
01217 {
01218 uffs_Device *dev = obj->dev;
01219 TreeNode *fnode = obj->node;
01220 u16 fdn;
01221 u32 flen;
01222 u32 startOfBlock;
01223 TreeNode *node;
01224 uffs_blockInfo *bc;
01225 uffs_Buf *buf;
01226 u16 page;
01227
01228 if (obj == NULL) return U_FAIL;
01229 if (obj->dev == NULL || obj->openSucc == U_FALSE) return U_FAIL;
01230
01231
01232
01233 if (obj->type == UFFS_TYPE_DIR) {
01234 obj->err = UEEXIST;
01235 return U_FAIL;
01236 }
01237
01238 if(remain > fnode->u.file.len) return U_FAIL;
01239
01240 uffs_ObjectDevLock(obj);
01241
01242 uffs_BufFlush(dev);
01243
01244 while(fnode->u.file.len > remain) {
01245 flen = fnode->u.file.len;
01246 fdn = _GetFdnByOfs(obj, flen - 1);
01247
01248 startOfBlock = _GetStartOfDataBlock(obj, fdn);
01249 if(remain <= startOfBlock && fdn > 0) {
01250 node = uffs_FindDataNode(dev, fnode->u.file.serial, fdn);
01251 if(node == NULL) {
01252 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't find data node when trancate obj.\n");
01253 uffs_ObjectDevUnLock(obj);
01254 return U_FAIL;
01255 }
01256 bc = uffs_GetBlockInfo(dev, node->u.data.block);
01257 if(bc == NULL) {
01258 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get block info when trancate obj.\n");
01259 uffs_ObjectDevUnLock(obj);
01260 return U_FAIL;
01261 }
01262 for(page = 0; page < dev->attr.pages_per_block; page++) {
01263 buf = uffs_BufFind(dev, fnode->u.file.serial, fdn, page);
01264 if(buf) uffs_BufSetMark(buf, UFFS_BUF_EMPTY);
01265 }
01266 uffs_ExpireBlockInfo(dev, bc, UFFS_ALL_PAGES);
01267 dev->ops->EraseBlock(dev, node->u.data.block);
01268 uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, node);
01269 node->u.list.block = bc->blockNum;
01270 uffs_PutBlockInfo(dev, bc);
01271 uffs_InsertToErasedListTail(dev, node);
01272 fnode->u.file.len = startOfBlock;
01273 }
01274 else {
01275 if(_TruncateInternalWithBlockRecover(obj, fdn, remain) == U_SUCC) {
01276 fnode->u.file.len = remain;
01277 }
01278 else {
01279 uffs_Perror(UFFS_ERR_SERIOUS, PFX"fail to truncate obj\n");
01280 uffs_ObjectDevUnLock(obj);
01281 return U_FAIL;
01282 }
01283 }
01284 }
01285
01286 if (HAVE_BADBLOCK(dev)) uffs_RecoverBadBlock(dev);
01287
01288 uffs_ObjectDevUnLock(obj);
01289
01290 return U_SUCC;
01291
01292 }
01293
01294
01298 URET uffs_DeleteObject(const char * name)
01299 {
01300 uffs_Object *obj;
01301 TreeNode *node;
01302 uffs_Device *dev;
01303 u16 block;
01304 uffs_Buf *buf;
01305 URET ret = U_FAIL;
01306
01307 obj = uffs_GetObject();
01308 if (obj == NULL) goto err1;
01309
01310 if (uffs_OpenObject(obj, name, UO_RDWR|UO_DIR, US_IREAD|US_IWRITE) == U_FAIL) {
01311 if (uffs_OpenObject(obj, name, UO_RDWR, US_IREAD|US_IWRITE) == U_FAIL)
01312 goto err1;
01313 }
01314
01315 uffs_TruncateObject(obj, 0);
01316
01317 uffs_ObjectDevLock(obj);
01318 dev = obj->dev;
01319
01320 if (obj->type == UFFS_TYPE_DIR) {
01321
01322 node = uffs_FindDirNodeFromTreeWithFather(dev, obj->serial);
01323 if (node != NULL) goto err;
01324
01325 node = uffs_FindFileNodeFromTreeWithFather(dev, obj->serial);
01326 if (node != NULL) goto err;
01327 }
01328
01329 block = GET_BLOCK_FROM_NODE(obj);
01330 node = obj->node;
01331
01332
01333 uffs_BufFlush(dev);
01334 if (HAVE_BADBLOCK(dev)) uffs_RecoverBadBlock(dev);
01335
01336 buf = uffs_BufFind(dev, obj->father, obj->serial, 0);
01337 if (buf) {
01338
01339 if (buf->refCount != 0) {
01340 uffs_Perror(UFFS_ERR_NORMAL, PFX"Try to delete object but still have buf referenced.\n");
01341 goto err;
01342 }
01343 buf->mark = UFFS_BUF_EMPTY;
01344 }
01345 uffs_BreakFromEntry(dev, obj->type, node);
01346 dev->ops->EraseBlock(dev, block);
01347 node->u.list.block = block;
01348 uffs_InsertToErasedListTail(dev, node);
01349
01350 ret = U_SUCC;
01351 err:
01352 uffs_ObjectDevUnLock(obj);
01353 err1:
01354 _ReleaseObjectResource(obj);
01355
01356 return ret;
01357 }
01358
01359 URET uffs_RenameObject(const char *old_name, const char *new_name)
01360 {
01361 uffs_Object *obj;
01362 uffs_Device *dev;
01363 TreeNode *node;
01364 uffs_Buf *buf;
01365 uffs_fileInfo fi;
01366 char buf_old[MAX_PATH_LENGTH+2]= {0};
01367 char buf_new[MAX_PATH_LENGTH+2]= {0};
01368 int pos, pos1;
01369 u16 father_new;
01370
01371 URET ret = U_FAIL;
01372
01373 if(strlen(old_name) >= MAX_PATH_LENGTH ||
01374 strlen(new_name) >= MAX_PATH_LENGTH) return U_FAIL;
01375 pos = find_maxMatchedMountPoint(old_name);
01376 pos1 = find_maxMatchedMountPoint(new_name);
01377 if (pos <= 0 || pos <= 0 || pos != pos1) {
01378 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't rename object with different mount point\n");
01379 return U_FAIL;
01380 }
01381
01382 _getpath(old_name, buf_old);
01383 _getpath(new_name, buf_new);
01384
01385 obj = uffs_GetObject();
01386
01387 if (obj == NULL) {
01388 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Can't get new object.\n");
01389 return U_FAIL;
01390 }
01391
01392 if (strcmp(buf_new, "/") == 0) {
01393 father_new = ROOT_DIR_ID;
01394 }
01395 else {
01396 pos = strlen(buf_new);
01397 if (buf_new[pos - 1] == '/') buf_new[pos - 1] = '\0';
01398 if (uffs_OpenObject(obj, buf_new, UO_RDONLY|UO_DIR, US_IREAD) == U_SUCC) {
01399 father_new = obj->serial;
01400 uffs_CloseObject(obj);
01401 }
01402 else {
01403 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't open dir %s\n", buf_new);
01404 goto err;
01405 }
01406 }
01407
01408 if (uffs_OpenObject(obj, new_name, UO_RDONLY, US_IREAD) == U_SUCC) {
01409
01410 uffs_CloseObject(obj);
01411 return U_FAIL;
01412 }
01413 if (uffs_OpenObject(obj, new_name, UO_RDONLY|UO_DIR, US_IREAD) == U_SUCC) {
01414
01415 uffs_CloseObject(obj);
01416 return U_FAIL;
01417 }
01418 _ReleaseObjectResource(obj);
01419 uffs_PutObject(obj);
01420 obj = uffs_GetObject();
01421
01422 if (uffs_OpenObject(obj, old_name, UO_RDWR, US_IREAD | US_IWRITE) == U_FAIL) {
01423 if (uffs_OpenObject(obj, old_name, UO_RDWR|UO_DIR, US_IREAD | US_IWRITE) == U_FAIL) {
01424 goto err;
01425 }
01426 }
01427
01428 dev = obj->dev;
01429 node = obj->node;
01430
01431 uffs_ObjectDevLock(obj);
01432
01433 uffs_BufFlush(dev);
01434 buf = uffs_BufGetEx(dev, obj->type, node, 0);
01435 if(buf == NULL) {
01436 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get buf when rename!\n");
01437 uffs_ObjectDevUnLock(obj);
01438 uffs_CloseObject(obj);
01439 goto err;
01440 }
01441
01442 memcpy(&fi, buf->data, sizeof(uffs_fileInfo));
01443 strcpy((char *)(fi.name), _getfilename(new_name));
01444 fi.name_len = strlen(fi.name);
01445 fi.lastModify = uffs_GetCurDateTime();
01446
01447 obj->sum = uffs_MakeSum16(fi.name, fi.name_len);
01448
01449
01450 if (obj->type == UFFS_TYPE_DIR) {
01451 obj->node->u.dir.checkSum = obj->sum;
01452 obj->node->u.dir.father = father_new;
01453 }
01454 else {
01455 obj->node->u.file.checkSum = obj->sum;
01456 obj->node->u.file.father = father_new;
01457 }
01458
01459 uffs_BufWrite(dev, buf, &fi, 0, sizeof(uffs_fileInfo));
01460 uffs_BufPut(dev, buf);
01461 uffs_BufFlush(dev);
01462
01463 uffs_ObjectDevUnLock(obj);
01464 uffs_CloseObject(obj);
01465
01466 ret = U_SUCC;
01467
01468 err:
01469 _ReleaseObjectResource(obj);
01470 uffs_PutObject(obj);
01471
01472 return ret;
01473 }
01474
01475
01476 static URET _LoadObjectInfo(uffs_Device *dev, TreeNode *node, uffs_ObjectInfo *info, int type)
01477 {
01478 uffs_Buf *buf;
01479
01480 buf = uffs_BufGetEx(dev, (u8)type, node, 0);
01481
01482 if(buf == NULL) {
01483 return U_FAIL;
01484 }
01485
01486 memcpy(&(info->info), buf->data, sizeof(uffs_fileInfo));
01487
01488 if (type == UFFS_TYPE_DIR) {
01489 info->len = 0;
01490 info->serial = node->u.dir.serial;
01491 }
01492 else {
01493 info->len = node->u.file.len;
01494 info->serial = node->u.file.serial;
01495 }
01496
01497 uffs_BufPut(dev, buf);
01498
01499 return U_SUCC;
01500 }
01501
01502 URET uffs_GetObjectInfo(uffs_Object *obj, uffs_ObjectInfo *info)
01503 {
01504 uffs_Device *dev = obj->dev;
01505 URET ret = U_FAIL;
01506
01507 uffs_ObjectDevLock(obj);
01508
01509 if (obj && obj->dev && info)
01510 ret = _LoadObjectInfo(dev, obj->node, info, obj->type);
01511
01512 uffs_ObjectDevUnLock(obj);
01513
01514 return ret;
01515 }
01516
01517
01518 URET uffs_OpenFindObject(uffs_FindInfo *f, const char * dir)
01519 {
01520 if (f == NULL) return U_FAIL;
01521
01522 f->obj = uffs_GetObject();
01523 if (f->obj == NULL) {
01524 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Can't get a new object\n");
01525 goto err;
01526 }
01527
01528 if (_PrepareOpenObj(f->obj, dir, UO_RDONLY|UO_DIR, US_IREAD|US_IWRITE) == U_FAIL) {
01529 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't prepare open dir %s for read.\n", dir);
01530 goto err;
01531 }
01532
01533 f->dev = f->obj->dev;
01534
01535 if (f->obj->nameLen == 0) {
01536
01537 f->father = ROOT_DIR_ID;
01538 }
01539 else {
01540 if (_OpenObjectUnder(f->obj) == U_FAIL) {
01541 uffs_Perror(UFFS_ERR_NOISY, PFX"Can't open dir %s for read, doesn't exist ?\n", dir);
01542 goto err;
01543 }
01544 f->father = f->obj->serial;
01545 }
01546
01547
01548 f->hash = 0;
01549 f->work = NULL;
01550 f->step = 0;
01551
01552 return U_SUCC;
01553
01554 err:
01555 if (f->obj) {
01556 _ReleaseObjectResource(f->obj);
01557 uffs_PutObject(f->obj);
01558 f->obj = NULL;
01559 }
01560
01561 return U_FAIL;
01562 }
01563
01564 URET uffs_FindFirstObject(uffs_ObjectInfo * info, uffs_FindInfo * f)
01565 {
01566 uffs_Device *dev = f->dev;
01567 TreeNode *node;
01568 u16 x;
01569 URET ret = U_SUCC;
01570
01571 uffs_DeviceLock(dev);
01572 f->step = 0;
01573
01574 if (f->step == 0) {
01575 for(f->hash = 0;
01576 f->hash < DIR_NODE_ENTRY_LEN;
01577 f->hash++) {
01578
01579 x = dev->tree.dirEntry[f->hash];
01580
01581 while(x != EMPTY_NODE) {
01582 node = FROM_IDX(x, &(dev->tree.dis));
01583 if(node->u.dir.father == f->father) {
01584 f->work = node;
01585 if (info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR);
01586 uffs_DeviceUnLock(dev);
01587 return ret;
01588 }
01589 x = node->hashNext;
01590 }
01591 }
01592
01593
01594 f->step++;
01595 }
01596
01597 if(f->step == 1) {
01598 for(f->hash = 0;
01599 f->hash < FILE_NODE_ENTRY_LEN;
01600 f->hash++) {
01601
01602 x = dev->tree.fileEntry[f->hash];
01603
01604 while(x != EMPTY_NODE) {
01605 node = FROM_IDX(x, &(dev->tree.dis));
01606 if(node->u.file.father == f->father) {
01607 f->work = node;
01608 if(info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE);
01609 uffs_DeviceUnLock(dev);
01610 return ret;
01611 }
01612 x = node->hashNext;
01613 }
01614 }
01615 f->step++;
01616 }
01617
01618 uffs_DeviceUnLock(dev);
01619 return U_FAIL;
01620 }
01621
01622 URET uffs_FindNextObject(uffs_ObjectInfo *info, uffs_FindInfo * f)
01623 {
01624 uffs_Device *dev = f->dev;
01625 TreeNode *node;
01626 u16 x;
01627 URET ret = U_SUCC;
01628
01629 if(f->dev == NULL ||
01630 f->work == NULL ||
01631 f->step > 1) return U_FAIL;
01632
01633 uffs_DeviceLock(dev);
01634
01635 x = f->work->hashNext;
01636
01637 if (f->step == 0) {
01638 while(x != EMPTY_NODE) {
01639 node = FROM_IDX(x, &(dev->tree.dis));
01640 if(node->u.dir.father == f->father) {
01641 f->work = node;
01642 if(info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR);
01643 uffs_DeviceUnLock(dev);
01644 return ret;
01645 }
01646 x = node->hashNext;
01647 }
01648
01649 f->hash++;
01650
01651 for(; f->hash < DIR_NODE_ENTRY_LEN; f->hash++) {
01652 x = dev->tree.dirEntry[f->hash];
01653 while(x != EMPTY_NODE) {
01654 node = FROM_IDX(x, &(dev->tree.dis));
01655 if(node->u.dir.father == f->father) {
01656 f->work = node;
01657 if(info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR);
01658 uffs_DeviceUnLock(dev);
01659 return ret;
01660 }
01661 x = node->hashNext;
01662 }
01663 }
01664
01665
01666 f->step++;
01667 f->hash = 0;
01668 x = EMPTY_NODE;
01669 }
01670
01671 if (f->step == 1) {
01672
01673 while(x != EMPTY_NODE) {
01674 node = FROM_IDX(x, &(dev->tree.dis));
01675 if(node->u.file.father == f->father) {
01676 f->work = node;
01677 if(info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE);
01678 uffs_DeviceUnLock(dev);
01679 return ret;
01680 }
01681 x = node->hashNext;
01682 }
01683
01684 f->hash++;
01685
01686 for(; f->hash < FILE_NODE_ENTRY_LEN; f->hash++) {
01687 x = dev->tree.fileEntry[f->hash];
01688 while(x != EMPTY_NODE) {
01689 node = FROM_IDX(x, &(dev->tree.dis));
01690 if(node->u.file.father == f->father) {
01691 f->work = node;
01692 if(info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE);
01693 uffs_DeviceUnLock(dev);
01694 return ret;
01695 }
01696 x = node->hashNext;
01697 }
01698 }
01699
01700
01701 f->step++;
01702 }
01703
01704 uffs_DeviceUnLock(dev);
01705 return U_FAIL;
01706 }
01707
01708 URET uffs_CloseFindObject(uffs_FindInfo * f)
01709 {
01710 if (f == NULL) return U_FAIL;
01711
01712 if (f->obj) {
01713
01714 _ReleaseObjectResource(f->obj);
01715 uffs_PutObject(f->obj);
01716 f->obj = NULL;
01717 }
01718
01719 f->dev = NULL;
01720 f->hash = 0;
01721 f->work = NULL;
01722
01723 return U_SUCC;
01724 }
01725
01726