00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <time.h>
00006 #include "sfs_index.h"
00007 #include <sys/uio.h>
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <fcntl.h>
00011 #include <errno.h>
00012
00013 #include <rtsLog.h>
00014
00015 #include <byteswap.h>
00016 #define swap16(x) bswap_16(x)
00017 #define swap32(x) bswap_32(x)
00018
00019
00020
00021
00022
00023
00024
00025 #define MAX_SEND_IOVECS 100
00026
00027 int mstrcmp(char *s1, char *s2)
00028 {
00029 if((s1[0] == '#') && (s2[0] == '#')) {
00030 int x1;
00031 int x2;
00032
00033 x1 = atoi(&s1[1]);
00034 x2 = atoi(&s2[1]);
00035 if(x1 > x2) return 1;
00036 if(x1 < x2) return -1;
00037 return 0;
00038 }
00039 return strcmp(s1,s2);
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049 void striptofirst(char *str)
00050 {
00051 while(*str != '\0') {
00052 if(*str == '/') *(str+1) = '\0';
00053 str++;
00054 }
00055 }
00056
00057
00058
00059
00060 void striptofirstdir(char *str)
00061 {
00062 int scount = 0;
00063 while(*str != '\0') {
00064 if(*str == '/') scount++;
00065 if(scount >= 2) {
00066 *str = '\0';
00067 }
00068 else str++;
00069 }
00070 }
00071
00072
00073
00074
00075
00076
00077
00078 char *striptofile(char *str)
00079 {
00080 char *ostr = str;
00081
00082 while(*str != '\0') {
00083 if(*str == '/') ostr = str+1;
00084 str++;
00085 }
00086
00087 return ostr;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 void stripfile(char *str)
00097 {
00098 char *ostr = str;
00099 char *lslash = NULL;
00100
00101 while(*str != '\0') {
00102 if(*str == '/') lslash = str;
00103 str++;
00104 }
00105
00106 if(lslash) *(lslash+1) = '\0';
00107 else strcpy(ostr, "/");
00108 }
00109
00110 int SFS_ittr::get(wrapfile *wrap)
00111 {
00112
00113 skipped_bytes = 0;
00114
00115 char buff[12];
00116 memset(buff, 0, sizeof(buff));
00117
00118 wfile = wrap;
00119
00120 stickypath[0] = '\0';
00121 ppath[0] = '\0';
00122 fullpath[0]='\0';
00123
00124
00125 filepos = 0;
00126 strcpy(ppath,"/");
00127
00128 return 0;
00129 }
00130
00131
00132 void SFS_ittr::swapEntry()
00133 {
00134
00135 if(entry.byte_order == 0x04030201) return;
00136
00137 entry.byte_order = swap32(entry.byte_order);
00138
00139 entry.byte_order = swap32(entry.byte_order);
00140 entry.sz = swap32(entry.sz);
00141 entry.reserved = swap16(entry.reserved);
00142 }
00143
00144
00145
00146
00147 int SFS_ittr::next()
00148 {
00149
00150 skipped_bytes = 0;
00151
00152 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00153 LOG(DBG, "Calling next: fileoffset=%lld filepos=%d",fileoffset,filepos);
00154 long long int ret;
00155 #else
00156 LOG(DBG, "Calling next: fileoffset=%d filepos=%d",fileoffset,filepos);
00157 int ret;
00158 #endif
00159
00160
00161
00162 LOG(DBG, "filepos = %d, entry.sz=%d entry.head_sz=%d",filepos,entry.sz,entry.head_sz);
00163 if(filepos == 1) {
00164 ret = wfile->lseek(seeksize(entry.sz), SEEK_CUR);
00165 if(ret < 0) {
00166 LOG(ERR,"Error seeking: %s\n",strerror(errno));
00167 return -1;
00168 }
00169 filepos = 2;
00170
00171 LOG(DBG, "fileoffset=%d --> + %d + %d",
00172 entry.sz, entry.head_sz);
00173 fileoffset += seeksize(entry.sz) + entry.head_sz;
00174 }
00175
00176 if(filepos == 2) {
00177
00178 LOG(DBG,"---DIR: name=%s entry.attr = 0x%x headsz=%d",entry.name, entry.attr,entry.head_sz);
00179
00180
00181 if(entry.attr & SFS_ATTR_NOCD) {
00182
00183
00184 }
00185 else {
00186 if(entry.name[0] == '/') {
00187
00188 strcpy(ppath, entry.name);
00189 }
00190 else {
00191
00192 strcat(ppath, entry.name);
00193 }
00194 stripfile(ppath);
00195 }
00196
00197 if(entry.attr & SFS_ATTR_STICKY_CD) {
00198 strcpy(stickypath,ppath);
00199
00200 }
00201
00202
00203
00204
00205 filepos = 0;
00206 }
00207
00208
00209
00210 for(;;) {
00211 char buff[10];
00212 int ret = wfile->read(buff, 8);
00213
00214 if(ret == 0) {
00215 filepos = -1;
00216 return 0;
00217 }
00218
00219 if(ret != 8) {
00220 LOG(ERR, "Error reading next file record...");
00221 return -1;
00222 }
00223
00224 buff[5] = 0;
00225
00226 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00227 wfile->lseek(-((long long int)8), SEEK_CUR);
00228 long long int xxx = wfile->lseek(0,SEEK_CUR);
00229 LOG(DBG, "fileoffset=%lld xxx=%lld buff=%s",fileoffset,xxx,buff);
00230 #else
00231 wfile->lseek(-8, SEEK_CUR);
00232 int xxx = wfile->lseek(0,SEEK_CUR);
00233 LOG(DBG, "fileoffset=%d xxx=%d buff=%s",fileoffset,xxx,buff);
00234 #endif
00235
00236 if(memcmp(buff, "SFS V", 5) == 0) {
00237
00238 wfile->lseek(12, SEEK_CUR);
00239 fileoffset += 12;
00240 skipped_bytes += 12;
00241 continue;
00242 }
00243
00244 if(memcmp(buff, "LRHD", 4) == 0) {
00245
00246
00247 if(nextLRHD() >= 0) {
00248 LOG(DBG, "lrhd entry.sz = %d",entry.sz);
00249 return 0;
00250 }
00251
00252
00253
00254 wfile->lseek(60, SEEK_CUR);
00255
00256
00257
00258 fileoffset += 60;
00259 skipped_bytes += 60;
00260 LOG(DBG, "Not a DATA LRHD fileoffset=%d skipped_bytes=%d seek=%d",
00261 fileoffset,skipped_bytes,wfile->lseek(0,SEEK_CUR));
00262
00263 continue;
00264 }
00265
00266 if(memcmp(buff, "DATAP", 5) == 0) {
00267
00268
00269 LOG(DBG, "Before datap: file=%d filepos=%d offset=%d entrysz=%d",
00270 wfile->lseek(0,SEEK_CUR), filepos,fileoffset,entry.sz);
00271
00272 if(nextDatap() >= 0) {
00273 LOG(DBG, "After datap: file=%d filepos=%d offset=%d entrysz=%d",
00274 wfile->lseek(0,SEEK_CUR), filepos,fileoffset,entry.sz);
00275 return 0;
00276 }
00277
00278 wfile->lseek(204, SEEK_CUR);
00279 fileoffset += 204;
00280 skipped_bytes += 204;
00281 continue;
00282 }
00283
00284 if(memcmp(buff, "HEAD", 4) == 0) {
00285
00286 wfile->lseek(12, SEEK_CUR);
00287 fileoffset += 12;
00288 skipped_bytes += 12;
00289 continue;
00290 }
00291
00292 if(memcmp(buff, "FILE", 4) == 0) {
00293 break;
00294 }
00295
00296 else {
00297
00298 if(wfile->type == WRAP_MEM) {
00299 filepos = -1;
00300 return 0;
00301 }
00302
00303 char ttmp[16] ;
00304 memcpy(ttmp,buff,16) ;
00305 ttmp[15] = 0 ;
00306 LOG(ERR,"Error: %s is not a valid specifier\n",ttmp);
00307 return -1;
00308 }
00309 }
00310
00311
00312 memset(entryBuff, 0, sizeof(entryBuff));
00313
00314 ret = wfile->read(entryBuff,16);
00315 if(ret == 0) {
00316 filepos = -1;
00317 return 0;
00318 }
00319
00320 if(ret != 16) {
00321 LOG(ERR,"Error reading file entry: %s (%d)\n",strerror(errno),ret);
00322 return -1;
00323 }
00324
00325
00326
00327 if(memcmp(entry.type,"FILE",4) != 0) {
00328 LOG(ERR,"Error reading file entry: {%c%c%c%c} Not a file record...\n",
00329 entry.type[0],entry.type[1],entry.type[2],entry.type[3]);
00330 return -1;
00331 }
00332
00333 swapEntry();
00334
00335
00336
00337
00338 ret = wfile->read(entryBuff + 16, entry.head_sz - 16);
00339 if(ret != entry.head_sz - 16) {
00340 LOG(ERR,"Error reading file entry: size mismatch ret=%d sz=%d\n",ret,entry.head_sz);
00341
00342 return -1;
00343 }
00344
00345
00346 LOG(DBG,"---DIR: name=%s entry.attr = 0x%x\n",entry.name, entry.attr);
00347
00348
00349
00350 if(strstr(entry.name, "legacy")) {
00351 entry.attr |= SFS_ATTR_POPSTICKY;
00352 }
00353
00354 if(strstr(entry.name, "pad")) {
00355 entry.attr |= SFS_ATTR_POPSTICKY;
00356 }
00357
00358 if(entry.attr & SFS_ATTR_POPSTICKY) {
00359
00360
00361 if(stickypath[0] != '\0')
00362 strcpy(ppath, stickypath);
00363 }
00364
00365 if(entry.name[0] == '/') {
00366 strcpy(fullpath, entry.name);
00367 }
00368 else {
00369 strcpy(fullpath, ppath);
00370 strcat(fullpath, entry.name);
00371 }
00372
00373 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00374 LOG(DBG,"fullpath %s, entry.name: %s, fileoffset %lld/%d, sz %d head_sz %d",
00375 fullpath, entry.name, fileoffset, filepos, entry.sz, entry.head_sz);
00376 #else
00377 LOG(DBG,"fullpath %s, entry.name: %s, fileoffset %d/%d, sz %d head_sz %d",
00378 fullpath, entry.name, fileoffset, filepos, entry.sz, entry.head_sz);
00379 #endif
00380
00381 filepos = 1;
00382 return 0;
00383 }
00384
00385 char *SFS_getpayload(char *buff)
00386 {
00387 SFS_File *f = (SFS_File *)buff;
00388 return (buff + f->head_sz);
00389 }
00390
00391 int sfs_index::getInodeSize(fs_inode *inode, SfsDirsize *sizes)
00392 {
00393
00394
00395
00396 sizes->dataSize += inode->sz;
00397 sizes->size += inode->sz + inode->overhead;
00398
00399 if(inode->fchild) getInodeSize(inode->fchild, sizes);
00400 if(inode->next) getInodeSize(inode->next, sizes);
00401 return 0;
00402 }
00403
00404 int sfs_index::getDirSize(char *dir, SfsDirsize *sizes)
00405 {
00406 memset(sizes, 0, sizeof(SfsDirsize));
00407 fs_dir *d = opendir(dir);
00408 if(!d) return -1;
00409
00410 sizes->dataSize += d->inode->sz;
00411 sizes->size += d->inode->sz + d->inode->overhead;
00412
00413 if(d->inode->fchild) return getInodeSize(d->inode->fchild,sizes);
00414 return 0;
00415 }
00416
00417 int sfs_index::writeFsHeader()
00418 {
00419 static char *volumeSpec = "SFS V00.01\0\0\0";
00420 int ret;
00421 int sz;
00422 char *bb;
00423 SFS_Header head;
00424
00425 bb = volumeSpec;
00426 sz = 12;
00427 while(sz) {
00428 ret = wfile.write(volumeSpec, sz);
00429
00430 if(ret < 0) {
00431 return -1;
00432 }
00433 sz -= ret;
00434 bb += ret;
00435 }
00436
00437 memcpy(head.type, "HEAD", 4);
00438 head.byte_order = 0x04030201;
00439 head.time = time(NULL);
00440
00441 bb = (char *)&head;
00442 sz = sizeof(head);
00443 while(sz) {
00444 ret = wfile.write(bb, sz);
00445
00446 if(ret < 0) {
00447 return -1;
00448 }
00449
00450 sz -= ret;
00451 bb += ret;
00452 }
00453
00454 return 0;
00455 }
00456
00457 int sfs_index::write(char *fn, char *buff, int size)
00458 {
00459 int ret;
00460 char *bb;
00461 int sz;
00462 char path[256];
00463 int attr = SFS_ATTR_NOCD;
00464
00465 char b[256];
00466 SFS_File *file = (SFS_File *)b;
00467
00468 if(cdchanged) {
00469
00470
00471
00472
00473
00474
00475 if(fn[0] == '/') {
00476 strcpy(path, fn);
00477 }
00478 else {
00479
00480 cdchanged = 0;
00481
00482 int subdirs = 0;
00483 int len = strlen(fn);
00484 for(int i=0;i<len-1;i++) {
00485 if(fn[i] == '/') {
00486 subdirs = 1;
00487 break;
00488 }
00489 }
00490
00491 if(!subdirs) {
00492 getFullPath(path, fn);
00493 attr = 0;
00494 }
00495
00496 if(subdirs) {
00497 memcpy(file->type, "FILE", 4);
00498 file->byte_order = 0x04030201;
00499 file->sz = 0;
00500 file->head_sz = seeksize(strlen(cwd)+1) + sizeof(SFS_File) - 4;
00501 file->attr = 0;
00502 strcpy(file->name, cwd);
00503
00504 bb = (char *)file;
00505 sz = file->head_sz;
00506
00507 while(sz) {
00508 ret = wfile.write(bb, sz);
00509 if(ret < 0) {
00510 return -1;
00511 }
00512
00513 sz -= ret;
00514 bb += ret;
00515 }
00516
00517 strcpy(path, fn);
00518 }
00519 }
00520 }
00521 else {
00522 strcpy(path, fn);
00523 }
00524
00525
00526
00527
00528
00529 memcpy(file->type, "FILE", 4);
00530 file->byte_order = 0x04030201;
00531 file->sz = size;
00532 file->head_sz = seeksize(strlen(path)+1) + sizeof(SFS_File) - 4;
00533 file->attr = attr;
00534
00535 strcpy(file->name, path);
00536
00537 bb = (char *)file;
00538 sz = file->head_sz;
00539
00540 while(sz) {
00541 ret = wfile.write(bb, sz);
00542 if(ret < 0) {
00543 return -1;
00544 }
00545
00546 sz -= ret;
00547 bb += ret;
00548 }
00549
00550 sz = size;
00551 bb = buff;
00552
00553 while(sz) {
00554 ret = wfile.write(bb, sz);
00555 if(ret < 0) {
00556 return -1;
00557 }
00558
00559 sz -= ret;
00560 bb += ret;
00561 }
00562
00563
00564 char *zero = "\0\0\0\0";
00565 sz = seeksize(size) - size;
00566 bb = zero;
00567
00568 while(sz) {
00569 ret = wfile.write(bb, sz);
00570 if(ret < 0) {
00571 return -1;
00572 }
00573
00574 sz -= ret;
00575 bb += ret;
00576 }
00577
00578 return size;
00579 }
00580
00581 int sfs_index::getwritevsz(fs_iovec *fsiovec, int n)
00582 {
00583 int sz = 0;
00584 for(int i=0;i<n;i++) {
00585 if(fsiovec[i].filename) {
00586 sz += seeksize(strlen(fsiovec[i].filename)+1);
00587 sz += sizeof(SFS_File) - 4;
00588 }
00589
00590 sz += seeksize(fsiovec[i].len);
00591 }
00592 return sz;
00593 }
00594
00595 int sfs_index::writev(fs_iovec *fsiovec, int n)
00596 {
00597 return writev_sticky(fsiovec, n, NULL);
00598 }
00599
00600
00601
00602 int sfs_index::writev_call_retry(int fd, iovec *iovec, int vec)
00603 {
00604
00605 struct iovec iovec_new[MAX_SEND_IOVECS];
00606 int vec_new=0;
00607
00608 if(vec > MAX_SEND_IOVECS) {
00609 LOG(CRIT, "writev with too %d iovecs... max=%d",vec,MAX_SEND_IOVECS);
00610 }
00611
00612 int len=0;
00613 for(int i=0;i<vec;i++) {
00614 len += iovec[i].iov_len;
00615 }
00616
00617 int ret = ::writev(fd, iovec, vec);
00618
00619 if(ret != len) {
00620 for(int i=0;i<vec;i++) {
00621 LOG(DBG, "socket error iovec[%d].base=%d, len=%d",
00622 i,iovec[i].iov_base,iovec[i].iov_len);
00623 }
00624
00625 LOG(NOTE, "writev failed: ret=%d of %d, err=%s. will retry",ret, len, strerror(errno));
00626 }
00627
00628
00629 if(ret < 0) {
00630 if((errno != EINTR) &&
00631 (errno != EAGAIN)) {
00632
00633 LOG(ERR, "Error on writev (%s)",strerror(errno));
00634 return -1;
00635 }
00636
00637 ret = 0;
00638 }
00639
00640 if(ret != len) {
00641 int nstart = ret;
00642 LOG(NOTE, "writev only wrote %d of %d... Retry", ret, len);
00643
00644
00645 for(int i=0;i<vec;i++) {
00646 if(nstart < (int)iovec[i].iov_len) {
00647 char *base = (char *)iovec[i].iov_base;
00648 base += nstart;
00649
00650 iovec_new[vec_new].iov_base = (void *)base;
00651 iovec_new[vec_new].iov_len = iovec[i].iov_len - nstart;
00652 vec_new++;
00653 }
00654
00655 nstart -= iovec[i].iov_len;
00656 if(nstart<0) nstart = 0;
00657 }
00658
00659
00660
00661 int ret2 = writev_call_retry(fd, iovec_new, vec_new);
00662
00663
00664
00665 if(ret2 < 0) return -1;
00666
00667 ret += ret2;
00668 LOG(NOTE, "writev retry returned %d (retry was %d)",ret,ret2);
00669 }
00670 return ret;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680 int sfs_index::writev_sticky(fs_iovec *fsiovec, int n, int *sticky)
00681 {
00682 iovec iovec[MAX_SEND_IOVECS];
00683 char _buff[(sizeof(SFS_File) + 40)*50];
00684 char *b = _buff;
00685
00686 int i;
00687 int vec=0;
00688
00689 if(n > MAX_SEND_IOVECS) {
00690 LOG(CRIT, "sending %d iovecs > than max=%d",n,MAX_SEND_IOVECS);
00691 }
00692
00693
00694
00695
00696
00697
00698
00699 for(i=0;i<n;i++) {
00700
00701 LOG(DBG, "i=%d\n",i);
00702
00703 if(fsiovec[i].filename) {
00704 SFS_File *file = (SFS_File *)b;
00705
00706 memcpy(file->type, "FILE", 4);
00707 file->byte_order = 0x04030201;
00708 file->sz = fsiovec[i].len;
00709 file->head_sz = seeksize(strlen(fsiovec[i].filename)+1) + sizeof(SFS_File) - 4;
00710 file->attr = SFS_ATTR_NOCD;
00711 if(sticky) {
00712 if(sticky[i]) {
00713 file->attr |= SFS_ATTR_POPSTICKY;
00714 }
00715 if(sticky[i] < 0) {
00716 LOG(DBG, "%d %d",sticky[i], file->sz);
00717 file->sz = -(sticky[i]);
00718 LOG(DBG, "Set file->sz=%d",file->sz);
00719 }
00720 }
00721 strcpy(file->name, fsiovec[i].filename);
00722
00723
00724 iovec[vec].iov_base = b;
00725 iovec[vec].iov_len = file->head_sz;
00726 LOG(DBG, "fn: iovec[%d] name=%s: base=0x%x(0x%x) len=%d",
00727 vec,fsiovec[i].filename,
00728 iovec[vec].iov_base,
00729
00730 iovec[vec].iov_len);
00731
00732
00733 vec++;
00734
00735 b += file->head_sz;
00736 }
00737
00738 iovec[vec].iov_base = fsiovec[i].buff;
00739 iovec[vec].iov_len = seeksize(fsiovec[i].len);
00740
00741 LOG(DBG, "iovec[%d] name=%s: base=0x%x len=%d",
00742 vec,fsiovec[vec].filename,
00743 iovec[vec].iov_base,
00744 iovec[vec].iov_len);
00745
00746 vec++;
00747
00748
00749 }
00750
00751
00752 int all_size = 0 ;
00753 for(int i=0;i<vec;i++) {
00754 all_size += iovec[i].iov_len ;
00755 }
00756
00757
00758 int ret = writev_call_retry(wfile.fd, iovec, vec);
00759
00760 return ret;
00761 }
00762
00763 sfs_index::sfs_index() : fs_index()
00764 {
00765 singleDirMount = 0;
00766 singleDirIttr = NULL;
00767 root = NULL;
00768 cw_inode = NULL;
00769
00770 return;
00771 }
00772
00773 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00774 int sfs_index::mountSingleDirMem(char *buffer, int size, long long int offset)
00775 #else
00776 int sfs_index::mountSingleDirMem(char *buffer, int size, int offset)
00777 #endif
00778 {
00779 wfile.close();
00780 oflags = O_RDONLY;
00781 wfile.openmem(buffer, size);
00782
00783 singleDirOffset = offset;
00784 singleDirSize = size;
00785 return mountSingleDir();
00786 }
00787
00788
00789
00790
00791 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00792 int sfs_index::mountSingleDir(char *fn, long long int offset)
00793 #else
00794 int sfs_index::mountSingleDir(char *fn, int offset)
00795 #endif
00796 {
00797 LOG(DBG,"the spec is: " __DATE__ ":" __TIME__);
00798
00799
00800 wfile.close();
00801 wfile.opendisk(fn, O_RDONLY);
00802 if(wfile.fd < 0) {
00803 LOG(ERR, "Bad error opening %s mounting single directory (%s)",fn,strerror(errno));
00804 return wfile.fd;
00805 }
00806 wfile.lseek(offset, SEEK_SET);
00807
00808 int ret = mountSingleDir();
00809
00810 return ret;
00811 }
00812
00813 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00814 int sfs_index::getSingleDirSize(char *fn, long long int offset)
00815 #else
00816 int sfs_index::getSingleDirSize(char *fn, int offset)
00817 #endif
00818 {
00819 char topdir[40];
00820 int topdirlen=0;
00821 topdir[0] = '\0';
00822
00823 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00824 LOG(DBG, "singledirsize file=%s, offset=%lld",fn,offset);
00825 #else
00826 LOG(DBG, "singledirsize file=%s, offset=%d",fn,offset);
00827 #endif
00828
00829 wfile.close();
00830 wfile.opendisk(fn, O_RDONLY);
00831 if(wfile.fd < 0) return wfile.fd;
00832 wfile.lseek(offset, SEEK_SET);
00833
00834 int sz = 0;
00835
00836 SFS_ittr *ittr = new SFS_ittr(offset);
00837 if(ittr->get(&wfile) < 0) {
00838 delete ittr;
00839 wfile.lseek(offset,SEEK_SET);
00840 return sz;
00841 }
00842
00843 sz += ittr->skipped_bytes;
00844
00845 LOG(DBG, "partial sz=%d, skipped=%d",sz,ittr->skipped_bytes);
00846
00847 while(ittr->next() >= 0) {
00848
00849 if(ittr->filepos == -1) break;
00850
00851
00852 if(topdir[0] == '\0') {
00853 strncpy(topdir,ittr->fullpath,40);
00854 for(int i=0;i<40;i++) {
00855 if(topdir[i] == '\0') break;
00856 if((i>0) && (topdir[i] == '/')) {
00857 topdir[i] = '\0';
00858 topdirlen = strlen(topdir);
00859 break;
00860 }
00861 }
00862 }
00863
00864 LOG(DBG, "Topdir=%s sz(before)=%d",topdir,sz);
00865
00866 if(memcmp(topdir, ittr->fullpath, topdirlen) != 0) {
00867 break;
00868 }
00869
00870 sz += ittr->skipped_bytes;
00871 sz += ittr->entry.head_sz;
00872 int esz = (ittr->entry.sz + 3) / 4;
00873 esz *= 4;
00874 sz += esz;
00875 }
00876
00877 delete ittr;
00878 wfile.close();
00879
00880 LOG(DBG, "returning %d",sz);
00881 return sz;
00882 }
00883
00884 int sfs_index::mountSingleDir()
00885 {
00886 if(singleDirIttr) delete singleDirIttr;
00887
00888 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00889 long long int offset = wfile.lseek(0,SEEK_CUR);
00890 LOG(DBG, "mountSingleDir() offset=%lld 0x%x", offset, wfile.wbuff);
00891 if(!wfile.wbuff) {
00892 singleDirOffset = offset;
00893 nextSingleDirOffset = offset;
00894 }
00895 #else
00896 int offset = wfile.lseek(0,SEEK_CUR);
00897 if(!wfile.wbuff) {
00898 singleDirOffset = offset;
00899 nextSingleDirOffset = offset;
00900 }
00901 #endif
00902
00903 singleDirMount = 1;
00904 singleDirIttr = new SFS_ittr(offset);
00905
00906 if(singleDirIttr->get(&wfile) < 0) {
00907 delete singleDirIttr;
00908 singleDirIttr = NULL;
00909 singleDirMount = 0;
00910
00911 root = alloc_inode("",0,0,0);
00912 strcpy(cwd, "/");
00913 index_created = 1;
00914 return -1;
00915 }
00916
00917 if(singleDirIttr->next() < 0) {
00918
00919 root = alloc_inode("",0,0,0);
00920 strcpy(cwd, "/");
00921 index_created = 1;
00922
00923 LOG(NOTE, "Couldn't get any SFS dirs...");
00924 return -1;
00925 }
00926
00927 return _mountNextDir();
00928 }
00929
00930
00931
00932
00933
00934
00935 int sfs_index::mountNextDir()
00936 {
00937 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00938
00939
00940 singleDirOffset = nextSingleDirOffset;
00941 long long int offset = wfile.lseek(singleDirOffset,SEEK_SET);
00942
00943 #else
00944 int offset = wfile.lseek(0,SEEK_CUR);
00945
00946 #endif
00947
00948 return(_mountNextDir());
00949 }
00950
00951
00952 int sfs_index::_mountNextDir()
00953 {
00954 int files_added=0;
00955
00956 if(index_created) free_inode(root);
00957 index_created = 0;
00958
00959 root = alloc_inode("",0,0,0);
00960 strcpy(cwd, "/");
00961 cw_inode = root;
00962 index_created = 1;
00963
00964
00965 if(singleDirIttr->filepos == -1) {
00966 return 0;
00967 }
00968
00969
00970 while(strcmp(singleDirIttr->fullpath,"/") == 0) {
00971 if(singleDirIttr->next() < 0) {
00972 LOG(DBG, "End of file/error before first directory");
00973 return -1;
00974 }
00975 if(singleDirIttr->filepos == -1) {
00976 return 0;
00977 }
00978 }
00979
00980
00981 char basedir[256];
00982 char currdir[256];
00983 strcpy(basedir, singleDirIttr->fullpath);
00984 striptofirstdir(basedir);
00985
00986 for(;;) {
00987
00988 files_added++;
00989 addnode(singleDirIttr);
00990
00991 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00992 long long int last_offset = singleDirIttr->fileoffset;
00993
00994 #else
00995 int last_offset = singleDirIttr->fileoffset;
00996 int last_filepos = singleDirIttr->filepos;
00997 #endif
00998
00999 int last_head_sz = singleDirIttr->entry.head_sz;
01000 int last_file_sz = seeksize(singleDirIttr->entry.sz);
01001
01002 if(singleDirIttr->next() < 0) {
01003 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
01004 return -1;
01005 }
01006
01007 if(singleDirIttr->filepos == -1) {
01008
01009 if(!wfile.wbuff) {
01010 singleDirSize = last_offset + last_head_sz + last_file_sz - singleDirOffset;
01011 }
01012 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
01013 return (files_added > 0) ? 1 : 0;
01014 }
01015
01016
01017 strcpy(currdir, singleDirIttr->fullpath);
01018 striptofirstdir(currdir);
01019
01020
01021
01022
01023
01024
01025 if(strcmp(basedir, currdir) != 0) {
01026 if(!wfile.wbuff) {
01027 singleDirSize = last_offset + last_head_sz + last_file_sz - singleDirOffset;
01028 }
01029 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
01030 return (files_added > 0) ? 1 : 0;
01031 }
01032 }
01033
01034 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
01035 return 0;
01036 }
01037
01038 int sfs_index::_create()
01039 {
01040 root = alloc_inode("",0,0,0);
01041 strcpy(cwd,"/");
01042 cw_inode = root;
01043
01044 SFS_ittr ittr;
01045
01046
01047
01048
01049 if(ittr.get(&wfile) < 0) {
01050 return -1;
01051 }
01052
01053 for(;;) {
01054
01055
01056
01057
01058 if(ittr.next() < 0) {
01059
01060
01061 return -1;
01062 }
01063
01064
01065
01066
01067 if(ittr.filepos == -1) {
01068
01069 return 0;
01070 }
01071
01072
01073
01074 addnode(&ittr);
01075
01076
01077 }
01078
01079 LOG(ERR,"never happens\n");
01080 return -1;
01081 }
01082
01083 void sfs_index::addnode(SFS_ittr *ittr)
01084 {
01085 char fullpath[256];
01086 char thispathonly[256];
01087 char *next[20];
01088
01089 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
01090 LOG(DBG, "addnode: %s %lld %d",ittr->fullpath, ittr->fileoffset, ittr->filepos);
01091 #else
01092 LOG(DBG, "addnode: %s %d %d",ittr->fullpath, ittr->fileoffset, ittr->filepos);
01093 #endif
01094
01095 if(ittr->entry.attr == SFS_ATTR_INVALID) return;
01096
01097 strcpy(thispathonly, ittr->fullpath);
01098 stripfile(thispathonly);
01099
01100 strcpy(fullpath, ittr->fullpath);
01101
01102 next[0] = strtok(&fullpath[1], "/");
01103
01104 int nn=1;
01105 while((next[nn] = strtok(NULL, "/"))) nn++;
01106
01107 fs_inode *inode = root;
01108
01109 for(int i=0;i<nn-1;i++) {
01110 inode = add_inode(inode, next[i], 0, 0, 0);
01111 }
01112
01113 inode = add_inode(inode, next[nn-1], ittr->fileoffset + ittr->entry.head_sz, ittr->entry.sz, ittr->entry.head_sz);
01114 }
01115
01116
01117
01118 void sfs_index::dump(const char *path, fs_inode *inode) {
01119 if(inode->fchild == NULL) {
01120 LOG(DBG,"%s%s\n",path,inode->name);
01121 return;
01122 }
01123
01124 char fp[256];
01125 sprintf(fp,"%s%s/",path,inode->name);
01126
01127 fs_inode *curr = inode->fchild;
01128
01129 while(curr) {
01130 dump(fp,curr);
01131 curr = curr->next;
01132 }
01133 }
01134
01135 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
01136 fs_inode *sfs_index::add_inode_from(fs_inode *prev, char *name, long long int offset, int sz, int overhead)
01137 #else
01138 fs_inode *sfs_index::add_inode_from(fs_inode *prev, char *name, int offset, int sz, int overhead)
01139 #endif
01140 {
01141 int eq=0;
01142
01143 fs_inode *parent = prev->parent;
01144
01145 fs_inode *link = find_last_lesser_neighbor(prev, name, eq);
01146 if(eq == 0) return link;
01147
01148
01149 if(!link) return add_inode(parent,name,offset,sz,overhead);
01150
01151 fs_inode *newn = alloc_inode(name,offset,sz,overhead);
01152 if(!newn) return NULL;
01153
01154
01155 newn->parent = parent;
01156 newn->next = link->next;
01157 link->next = newn;
01158 return newn;
01159 }
01160
01161 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
01162 fs_inode *sfs_index::add_inode(fs_inode *parent, char *name, long long int offset, int sz, int overhead)
01163 #else
01164 fs_inode *sfs_index::add_inode(fs_inode *parent, char *name, int offset, int sz, int overhead)
01165 #endif
01166 {
01167 int eq=0;
01168 int first=0;
01169
01170 fs_inode *link = find_last_lesser_child(parent, name, first, eq);
01171
01172 if(eq == 0) return link;
01173
01174 fs_inode *newn = alloc_inode(name,offset,sz,overhead);
01175
01176 if(!newn) return NULL;
01177 newn->parent = parent;
01178
01179 if(first) {
01180 newn->next = parent->fchild;
01181 parent->fchild = newn;
01182
01183 return newn;
01184 }
01185
01186 newn->next = link->next;
01187 link->next = newn;
01188 return newn;
01189 }
01190
01191 fs_inode *sfs_index::find_last_lesser_neighbor(fs_inode *first, char *name, int &eq)
01192 {
01193 eq = -1;
01194 fs_inode *curr = first;
01195 if(!curr) return NULL;
01196
01197
01198 eq = mstrcmp(curr->name, name);
01199
01200 if(eq > 0) return NULL;
01201 if(eq == 0) return curr;
01202
01203 fs_inode *next = curr->next;
01204
01205 while(next) {
01206
01207 eq = mstrcmp(next->name, name);
01208 if(eq > 0) return curr;
01209 if(eq == 0) return next;
01210 curr = next;
01211 next = curr->next;
01212 }
01213 return curr;
01214 }
01215
01216 fs_inode *sfs_index::find_last_lesser_child(fs_inode *parent, char *name, int &first, int &eq)
01217 {
01218 first = 1;
01219 eq = -1;
01220
01221 fs_inode *curr = parent->fchild;
01222 if(!curr) return NULL;
01223
01224
01225 eq = mstrcmp(curr->name, name);
01226
01227 if(eq > 0) return NULL;
01228 if(eq == 0) {
01229 return curr;
01230 }
01231
01232 first = 0;
01233
01234 fs_inode *next = curr->next;
01235
01236 while(next) {
01237
01238 eq = mstrcmp(next->name, name);
01239 if(eq > 0) return curr;
01240 if(eq == 0) return next;
01241
01242 curr = next;
01243 next = curr->next;
01244 }
01245
01246 return curr;
01247 }
01248
01249 int sfs_index::getfileheadersz(char *fn)
01250 {
01251 return (sizeof(SFS_File) - 4 + seeksize(strlen(fn)+1));
01252 }
01253
01254
01255 int sfs_index::putfileheader(char *ptr, char *fn, int filesz, int flags)
01256 {
01257 return sfs_putfileheader(ptr,fn,filesz,flags);
01258 }
01259