26 #define MAX_SEND_IOVECS 100
28 int mstrcmp(
char *s1,
char *s2)
30 if((s1[0] ==
'#') && (s2[0] ==
'#')) {
37 if(x1 < x2)
return -1;
50 void striptofirst(
char *str)
53 if(*str ==
'/') *(str+1) =
'\0';
61 void striptofirstdir(
char *str)
65 if(*str ==
'/') scount++;
79 char *striptofile(
char *str)
84 if(*str ==
'/') ostr = str+1;
97 void stripfile(
char *str)
102 while(*str !=
'\0') {
103 if(*str ==
'/') lslash = str;
107 if(lslash) *(lslash+1) =
'\0';
108 else strcpy(ostr,
"/");
117 memset(buff, 0,
sizeof(buff));
121 stickypath[0] =
'\0';
133 void SFS_ittr::swapEntry()
136 if(entry.byte_order == 0x04030201)
return;
138 entry.byte_order = swap32(entry.byte_order);
140 entry.byte_order = swap32(entry.byte_order);
141 entry.sz = swap32(entry.sz);
142 entry.reserved = swap16(entry.reserved);
153 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
154 LOG(DBG,
"Calling next: fileoffset=%lld filepos=%d",fileoffset,filepos);
157 LOG(DBG,
"Calling next: fileoffset=%d filepos=%d",fileoffset,filepos);
163 LOG(DBG,
"filepos = %d, entry.sz=%d entry.head_sz=%d",filepos,entry.sz,entry.head_sz);
165 ret = wfile->lseek(seeksize(entry.sz), SEEK_CUR);
167 LOG(ERR,
"Error seeking: %s\n",strerror(errno));
172 LOG(DBG,
"fileoffset=%d --> + %d + %d",
173 entry.sz, entry.head_sz);
174 fileoffset += seeksize(entry.sz) + entry.head_sz;
179 LOG(DBG,
"---DIR: name=%s entry.attr = 0x%x headsz=%d",entry.name, entry.attr,entry.head_sz);
182 if(entry.attr & SFS_ATTR_NOCD) {
187 if(entry.name[0] ==
'/') {
189 strcpy(ppath, entry.name);
193 strcat(ppath, entry.name);
198 if(entry.attr & SFS_ATTR_STICKY_CD) {
199 strcpy(stickypath,ppath);
213 int ret = wfile->read(buff, 8);
221 LOG(ERR,
"Error reading next file record...");
227 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
228 wfile->lseek(-((
long long int)8), SEEK_CUR);
229 long long int xxx = wfile->lseek(0,SEEK_CUR);
230 LOG(DBG,
"fileoffset=%lld xxx=%lld buff=%s",fileoffset,xxx,buff);
232 wfile->lseek(-8, SEEK_CUR);
233 int xxx = wfile->lseek(0,SEEK_CUR);
234 LOG(DBG,
"fileoffset=%d xxx=%d buff=%s",fileoffset,xxx,buff);
237 if(memcmp(buff,
"SFS V", 5) == 0) {
239 wfile->lseek(12, SEEK_CUR);
245 if(memcmp(buff,
"LRHD", 4) == 0) {
248 if(nextLRHD() >= 0) {
249 LOG(DBG,
"lrhd entry.sz = %d",entry.sz);
255 wfile->lseek(60, SEEK_CUR);
261 LOG(DBG,
"Not a DATA LRHD fileoffset=%d skipped_bytes=%d seek=%d",
262 fileoffset,skipped_bytes,wfile->lseek(0,SEEK_CUR));
267 if(memcmp(buff,
"DATAP", 5) == 0) {
270 LOG(DBG,
"Before datap: file=%d filepos=%d offset=%d entrysz=%d",
271 wfile->lseek(0,SEEK_CUR), filepos,fileoffset,entry.sz);
273 if(nextDatap() >= 0) {
274 LOG(DBG,
"After datap: file=%d filepos=%d offset=%d entrysz=%d",
275 wfile->lseek(0,SEEK_CUR), filepos,fileoffset,entry.sz);
279 wfile->lseek(204, SEEK_CUR);
281 skipped_bytes += 204;
285 if(memcmp(buff,
"HEAD", 4) == 0) {
287 wfile->lseek(12, SEEK_CUR);
293 if(memcmp(buff,
"FILE", 4) == 0) {
299 if(wfile->type == WRAP_MEM) {
305 memcpy(ttmp,buff,16) ;
307 LOG(ERR,
"Error: %s is not a valid specifier\n",ttmp);
314 memset(entryBuff, 0,
sizeof(entryBuff));
316 ret = wfile->read(entryBuff,16);
323 LOG(ERR,
"Error reading file entry: %s (%d)\n",strerror(errno),ret);
329 if(memcmp(entry.type,
"FILE",4) != 0) {
330 LOG(ERR,
"Error reading file entry: {%c%c%c%c} Not a file record...\n",
331 entry.type[0],entry.type[1],entry.type[2],entry.type[3]);
340 ret = wfile->read(entryBuff + 16, entry.head_sz - 16);
341 if(ret != entry.head_sz - 16) {
342 LOG(ERR,
"Error reading file entry: size mismatch ret=%d sz=%d\n",ret,entry.head_sz);
348 LOG(DBG,
"---DIR: name=%s entry.attr = 0x%x\n",entry.name, entry.attr);
352 if(strstr(entry.name,
"legacy")) {
353 entry.attr |= SFS_ATTR_POPSTICKY;
356 if(strstr(entry.name,
"pad")) {
357 entry.attr |= SFS_ATTR_POPSTICKY;
360 if(entry.attr & SFS_ATTR_POPSTICKY) {
363 if(stickypath[0] !=
'\0')
364 strcpy(ppath, stickypath);
367 if(entry.name[0] ==
'/') {
368 strcpy(fullpath, entry.name);
371 strcpy(fullpath, ppath);
372 strcat(fullpath, entry.name);
375 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
376 LOG(DBG,
"fullpath %s, entry.name: %s, fileoffset %lld/%d, sz %d head_sz %d",
377 fullpath, entry.name, fileoffset, filepos, entry.sz, entry.head_sz);
379 LOG(DBG,
"fullpath %s, entry.name: %s, fileoffset %d/%d, sz %d head_sz %d",
380 fullpath, entry.name, fileoffset, filepos, entry.sz, entry.head_sz);
387 char *SFS_getpayload(
char *buff)
390 return (buff + f->head_sz);
398 sizes->dataSize += inode->sz;
399 sizes->size += inode->sz + inode->overhead;
401 if(inode->fchild) getInodeSize(inode->fchild, sizes);
402 if(inode->next) getInodeSize(inode->next, sizes);
406 int sfs_index::getDirSize(
char *dir,
SfsDirsize *sizes)
412 sizes->dataSize += d->inode->sz;
413 sizes->size += d->inode->sz + d->inode->overhead;
416 if(d->inode->fchild) {
417 dirsz = getInodeSize(d->inode->fchild,sizes);
425 int sfs_index::writeFsHeader()
427 static char *volumeSpec = (
char *)
"SFS V00.01\0\0\0";
436 ret = wfile.write(volumeSpec, sz);
445 memcpy(head.type,
"HEAD", 4);
446 head.byte_order = 0x04030201;
447 head.time = time(NULL);
452 ret = wfile.write(bb, sz);
465 int sfs_index::write(
char *fn,
char *buff,
int size)
471 int attr = SFS_ATTR_NOCD;
491 int len = strlen(fn);
492 for(
int i=0;i<len-1;i++) {
500 getFullPath(path, fn);
505 memcpy(file->type,
"FILE", 4);
506 file->byte_order = 0x04030201;
508 file->head_sz = seeksize(strlen(cwd)+1) +
sizeof(
SFS_File) - 4;
510 strcpy(file->name, cwd);
516 ret = wfile.write(bb, sz);
537 memcpy(file->type,
"FILE", 4);
538 file->byte_order = 0x04030201;
540 file->head_sz = seeksize(strlen(path)+1) +
sizeof(
SFS_File) - 4;
543 strcpy(file->name, path);
549 ret = wfile.write(bb, sz);
562 ret = wfile.write(bb, sz);
572 char *zero = (
char *)
"\0\0\0\0";
573 sz = seeksize(size) - size;
577 ret = wfile.write(bb, sz);
589 int sfs_index::getwritevsz(
fs_iovec *fsiovec,
int n)
592 for(
int i=0;i<n;i++) {
593 if(fsiovec[i].filename) {
594 sz += seeksize(strlen(fsiovec[i].filename)+1);
598 sz += seeksize(fsiovec[i].len);
603 int sfs_index::writev(
fs_iovec *fsiovec,
int n)
605 return writev_sticky(fsiovec, n, NULL);
610 int sfs_index::writev_call_retry(
int fd, iovec *iovec,
int vec)
612 if(vec > MAX_SEND_IOVECS) {
613 LOG(CRIT,
"writev with too %d iovecs... max=%d",vec,MAX_SEND_IOVECS);
618 for(
int i=0;i<vec;i++) {
619 len += iovec[i].iov_len;
624 if((ret == 0) && (retries<5)) {
625 ret = ::writev(fd, iovec, vec);
629 if((ret==len) && (retries > 1)) {
630 LOG(U_JEFF,
"successful writev took %d tries!");
634 for(
int i=0;i<vec;i++) {
635 LOG(NOTE,
"socket error (%d)(%s) vec[%d]:base=%p len=%d",
636 ret, strerror(errno), i, iovec[i].iov_base, iovec[i].iov_len);
638 LOG(ERR,
"socket error: ret=%d of %d in %d tries (%s)", ret, len, retries, strerror(errno));
651 int sfs_index::writev_sticky(
fs_iovec *fsiovec,
int n,
int *sticky)
653 iovec iovec[MAX_SEND_IOVECS];
654 char _buff[(
sizeof(
SFS_File) + 40)*50];
660 if(n > MAX_SEND_IOVECS) {
661 LOG(CRIT,
"sending %d iovecs > than max=%d",n,MAX_SEND_IOVECS);
672 LOG(DBG,
"i=%d\n",i);
674 if(fsiovec[i].filename) {
677 memcpy(file->type,
"FILE", 4);
678 file->byte_order = 0x04030201;
679 file->sz = fsiovec[i].len;
680 file->head_sz = seeksize(strlen(fsiovec[i].filename)+1) +
sizeof(
SFS_File) - 4;
681 file->attr = SFS_ATTR_NOCD;
684 file->attr |= SFS_ATTR_POPSTICKY;
687 LOG(DBG,
"%d %d",sticky[i], file->sz);
688 file->sz = -(sticky[i]);
689 LOG(DBG,
"Set file->sz=%d",file->sz);
692 strcpy(file->name, fsiovec[i].filename);
695 iovec[vec].iov_base = b;
696 iovec[vec].iov_len = file->head_sz;
697 LOG(DBG,
"fn: iovec[%d] name=%s 0x%x: base=0x%x len=%d",
710 iovec[vec].iov_base = fsiovec[i].buff;
711 iovec[vec].iov_len = seeksize(fsiovec[i].len);
713 LOG(DBG,
"iovec[%d] name=%s 0x%x: base=0x%x len=%d",
715 fsiovec[vec].filename,
716 fsiovec[vec].filename,
727 for(
int i=0;i<vec;i++) {
728 all_size += iovec[i].iov_len ;
732 int ret = writev_call_retry(wfile.fd, iovec, vec);
740 singleDirIttr = NULL;
747 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
748 int sfs_index::mountSingleDirMem(
char *buffer,
int size,
long long int offset)
750 int sfs_index::mountSingleDirMem(
char *buffer,
int size,
int offset)
755 wfile.openmem(buffer, size);
757 singleDirOffset = offset;
758 singleDirSize = size;
759 return mountSingleDir();
765 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
766 int sfs_index::mountSingleDir(
char *fn,
long long int offset)
768 int sfs_index::mountSingleDir(
char *fn,
int offset)
771 LOG(DBG,
"the spec is: " __DATE__
":" __TIME__);
776 wfile.opendisk(fn, O_RDONLY);
778 LOG(ERR,
"Bad error opening %s mounting single directory (%s)",fn,strerror(errno));
781 wfile.lseek(offset, SEEK_SET);
783 int ret = mountSingleDir();
788 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
789 int sfs_index::getSingleDirSize(
char *fn,
long long int offset)
791 int sfs_index::getSingleDirSize(
char *fn,
int offset)
798 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
799 LOG(DBG,
"singledirsize file=%s, offset=%lld",fn,offset);
801 LOG(DBG,
"singledirsize file=%s, offset=%d",fn,offset);
805 wfile.opendisk(fn, O_RDONLY);
806 if(wfile.fd < 0)
return wfile.fd;
807 wfile.lseek(offset, SEEK_SET);
812 if(ittr->get(&wfile) < 0) {
814 wfile.lseek(offset,SEEK_SET);
818 sz += ittr->skipped_bytes;
820 LOG(DBG,
"partial sz=%d, skipped=%d",sz,ittr->skipped_bytes);
822 while(ittr->next() >= 0) {
824 if(ittr->filepos == -1)
break;
827 if(topdir[0] ==
'\0') {
828 strncpy(topdir,ittr->fullpath,40);
829 for(
int i=0;i<40;i++) {
830 if(topdir[i] ==
'\0')
break;
831 if((i>0) && (topdir[i] ==
'/')) {
833 topdirlen = strlen(topdir);
839 LOG(DBG,
"Topdir=%s sz(before)=%d",topdir,sz);
841 if(memcmp(topdir, ittr->fullpath, topdirlen) != 0) {
845 sz += ittr->skipped_bytes;
846 sz += ittr->entry.head_sz;
847 int esz = (ittr->entry.sz + 3) / 4;
855 LOG(DBG,
"returning %d",sz);
859 int sfs_index::mountSingleDir()
861 if(singleDirIttr)
delete singleDirIttr;
863 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
864 long long int offset = wfile.lseek(0,SEEK_CUR);
865 LOG(DBG,
"mountSingleDir() offset=%lld 0x%x", offset, wfile.wbuff);
867 singleDirOffset = offset;
868 nextSingleDirOffset = offset;
871 int offset = wfile.lseek(0,SEEK_CUR);
873 singleDirOffset = offset;
874 nextSingleDirOffset = offset;
879 singleDirIttr =
new SFS_ittr(offset);
881 if(singleDirIttr->get(&wfile) < 0) {
882 delete singleDirIttr;
883 singleDirIttr = NULL;
886 root = alloc_inode(
"",0,0,0);
892 if(singleDirIttr->next() < 0) {
894 root = alloc_inode(
"",0,0,0);
898 LOG(NOTE,
"Couldn't get any SFS dirs...");
902 return _mountNextDir();
910 int sfs_index::mountNextDir()
912 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
913 singleDirOffset = nextSingleDirOffset;
915 wfile.lseek(singleDirOffset,SEEK_SET);
918 wfile.lseek(0,SEEK_CUR);
922 return(_mountNextDir());
926 int sfs_index::_mountNextDir()
930 if(index_created) free_inode(root);
933 root = alloc_inode(
"",0,0,0);
939 if(singleDirIttr->filepos == -1) {
944 while(strcmp(singleDirIttr->fullpath,
"/") == 0) {
945 if(singleDirIttr->next() < 0) {
946 LOG(DBG,
"End of file/error before first directory");
949 if(singleDirIttr->filepos == -1) {
957 strcpy(basedir, singleDirIttr->fullpath);
958 striptofirstdir(basedir);
963 addnode(singleDirIttr);
965 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
966 long long int last_offset = singleDirIttr->fileoffset;
969 int last_offset = singleDirIttr->fileoffset;
970 int last_filepos = singleDirIttr->filepos;
973 int last_head_sz = singleDirIttr->entry.head_sz;
974 int last_file_sz = seeksize(singleDirIttr->entry.sz);
976 if(singleDirIttr->next() < 0) {
977 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
981 if(singleDirIttr->filepos == -1) {
984 singleDirSize = last_offset + last_head_sz + last_file_sz - singleDirOffset;
986 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
987 return (files_added > 0) ? 1 : 0;
991 strcpy(currdir, singleDirIttr->fullpath);
992 striptofirstdir(currdir);
999 if(strcmp(basedir, currdir) != 0) {
1001 singleDirSize = last_offset + last_head_sz + last_file_sz - singleDirOffset;
1003 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
1004 return (files_added > 0) ? 1 : 0;
1008 nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
1012 int sfs_index::_create()
1014 root = alloc_inode(
"",0,0,0);
1023 if(ittr.get(&wfile) < 0) {
1032 if(ittr.next() < 0) {
1041 if(ittr.filepos == -1) {
1053 LOG(ERR,
"never happens\n");
1057 void sfs_index::addnode(
SFS_ittr *ittr)
1060 char thispathonly[256];
1063 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
1064 LOG(DBG,
"addnode: %s %lld %d",ittr->fullpath, ittr->fileoffset, ittr->filepos);
1066 LOG(DBG,
"addnode: %s %d %d",ittr->fullpath, ittr->fileoffset, ittr->filepos);
1069 if(ittr->entry.attr == SFS_ATTR_INVALID)
return;
1071 strcpy(thispathonly, ittr->fullpath);
1072 stripfile(thispathonly);
1074 strcpy(fullpath, ittr->fullpath);
1076 next[0] = strtok_r(&fullpath[1],
"/", &_strtok_static_);
1079 while((next[nn] = strtok_r(NULL,
"/", &_strtok_static_))) nn++;
1083 for(
int i=0;i<nn-1;i++) {
1084 inode = add_inode(inode, next[i], 0, 0, 0);
1087 inode = add_inode(inode, next[nn-1], ittr->fileoffset + ittr->entry.head_sz, ittr->entry.sz, ittr->entry.head_sz);
1092 void sfs_index::dump(
const char *path,
fs_inode *inode) {
1093 if(inode->fchild == NULL) {
1094 LOG(DBG,
"%s%s\n",path,inode->name);
1099 sprintf(fp,
"%s%s/",path,inode->name);
1109 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
1110 fs_inode *sfs_index::add_inode_from(
fs_inode *prev,
char *name,
long long int offset,
int sz,
int overhead)
1112 fs_inode *sfs_index::add_inode_from(
fs_inode *prev,
char *name,
int offset,
int sz,
int overhead)
1119 fs_inode *link = find_last_lesser_neighbor(prev, name, eq);
1120 if(eq == 0)
return link;
1123 if(!link)
return add_inode(parent,name,offset,sz,overhead);
1125 fs_inode *newn = alloc_inode(name,offset,sz,overhead);
1126 if(!newn)
return NULL;
1129 newn->parent = parent;
1130 newn->next = link->next;
1135 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
1136 fs_inode *sfs_index::add_inode(
fs_inode *parent,
char *name,
long long int offset,
int sz,
int overhead)
1138 fs_inode *sfs_index::add_inode(
fs_inode *parent,
char *name,
int offset,
int sz,
int overhead)
1144 fs_inode *link = find_last_lesser_child(parent, name, first, eq);
1146 if(eq == 0)
return link;
1148 fs_inode *newn = alloc_inode(name,offset,sz,overhead);
1150 if(!newn)
return NULL;
1151 newn->parent = parent;
1154 newn->next = parent->fchild;
1155 parent->fchild = newn;
1160 newn->next = link->next;
1165 fs_inode *sfs_index::find_last_lesser_neighbor(
fs_inode *first,
char *name,
int &eq)
1169 if(!curr)
return NULL;
1172 eq = mstrcmp(curr->name, name);
1174 if(eq > 0)
return NULL;
1175 if(eq == 0)
return curr;
1181 eq = mstrcmp(next->name, name);
1182 if(eq > 0)
return curr;
1183 if(eq == 0)
return next;
1190 fs_inode *sfs_index::find_last_lesser_child(
fs_inode *parent,
char *name,
int &first,
int &eq)
1196 if(!curr)
return NULL;
1199 eq = mstrcmp(curr->name, name);
1201 if(eq > 0)
return NULL;
1212 eq = mstrcmp(next->name, name);
1213 if(eq > 0)
return curr;
1214 if(eq == 0)
return next;
1223 int sfs_index::getfileheadersz(
char *fn)
1225 return (
sizeof(
SFS_File) - 4 + seeksize(strlen(fn)+1));
1229 int sfs_index::putfileheader(
char *ptr,
char *fn,
int filesz,
int flags)
1231 return sfs_putfileheader(ptr,fn,filesz,flags);