StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
sfs_index.cxx
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <time.h>
6 #include "sfs_index.h"
7 #include <sys/uio.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <errno.h>
12 
13 #include <rtsLog.h>
14 
15 #include <rts.h>
16 //#include <byteswap.h>
17 //#define swap16(x) bswap_16(x)
18 //#define swap32(x) bswap_32(x)
19 
20 //int debug = 0;
21 
22 /********************************/
23 /* Utilities */
24 /********************************/
25 
26 #define MAX_SEND_IOVECS 100
27 
28 int mstrcmp(char *s1, char *s2)
29 {
30  if((s1[0] == '#') && (s2[0] == '#')) {
31  int x1;
32  int x2;
33 
34  x1 = atoi(&s1[1]);
35  x2 = atoi(&s2[1]);
36  if(x1 > x2) return 1;
37  if(x1 < x2) return -1;
38  return 0;
39  }
40  return strcmp(s1,s2);
41 }
42 
43 
44 // /dir_1/dir_2/file --> /
45 // file --> file
46 // dir_1/file --> dir_1/
47 // dir_1/ --> dir_1/
48 // "" --> ""
49 //
50 void striptofirst(char *str)
51 {
52  while(*str != '\0') {
53  if(*str == '/') *(str+1) = '\0';
54  str++;
55  }
56 }
57 
58 // /dir_1/dir_2 --> /dir_1
59 // dir_1/dir_2/dir_3 --> /dir_1/dir_2
60 
61 void striptofirstdir(char *str)
62 {
63  int scount = 0;
64  while(*str != '\0') {
65  if(*str == '/') scount++;
66  if(scount >= 2) {
67  *str = '\0';
68  }
69  else str++;
70  }
71 }
72 
73 // /dir_1/dir_2/file --> file
74 // file --> file
75 // dir_1/file --> file
76 // dir_1/ --> ""
77 // "" --> ""
78 //
79 char *striptofile(char *str)
80 {
81  char *ostr = str;
82 
83  while(*str != '\0') {
84  if(*str == '/') ostr = str+1;
85  str++;
86  }
87 
88  return ostr;
89 }
90 
91 // /dir_1/dir_2/file --> /dir_1/dir_2/
92 // file --> /
93 // dir_1/file --> dir_1
94 // dir_1/ --> dir_1/
95 // "" --> /
96 //
97 void stripfile(char *str)
98 {
99  char *ostr = str;
100  char *lslash = NULL;
101 
102  while(*str != '\0') {
103  if(*str == '/') lslash = str;
104  str++;
105  }
106 
107  if(lslash) *(lslash+1) = '\0';
108  else strcpy(ostr, "/");
109 }
110 
111 int SFS_ittr::get(wrapfile *wrap)
112 {
113  // printf("ittr get file 0x%x %d\n",wrapbuff, fd);
114  skipped_bytes = 0;
115 
116  char buff[12];
117  memset(buff, 0, sizeof(buff));
118 
119  wfile = wrap;
120 
121  stickypath[0] = '\0';
122  ppath[0] = '\0';
123  fullpath[0]='\0';
124 
125  //printf("fileoffset %d\n",fileoffset);
126  filepos = 0;
127  strcpy(ppath,"/");
128 
129  return 0;
130 }
131 
132 
133 void SFS_ittr::swapEntry()
134 {
135  // int swap;
136  if(entry.byte_order == 0x04030201) return;
137 
138  entry.byte_order = swap32(entry.byte_order);
139 
140  entry.byte_order = swap32(entry.byte_order);
141  entry.sz = swap32(entry.sz);
142  entry.reserved = swap16(entry.reserved);
143 }
144 
145 
146 // Return -1 on error
147 // 0 on ok.
148 int SFS_ittr::next()
149 {
150  //if(legacy) return legacy_next();
151  skipped_bytes = 0;
152 
153 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
154  LOG(DBG, "Calling next: fileoffset=%lld filepos=%d",fileoffset,filepos);
155  long long int ret;
156 #else
157  LOG(DBG, "Calling next: fileoffset=%d filepos=%d",fileoffset,filepos);
158  int ret;
159 #endif
160 
161  //printf("ittr next\n");
162 
163  LOG(DBG, "filepos = %d, entry.sz=%d entry.head_sz=%d",filepos,entry.sz,entry.head_sz);
164  if(filepos == 1) { // need to jump to next...
165  ret = wfile->lseek(seeksize(entry.sz), SEEK_CUR);
166  if(ret < 0) {
167  LOG(ERR,"Error seeking: %s\n",strerror(errno));
168  return -1;
169  }
170  filepos = 2;
171 
172  LOG(DBG, "fileoffset=%d --> + %d + %d",
173  entry.sz, entry.head_sz);
174  fileoffset += seeksize(entry.sz) + entry.head_sz;
175  }
176 
177  if(filepos == 2) {
178  // update ppath...
179  LOG(DBG,"---DIR: name=%s entry.attr = 0x%x headsz=%d",entry.name, entry.attr,entry.head_sz);
180 
181 
182  if(entry.attr & SFS_ATTR_NOCD) {
183  // ppath unchanged....
184  //printf("no change %s\n",entry.name);
185  }
186  else { // update ppath regularly...
187  if(entry.name[0] == '/') {
188  //printf("strcpy %s\n",entry.name);
189  strcpy(ppath, entry.name);
190  }
191  else {
192  //printf("ccat %s %s\n",ppath,entry.name);
193  strcat(ppath, entry.name);
194  }
195  stripfile(ppath);
196  }
197 
198  if(entry.attr & SFS_ATTR_STICKY_CD) {
199  strcpy(stickypath,ppath);
200  // printf("(set) ppath = %s, stickypath %s\n",ppath,stickypath);
201  }
202 
203 
204  //printf("----------ppath is now %s (%s)\n",ppath,entry.name);
205 
206  filepos = 0;
207  }
208 
209 
210  // expect a FILE record, LRHD or DATAP... jump the rest...
211  for(;;) {
212  char buff[16];
213  int ret = wfile->read(buff, 8);
214 
215  if(ret == 0) { // done...
216  filepos = -1;
217  return 0;
218  }
219 
220  if(ret != 8) {
221  LOG(ERR, "Error reading next file record...");
222  return -1;
223  }
224 
225  buff[5] = 0;
226 
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);
231 #else
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);
235 #endif
236 
237  if(memcmp(buff, "SFS V", 5) == 0) {
238  //if(debug) LOG(DBG,"Found SFS version");
239  wfile->lseek(12, SEEK_CUR);
240  fileoffset += 12;
241  skipped_bytes += 12;
242  continue;
243  }
244 
245  if(memcmp(buff, "LRHD", 4) == 0) {
246  //if(debug) LOG(DBG,"Found LRHD");
247 
248  if(nextLRHD() >= 0) { // good data LRHD... got entry...
249  LOG(DBG, "lrhd entry.sz = %d",entry.sz);
250  return 0;
251  }
252 
253  //LOG(DBG, "Seek: %d",wfile->lseek(0,SEEK_CUR));
254 
255  wfile->lseek(60, SEEK_CUR);
256 
257  //LOG(DBG, "Seek2: %d",wfile->lseek(0,SEEK_CUR));
258 
259  fileoffset += 60;
260  skipped_bytes += 60;
261  LOG(DBG, "Not a DATA LRHD fileoffset=%d skipped_bytes=%d seek=%d",
262  fileoffset,skipped_bytes,wfile->lseek(0,SEEK_CUR));
263 
264  continue;
265  }
266 
267  if(memcmp(buff, "DATAP", 5) == 0) {
268  //if(debug) LOG(DBG,"Found DATAP");
269 
270  LOG(DBG, "Before datap: file=%d filepos=%d offset=%d entrysz=%d",
271  wfile->lseek(0,SEEK_CUR), filepos,fileoffset,entry.sz);
272 
273  if(nextDatap() >= 0) { // DATAP and no following FILE. got entry
274  LOG(DBG, "After datap: file=%d filepos=%d offset=%d entrysz=%d",
275  wfile->lseek(0,SEEK_CUR), filepos,fileoffset,entry.sz);
276  return 0;
277  }
278 
279  wfile->lseek(204, SEEK_CUR);
280  fileoffset += 204;
281  skipped_bytes += 204;
282  continue;
283  }
284 
285  if(memcmp(buff, "HEAD", 4) == 0) {
286  //if(debug) LOG(DBG,"Found HEAD");
287  wfile->lseek(12, SEEK_CUR);
288  fileoffset += 12;
289  skipped_bytes += 12;
290  continue;
291  }
292 
293  if(memcmp(buff, "FILE", 4) == 0) { // finally!
294  break;
295  }
296 
297  else {
298 
299  if(wfile->type == WRAP_MEM) { // ugly hack... done!
300  filepos = -1;
301  return 0;
302  }
303 
304  char ttmp[16] ;
305  memcpy(ttmp,buff,16) ;
306  ttmp[15] = 0 ;
307  LOG(ERR,"Error: %s is not a valid specifier\n",ttmp);
308  filepos = -1;
309  return 0;
310  }
311  }
312  // Read File Desc
313  // clear entrybuff
314  memset(entryBuff, 0, sizeof(entryBuff));
315 
316  ret = wfile->read(entryBuff,16);
317  if(ret == 0) {
318  filepos = -1;
319  return 0;
320  }
321 
322  if(ret != 16) {
323  LOG(ERR,"Error reading file entry: %s (%d)\n",strerror(errno),ret);
324  return -1;
325  }
326 
327  //printf("1- compare file: %s\n",entry.type);
328 
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]);
332  return -1;
333  }
334 
335  swapEntry();
336 
337  // printf("reading... bytes 0x%x, head_sz %d, sz = %d\n",
338  // entry.byte_order, entry.head_sz, entry.sz);
339 
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);
343 
344  return -1;
345  }
346 
347 
348  LOG(DBG,"---DIR: name=%s entry.attr = 0x%x\n",entry.name, entry.attr);
349 
350 
351  // hacks for 2007
352  if(strstr(entry.name, "legacy")) {
353  entry.attr |= SFS_ATTR_POPSTICKY;
354  }
355 
356  if(strstr(entry.name, "pad")) {
357  entry.attr |= SFS_ATTR_POPSTICKY;
358  }
359 
360  if(entry.attr & SFS_ATTR_POPSTICKY) {
361  // doesn't reset stickypath!
362  //printf("---DIR: (pop) ppath %s stickypath %s\n",ppath,stickypath);
363  if(stickypath[0] != '\0')
364  strcpy(ppath, stickypath);
365  }
366 
367  if(entry.name[0] == '/') {
368  strcpy(fullpath, entry.name);
369  }
370  else {
371  strcpy(fullpath, ppath);
372  strcat(fullpath, entry.name);
373  }
374 
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);
378 #else
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);
381 #endif
382 
383  filepos = 1;
384  return 0;
385 }
386 
387 char *SFS_getpayload(char *buff)
388 {
389  SFS_File *f = (SFS_File *)buff;
390  return (buff + f->head_sz);
391 }
392 
393 int sfs_index::getInodeSize(fs_inode *inode, SfsDirsize *sizes)
394 {
395  //printf("name: %s offset: %lld overhead: %d sz: %d (sz: %lld)\n",
396  // inode->name, inode->offset, inode->overhead, inode->sz, sizes->dataSize);
397 
398  sizes->dataSize += inode->sz;
399  sizes->size += inode->sz + inode->overhead;
400 
401  if(inode->fchild) getInodeSize(inode->fchild, sizes);
402  if(inode->next) getInodeSize(inode->next, sizes);
403  return 0;
404 }
405 
406 int sfs_index::getDirSize(char *dir, SfsDirsize *sizes)
407 {
408  memset(sizes, 0, sizeof(SfsDirsize));
409  fs_dir *d = opendir(dir);
410  if(!d) return -1;
411 
412  sizes->dataSize += d->inode->sz;
413  sizes->size += d->inode->sz + d->inode->overhead;
414 
415  int dirsz = 0;
416  if(d->inode->fchild) {
417  dirsz = getInodeSize(d->inode->fchild,sizes);
418  }
419 
420  closedir(d);
421 
422  return dirsz;
423 }
424 
425 int sfs_index::writeFsHeader()
426 {
427  static char *volumeSpec = (char *)"SFS V00.01\0\0\0";
428  int ret;
429  int sz;
430  char *bb;
431  SFS_Header head;
432 
433  bb = volumeSpec;
434  sz = 12;
435  while(sz) {
436  ret = wfile.write(volumeSpec, sz);
437 
438  if(ret < 0) {
439  return -1;
440  }
441  sz -= ret;
442  bb += ret;
443  }
444 
445  memcpy(head.type, "HEAD", 4);
446  head.byte_order = 0x04030201;
447  head.time = time(NULL);
448 
449  bb = (char *)&head;
450  sz = sizeof(head);
451  while(sz) {
452  ret = wfile.write(bb, sz);
453 
454  if(ret < 0) {
455  return -1;
456  }
457 
458  sz -= ret;
459  bb += ret;
460  }
461 
462  return 0;
463 }
464 
465 int sfs_index::write(char *fn, char *buff, int size)
466 {
467  int ret;
468  char *bb;
469  int sz;
470  char path[256];
471  int attr = SFS_ATTR_NOCD;
472 
473  char b[256];
474  SFS_File *file = (SFS_File *)b;
475 
476  if(cdchanged) {
477  // (a) if filename is absolute filename do nothing, leave cdchanged as is
478  // (b) if filename has no subdirs, then use fullpath and unset NOCD
479  // (c) if filename has subdirs, then write a directory entry separately
480 
481  //printf("cdchanged\n");
482 
483  if(fn[0] == '/') {
484  strcpy(path, fn);
485  }
486  else {
487  // any non-trailing slash?
488  cdchanged = 0; // now we do a cd either way!
489 
490  int subdirs = 0;
491  int len = strlen(fn);
492  for(int i=0;i<len-1;i++) {
493  if(fn[i] == '/') {
494  subdirs = 1;
495  break;
496  }
497  }
498 
499  if(!subdirs) {
500  getFullPath(path, fn);
501  attr = 0;
502  }
503 
504  if(subdirs) {
505  memcpy(file->type, "FILE", 4);
506  file->byte_order = 0x04030201;
507  file->sz = 0;
508  file->head_sz = seeksize(strlen(cwd)+1) + sizeof(SFS_File) - 4;
509  file->attr = 0;
510  strcpy(file->name, cwd);
511 
512  bb = (char *)file;
513  sz = file->head_sz;
514 
515  while(sz) {
516  ret = wfile.write(bb, sz);
517  if(ret < 0) {
518  return -1;
519  }
520 
521  sz -= ret;
522  bb += ret;
523  }
524 
525  strcpy(path, fn);
526  }
527  }
528  }
529  else {
530  strcpy(path, fn);
531  }
532 
533  //printf("cd changed = %d path = %s\n",cdchanged,path);
534 
535 
536 
537  memcpy(file->type, "FILE", 4);
538  file->byte_order = 0x04030201;
539  file->sz = size;
540  file->head_sz = seeksize(strlen(path)+1) + sizeof(SFS_File) - 4;
541  file->attr = attr;
542 
543  strcpy(file->name, path);
544 
545  bb = (char *)file;
546  sz = file->head_sz;
547 
548  while(sz) {
549  ret = wfile.write(bb, sz);
550  if(ret < 0) {
551  return -1;
552  }
553 
554  sz -= ret;
555  bb += ret;
556  }
557 
558  sz = size;
559  bb = buff;
560 
561  while(sz) {
562  ret = wfile.write(bb, sz);
563  if(ret < 0) {
564  return -1;
565  }
566 
567  sz -= ret;
568  bb += ret;
569  }
570 
571  // pad to multiple of 4 bytes.
572  char *zero = (char *)"\0\0\0\0";
573  sz = seeksize(size) - size;
574  bb = zero;
575 
576  while(sz) {
577  ret = wfile.write(bb, sz);
578  if(ret < 0) {
579  return -1;
580  }
581 
582  sz -= ret;
583  bb += ret;
584  }
585 
586  return size;
587 }
588 
589 int sfs_index::getwritevsz(fs_iovec *fsiovec, int n)
590 {
591  int sz = 0;
592  for(int i=0;i<n;i++) {
593  if(fsiovec[i].filename) {
594  sz += seeksize(strlen(fsiovec[i].filename)+1);
595  sz += sizeof(SFS_File) - 4;
596  }
597 
598  sz += seeksize(fsiovec[i].len);
599  }
600  return sz;
601 }
602 
603 int sfs_index::writev(fs_iovec *fsiovec, int n)
604 {
605  return writev_sticky(fsiovec, n, NULL);
606 }
607 
608 
609 // Non-interruptable writev
610 int sfs_index::writev_call_retry(int fd, iovec *iovec, int vec)
611 {
612  if(vec > MAX_SEND_IOVECS) {
613  LOG(CRIT, "writev with too %d iovecs... max=%d",vec,MAX_SEND_IOVECS);
614  return -1;
615  }
616 
617  int len=0;
618  for(int i=0;i<vec;i++) {
619  len += iovec[i].iov_len;
620  }
621 
622  int ret = 0;
623  int retries = 0;
624  if((ret == 0) && (retries<5)) { // retry 1 time!
625  ret = ::writev(fd, iovec, vec);
626  retries++;
627  }
628 
629  if((ret==len) && (retries > 1)) {
630  LOG(U_JEFF, "successful writev took %d tries!");
631  }
632 
633  if(ret != len) {
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);
637  }
638  LOG(ERR, "socket error: ret=%d of %d in %d tries (%s)", ret, len, retries, strerror(errno));
639  return -1;
640  }
641 
642  return ret;
643 }
644 
645 
646 // Header is an optional, non-fs file header
647 // of course in stardaq, it is the iccp2k ethernet header...
648 // this is now threadsafe!
649 
650 
651 int sfs_index::writev_sticky(fs_iovec *fsiovec, int n, int *sticky)
652 {
653  iovec iovec[MAX_SEND_IOVECS];
654  char _buff[(sizeof(SFS_File) + 40)*50];
655  char *b = _buff;
656 
657  int i;
658  int vec=0;
659 
660  if(n > MAX_SEND_IOVECS) {
661  LOG(CRIT, "sending %d iovecs > than max=%d",n,MAX_SEND_IOVECS);
662  }
663 
664  // if(!writevbuff) {
665  // writevbuff = (char *)malloc(64*100);
666  // }
667 
668  // char *b = writevbuff;
669 
670  for(i=0;i<n;i++) { // each file...
671 
672  LOG(DBG, "i=%d\n",i);
673 
674  if(fsiovec[i].filename) {
675  SFS_File *file = (SFS_File *)b;
676 
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;
682  if(sticky) {
683  if(sticky[i]) {
684  file->attr |= SFS_ATTR_POPSTICKY;
685  }
686  if(sticky[i] < 0) {
687  LOG(DBG, "%d %d",sticky[i], file->sz);
688  file->sz = -(sticky[i]);
689  LOG(DBG, "Set file->sz=%d",file->sz);
690  }
691  }
692  strcpy(file->name, fsiovec[i].filename);
693 
694 
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",
698  vec,
699  fsiovec[i].filename,
700  fsiovec[i].filename,
701  iovec[vec].iov_base,
702  iovec[vec].iov_len);
703 
704 
705  vec++;
706 
707  b += file->head_sz;
708  }
709 
710  iovec[vec].iov_base = fsiovec[i].buff;
711  iovec[vec].iov_len = seeksize(fsiovec[i].len);
712 
713  LOG(DBG, "iovec[%d] name=%s 0x%x: base=0x%x len=%d",
714  vec,
715  fsiovec[vec].filename,
716  fsiovec[vec].filename,
717  iovec[vec].iov_base,
718  iovec[vec].iov_len);
719 
720  vec++;
721 
722 
723  }
724 
725  // we need this check when writing over ethernet!
726  int all_size = 0 ;
727  for(int i=0;i<vec;i++) {
728  all_size += iovec[i].iov_len ;
729  }
730 
731  // This can not be interrupted, except by hard error!
732  int ret = writev_call_retry(wfile.fd, iovec, vec);
733 
734  return ret;
735 }
736 
737 sfs_index::sfs_index() : fs_index()
738 {
739  singleDirMount = 0;
740  singleDirIttr = NULL;
741  root = NULL;
742  cw_inode = NULL;
743 
744  return;
745 }
746 
747 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
748 int sfs_index::mountSingleDirMem(char *buffer, int size, long long int offset)
749 #else
750 int sfs_index::mountSingleDirMem(char *buffer, int size, int offset)
751 #endif
752 {
753  wfile.close(); // just in case
754  oflags = O_RDONLY;
755  wfile.openmem(buffer, size);
756 
757  singleDirOffset = offset;
758  singleDirSize = size;
759  return mountSingleDir();
760 }
761 
762 // returns -1 on error
763 // returns 0 on eof
764 // returns 1 on valid dir
765 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
766 int sfs_index::mountSingleDir(char *fn, long long int offset)
767 #else
768 int sfs_index::mountSingleDir(char *fn, int offset)
769 #endif
770 {
771  LOG(DBG,"the spec is: " __DATE__ ":" __TIME__);
772 
773  // open file...
774  umount(); // just in case!
775  wfile.close(); // just in case!
776  wfile.opendisk(fn, O_RDONLY);
777  if(wfile.fd < 0) {
778  LOG(ERR, "Bad error opening %s mounting single directory (%s)",fn,strerror(errno));
779  return wfile.fd;
780  }
781  wfile.lseek(offset, SEEK_SET);
782 
783  int ret = mountSingleDir();
784  //wfile.close();
785  return ret;
786 }
787 
788 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
789 int sfs_index::getSingleDirSize(char *fn, long long int offset)
790 #else
791 int sfs_index::getSingleDirSize(char *fn, int offset)
792 #endif
793 {
794  char topdir[40];
795  int topdirlen=0;
796  topdir[0] = '\0';
797 
798 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
799  LOG(DBG, "singledirsize file=%s, offset=%lld",fn,offset);
800 #else
801  LOG(DBG, "singledirsize file=%s, offset=%d",fn,offset);
802 #endif
803 
804  wfile.close();
805  wfile.opendisk(fn, O_RDONLY);
806  if(wfile.fd < 0) return wfile.fd;
807  wfile.lseek(offset, SEEK_SET);
808 
809  int sz = 0;
810 
811  SFS_ittr *ittr = new SFS_ittr(offset);
812  if(ittr->get(&wfile) < 0) {
813  delete ittr;
814  wfile.lseek(offset,SEEK_SET);
815  return sz;
816  }
817 
818  sz += ittr->skipped_bytes;
819 
820  LOG(DBG, "partial sz=%d, skipped=%d",sz,ittr->skipped_bytes);
821 
822  while(ittr->next() >= 0) {
823 
824  if(ittr->filepos == -1) break; // EOF
825 
826  // set topdir, if not yet set...
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] == '/')) {
832  topdir[i] = '\0';
833  topdirlen = strlen(topdir);
834  break;
835  }
836  }
837  }
838 
839  LOG(DBG, "Topdir=%s sz(before)=%d",topdir,sz);
840 
841  if(memcmp(topdir, ittr->fullpath, topdirlen) != 0) {
842  break;
843  }
844 
845  sz += ittr->skipped_bytes;
846  sz += ittr->entry.head_sz;
847  int esz = (ittr->entry.sz + 3) / 4;
848  esz *= 4;
849  sz += esz;
850  }
851 
852  delete ittr;
853  wfile.close();
854 
855  LOG(DBG, "returning %d",sz);
856  return sz;
857 }
858 
859 int sfs_index::mountSingleDir() // mounts from current position of wfile...
860 {
861  if(singleDirIttr) delete singleDirIttr;
862 
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);
866  if(!wfile.wbuff) { // if a memory mount, already done...
867  singleDirOffset = offset;
868  nextSingleDirOffset = offset;
869  }
870 #else
871  int offset = wfile.lseek(0,SEEK_CUR);
872  if(!wfile.wbuff) {
873  singleDirOffset = offset;
874  nextSingleDirOffset = offset;
875  }
876 #endif
877 
878  singleDirMount = 1;
879  singleDirIttr = new SFS_ittr(offset);
880 
881  if(singleDirIttr->get(&wfile) < 0) {
882  delete singleDirIttr;
883  singleDirIttr = NULL;
884  singleDirMount = 0;
885 
886  root = alloc_inode("",0,0,0);
887  strcpy(cwd, "/");
888  index_created = 1;
889  return -1;
890  }
891 
892  if(singleDirIttr->next() < 0) {
893 
894  root = alloc_inode("",0,0,0);
895  strcpy(cwd, "/");
896  index_created = 1;
897 
898  LOG(NOTE, "Couldn't get any SFS dirs...");
899  return -1;
900  }
901 
902  return _mountNextDir();
903 }
904 
905 // returns -1 on error
906 // returns 0 on eof (no directory...)
907 // returns 1 on valid dir
908 
909 // entry point for user code
910 int sfs_index::mountNextDir()
911 {
912 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
913  singleDirOffset = nextSingleDirOffset;
914  //long long int offset = wfile.lseek(singleDirOffset,SEEK_SET);
915  wfile.lseek(singleDirOffset,SEEK_SET);
916 #else
917  //int offset = wfile.lseek(0,SEEK_CUR);
918  wfile.lseek(0,SEEK_CUR);
919  //singleDirOffset = nextSingleDirOffset;
920 #endif
921 
922  return(_mountNextDir());
923 }
924 
925 // if called from sfs_index, already have offsets set...
926 int sfs_index::_mountNextDir()
927 {
928  int files_added=0;
929 
930  if(index_created) free_inode(root);
931  index_created = 0;
932 
933  root = alloc_inode("",0,0,0);
934  strcpy(cwd, "/");
935  cw_inode = root;
936  index_created = 1;
937 
938  // eof?
939  if(singleDirIttr->filepos == -1) {
940  return 0;
941  }
942 
943  // get to a non-'/' ittr...
944  while(strcmp(singleDirIttr->fullpath,"/") == 0) {
945  if(singleDirIttr->next() < 0) {
946  LOG(DBG, "End of file/error before first directory");
947  return -1;
948  }
949  if(singleDirIttr->filepos == -1) {
950  return 0;
951  }
952  }
953 
954  // Have the first file record in place...
955  char basedir[256];
956  char currdir[256];
957  strcpy(basedir, singleDirIttr->fullpath);
958  striptofirstdir(basedir);
959 
960  for(;;) {
961 
962  files_added++;
963  addnode(singleDirIttr);
964 
965 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
966  long long int last_offset = singleDirIttr->fileoffset;
967  // long long int last_filepos = singleDirIttr->filepos;
968 #else
969  int last_offset = singleDirIttr->fileoffset;
970  int last_filepos = singleDirIttr->filepos;
971 #endif
972 
973  int last_head_sz = singleDirIttr->entry.head_sz;
974  int last_file_sz = seeksize(singleDirIttr->entry.sz);
975 
976  if(singleDirIttr->next() < 0) {
977  nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
978  return -1;
979  }
980 
981  if(singleDirIttr->filepos == -1) { // end of file...
982  // printf("next() ittr filepos = -1\n");
983  if(!wfile.wbuff) { // if a memory mount, already done...
984  singleDirSize = last_offset + last_head_sz + last_file_sz - singleDirOffset;
985  }
986  nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
987  return (files_added > 0) ? 1 : 0;
988  }
989 
990 
991  strcpy(currdir, singleDirIttr->fullpath);
992  striptofirstdir(currdir);
993 
994  //if(debug) {
995  // LOG(DBG,"basedir=%s singleDirIttr->fullpath=%s currdir=%s\n",
996  // basedir, singleDirIttr->fullpath, currdir);
997  //}
998 
999  if(strcmp(basedir, currdir) != 0) {
1000  if(!wfile.wbuff) { // if a memory mount, already done...
1001  singleDirSize = last_offset + last_head_sz + last_file_sz - singleDirOffset;
1002  }
1003  nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
1004  return (files_added > 0) ? 1 : 0;
1005  }
1006  }
1007 
1008  nextSingleDirOffset = wfile.lseek(0, SEEK_CUR);
1009  return 0;
1010 }
1011 
1012 int sfs_index::_create()
1013 {
1014  root = alloc_inode("",0,0,0);
1015  strcpy(cwd,"/");
1016  cw_inode = root;
1017 
1018  SFS_ittr ittr;
1019 
1020 
1021 
1022 
1023  if(ittr.get(&wfile) < 0) {
1024  return -1;
1025  }
1026 
1027  for(;;) {
1028 
1029  //printf("ittrnext\n");
1030  //fflush(stdout);
1031 
1032  if(ittr.next() < 0) {
1033  //printf("Error itterating...\n");
1034  //fflush(stdout);
1035  return -1;
1036  }
1037 
1038  //printf("ittrnexted\n");
1039  //fflush(stdout);
1040 
1041  if(ittr.filepos == -1) { // end of file...
1042 
1043  return 0;
1044  }
1045 
1046  //printf("addnode\n");
1047  //fflush(stdout);
1048  addnode(&ittr);
1049  //printf("addnode 2\n");
1050  //fflush(stdout);
1051  }
1052 
1053  LOG(ERR,"never happens\n");
1054  return -1;
1055 }
1056 
1057 void sfs_index::addnode(SFS_ittr *ittr)
1058 {
1059  char fullpath[256];
1060  char thispathonly[256];
1061  char *next[20];
1062 
1063 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
1064  LOG(DBG, "addnode: %s %lld %d",ittr->fullpath, ittr->fileoffset, ittr->filepos);
1065 #else
1066  LOG(DBG, "addnode: %s %d %d",ittr->fullpath, ittr->fileoffset, ittr->filepos);
1067 #endif
1068 
1069  if(ittr->entry.attr == SFS_ATTR_INVALID) return;
1070 
1071  strcpy(thispathonly, ittr->fullpath);
1072  stripfile(thispathonly);
1073 
1074  strcpy(fullpath, ittr->fullpath);
1075 
1076  next[0] = strtok_r(&fullpath[1], "/", &_strtok_static_);
1077 
1078  int nn=1;
1079  while((next[nn] = strtok_r(NULL, "/", &_strtok_static_))) nn++;
1080 
1081  fs_inode *inode = root;
1082 
1083  for(int i=0;i<nn-1;i++) {
1084  inode = add_inode(inode, next[i], 0, 0, 0);
1085  }
1086 
1087  inode = add_inode(inode, next[nn-1], ittr->fileoffset + ittr->entry.head_sz, ittr->entry.sz, ittr->entry.head_sz);
1088 }
1089 
1090 
1091 
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);
1095  return;
1096  }
1097 
1098  char fp[256];
1099  sprintf(fp,"%s%s/",path,inode->name);
1100 
1101  fs_inode *curr = inode->fchild;
1102 
1103  while(curr) {
1104  dump(fp,curr);
1105  curr = curr->next;
1106  }
1107 }
1108 
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)
1111 #else
1112  fs_inode *sfs_index::add_inode_from(fs_inode *prev, char *name, int offset, int sz, int overhead)
1113 #endif
1114 {
1115  int eq=0;
1116 
1117  fs_inode *parent = prev->parent;
1118 
1119  fs_inode *link = find_last_lesser_neighbor(prev, name, eq);
1120  if(eq == 0) return link;
1121 
1122  // if(newn < prev, have to go from start...
1123  if(!link) return add_inode(parent,name,offset,sz,overhead);
1124 
1125  fs_inode *newn = alloc_inode(name,offset,sz,overhead);
1126  if(!newn) return NULL;
1127 
1128 
1129  newn->parent = parent;
1130  newn->next = link->next;
1131  link->next = newn;
1132  return newn;
1133 }
1134 
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)
1137 #else
1138  fs_inode *sfs_index::add_inode(fs_inode *parent, char *name, int offset, int sz, int overhead)
1139 #endif
1140 {
1141  int eq=0;
1142  int first=0;
1143 
1144  fs_inode *link = find_last_lesser_child(parent, name, first, eq);
1145 
1146  if(eq == 0) return link;
1147 
1148  fs_inode *newn = alloc_inode(name,offset,sz,overhead);
1149 
1150  if(!newn) return NULL;
1151  newn->parent = parent;
1152 
1153  if(first) {
1154  newn->next = parent->fchild;
1155  parent->fchild = newn;
1156 
1157  return newn;
1158  }
1159 
1160  newn->next = link->next;
1161  link->next = newn;
1162  return newn;
1163 }
1164 
1165 fs_inode *sfs_index::find_last_lesser_neighbor(fs_inode *first, char *name, int &eq)
1166 {
1167  eq = -1;
1168  fs_inode *curr = first;
1169  if(!curr) return NULL;
1170 
1171  //printf("lln1 %s %s\n",curr->name, name);
1172  eq = mstrcmp(curr->name, name);
1173 
1174  if(eq > 0) return NULL;
1175  if(eq == 0) return curr;
1176 
1177  fs_inode *next = curr->next;
1178 
1179  while(next) {
1180  //printf("lln2 %s %s\n",next->name, name);
1181  eq = mstrcmp(next->name, name);
1182  if(eq > 0) return curr;
1183  if(eq == 0) return next;
1184  curr = next;
1185  next = curr->next;
1186  }
1187  return curr;
1188 }
1189 
1190 fs_inode *sfs_index::find_last_lesser_child(fs_inode *parent, char *name, int &first, int &eq)
1191 {
1192  first = 1;
1193  eq = -1;
1194 
1195  fs_inode *curr = parent->fchild;
1196  if(!curr) return NULL;
1197 
1198  //printf("llc1 %s %s\n",curr->name, name);
1199  eq = mstrcmp(curr->name, name);
1200 
1201  if(eq > 0) return NULL;
1202  if(eq == 0) {
1203  return curr;
1204  }
1205 
1206  first = 0;
1207 
1208  fs_inode *next = curr->next;
1209 
1210  while(next) {
1211  //printf("llc2 %s %s\n",next->name, name);
1212  eq = mstrcmp(next->name, name);
1213  if(eq > 0) return curr;
1214  if(eq == 0) return next;
1215 
1216  curr = next;
1217  next = curr->next;
1218  }
1219 
1220  return curr;
1221 }
1222 
1223 int sfs_index::getfileheadersz(char *fn)
1224 {
1225  return (sizeof(SFS_File) - 4 + seeksize(strlen(fn)+1));
1226 }
1227 
1228 
1229 int sfs_index::putfileheader(char *ptr, char *fn, int filesz, int flags)
1230 {
1231  return sfs_putfileheader(ptr,fn,filesz,flags);
1232 }
1233