StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fs_index.cxx
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <rts.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <ctype.h>
13 
14 #include <rts.h>
15 #include <rtsLog.h>
16 
17 #include "fs_index.h"
18 
19 //extern int debug;
20 
21 int wrapfile::openmem(char *buff, int size) {
22  wbuff = buff;
23  wsize = size;
24  wfpos = 0;
25  type = WRAP_MEM;
26  return 1;
27 }
28 
29 int wrapfile::opendisk(char *fn, int flags, int perms)
30 {
31 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
32  fd = open64(fn, flags, perms);
33 #else
34  fd = open(fn, flags, perms);
35 #endif
36  if(fd > 0) {
37  type = WRAP_DISK;
38  }
39  else {
40  type = 0;
41  }
42  return fd;
43 }
44 
45 int wrapfile::openfd(int fd)
46 {
47  this->fd = fd;
48  type = WRAP_DISK;
49  return fd;
50 }
51 
52 int wrapfile::read(void *buff, int sz)
53 {
54  switch(type) {
55  case WRAP_MEM:
56 
57 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
58  LOG(DBG, "read: wfpos=%lld wsize=%lld sz=%d",wfpos,wsize,sz);
59 #else
60  LOG(DBG, "read: wfpos=%d wsize=%d sz=%d",wfpos,wsize,sz);
61 #endif
62 
63  if((wfpos + sz) > wsize) { // max read is filesize...
64  sz = wsize - wfpos;
65  }
66  memcpy(buff, wbuff + wfpos, sz);
67  wfpos += sz;
68  return sz;
69 
70  case WRAP_DISK:
71  return ::read(fd, buff, sz);
72 
73  case WRAP_SOCKET:
74  return -1;
75  }
76 
77  return -1;
78 }
79 
80 int wrapfile::write(void *buff, int sz)
81 {
82  switch(type) {
83  case WRAP_MEM:
84 
85  if((wfpos + sz) > wsize) {
86  sz = wsize - wfpos;
87  }
88  memcpy(this->wbuff + wfpos, buff, sz);
89  wfpos += sz;
90  return sz;
91 
92  case WRAP_DISK:
93  case WRAP_SOCKET:
94  return ::write(fd, buff, sz);
95  }
96 
97  return -1;
98 }
99 
100 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
101 long long int wrapfile::lseek(long long int offset, int whence)
102 #else
103 int wrapfile::lseek(int offset, int whence)
104 #endif
105 {
106  switch(type) {
107 
108  case WRAP_MEM:
109  {
110  switch(whence) {
111  case SEEK_CUR:
112  wfpos += offset;
113  break;
114  case SEEK_SET:
115  wfpos = offset;
116  break;
117  }
118  if(wfpos > wsize) {
119  wfpos = wsize;
120  }
121  return wfpos;
122  }
123 
124  case WRAP_DISK:
125 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
126  return ::lseek64(fd, offset, whence);
127 #else
128  return ::lseek(fd, offset,whence);
129 #endif
130  }
131 
132  return -1;
133 }
134 
135 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
136 int wrapfile::fstat(struct stat64 *stat)
137 #else
138 int wrapfile::fstat(struct stat *stat)
139 #endif
140 {
141  stat->st_size = 0;
142 
143  switch(type) {
144  case WRAP_MEM:
145  case WRAP_SOCKET:
146  return -1;
147 
148  case WRAP_DISK:
149 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
150  return ::fstat64(fd, stat);
151 #else
152  return ::fstat(fd, stat);
153 #endif
154  }
155  return 0;
156 }
157 
158 int wrapfile::close()
159 {
160  switch(type) {
161  case WRAP_DISK:
162  case WRAP_SOCKET:
163  {
164  type = 0;
165  return ::close(fd);
166  }
167  case WRAP_MEM:
168  {
169  type = 0;
170  return 0;
171  }
172  }
173  return 0;
174 }
175 
176 
177 
178 fs_index::fs_index()
179 {
180  strcpy(cwd, "/");
181  root = NULL;
182  n_inodes = 0;
183  index_created=0;
184  cdchanged = 0;
185  writevbuff = NULL;
186 
187 }
188 
189 fs_index::~fs_index()
190 {
191  if(writevbuff) {
192  free(writevbuff);
193  }
194 }
195 
196 void fs_index::hexdump(char *buff, int sz)
197 {
198  for(int i=0;i<sz;i+=16) {
199  int k= sz-i;
200  if(k>16) k=16;
201 
202 
203  printf("0x%08x: ",i);
204 
205  for(int j=0;j<16;j++) {
206  if(j==8) printf(" ");
207  int x = buff[i+j] & 0x00ff;
208  if(j<k)
209  printf(" %02x",x);
210  else printf(" ");
211  }
212 
213  printf(" ");
214  for(int j=0;j<16;j++) {
215 
216  if(j == 8) printf(" ");
217 
218  if(j<k) {
219  if(isprint(buff[i+j]))
220  printf("%c",buff[i+j]);
221  else
222  printf(".");
223  }
224  }
225  printf("\n");
226  }
227 }
228 
229 int fs_index::mountmem(char *buffer, int sz, int flags)
230 {
231  oflags = flags;
232  wfile.openmem(buffer, sz);
233  return initmount(); // build index/file header
234 }
235 
236 // Mounts to a socket...
237 // always WRONLY!
238 // always append-like
239 // always prepends ethernet header to writes.
240 int fs_index::mount(int fd)
241 {
242  oflags = O_WRONLY;
243  wfile.openfd(fd);
244  return wfile.fd;
245 }
246 
247 // Flags currently allowed/required
248 //
249 // O_RDONLY, O_WRONLY, O_APPEND, O_CREAT
250 //
251 int fs_index::mount(char *filename, int flags, int perms)
252 {
253  oflags = flags;
254  wfile.opendisk(filename,flags,perms);
255 
256  if(wfile.fd < 0) return wfile.fd;
257 
258  return initmount(); // build index/file header
259 }
260 
261 int fs_index::mount(int ip, int port)
262 {
263  int fd ;
264  int ret;
265  int optval ;
266  sockaddr_in addr ;
267 
268  errno = 0 ;
269  fd = socket(AF_INET, SOCK_STREAM, 0) ;
270  if(fd < 0) {
271 
272  return -1 ;
273  }
274 
275  optval = 1 ;
276  setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) ;
277  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) ;
278 
279  memset((char *)&addr,0,sizeof(addr)) ;
280  addr.sin_family = AF_INET ;
281  addr.sin_port = htons(port) ;
282  addr.sin_addr.s_addr = htonl(ip) ;
283 
284  errno = 0 ;
285  ret = connect(fd, (sockaddr *)&addr,sizeof(addr)) ;
286  if(ret < 0) {
287 
288  return -1 ;
289  }
290 
291  optval = 64*1024*1024 ;
292  for(;;) {
293  ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&optval, sizeof(optval)) ;
294  if(ret==0) break ;
295  optval /= 2 ;
296  }
297 
298  // check
299  int new_val ;
300  socklen_t new_val_len = sizeof(new_val) ;
301  ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &new_val, &new_val_len) ;
302 
303  LOG(NOTE,"mount: IP 0x%08X:%d claims %d buffer bytes, reports %d (%d)",ip,port,optval,new_val,ret) ;
304 
305 
306  return mount(fd) ;
307 
308 
309 }
310 
311 int fs_index::initmount()
312 {
313  int ret;
314 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
315  struct stat64 stat;
316 #else
317  struct stat stat;
318 #endif
319 
320  strcpy(cwd, "/");
321  root = NULL;
322  n_inodes = 0;
323  index_created=0;
324 
325 
326  if(oflags & O_WRONLY) { // filedescriptor
327  wfile.fstat(&stat);
328 
329  LOG(TERR,"stat.st_size %d",stat.st_size) ;
330 
331  if(stat.st_size > 0) {
332  if(!(oflags & O_APPEND)) { // if not append do not allow...
333  wfile.close();
334  LOG(ERR,"no APPEND") ;
335  return -1;
336  }
337  }
338  else { // writing file, but already exists...
339  ret = writeFsHeader();
340  if(ret < 0) {
341  LOG(ERR,"writeFsHeader %d",ret) ;
342  return ret;
343  }
344  }
345  }
346  else { // O_RDONLY = 0
347  ret = _create();
348 
349 
350  if(ret < 0) {
351  LOG(ERR,"_create() %d",ret) ;
352  return ret;
353  }
354  index_created = 1;
355  }
356  return 0;
357 }
358 
359 void fs_index::getFullPath(char *fullpath, const char *name)
360 {
361  if(name[0] == '/') {
362  strcpy(fullpath,name);
363  }
364  else {
365  strcpy(fullpath,cwd);
366  int n = strlen(fullpath)-1;
367  if(fullpath[n] != '/') strcat(fullpath, "/");
368  strcat(fullpath,name);
369  }
370 }
371 
372 fs_inode *fs_index::find_child(fs_inode *parent, char *name) {
373  fs_inode *next = parent->fchild;
374  while(next) {
375  //printf("finding child looking for %s in %s\n",name,next->name);
376  if(strcmp(name, next->name) == 0) return next;
377  next = next->next;
378  }
379  return NULL;
380 }
381 
382 
383 int fs_index::cd(char *name)
384 {
385  char fullpath[256];
386  getFullPath(fullpath,name);
387  cdchanged = 1;
388 
389  if(oflags & O_WRONLY) { // writeonly, simply set name
390  strcpy(cwd, fullpath);
391  return 0;
392  }
393 
394  // otherwise, make sure directory is valid & also set cw_inode.
395  if(!index_created) return -1;
396 
397  char tokes[256];
398  strcpy(tokes,fullpath);
399 
400  char *token = strtok_r(tokes,"/", &_strtok_static_);
401  fs_inode *node = root;
402 
403  while(token) {
404  fs_inode *newn = find_child(node, token);
405  if(!newn) return -1;
406  node = newn;
407  token = strtok_r(NULL, "/", &_strtok_static_);
408  }
409 
410  if(!node->fchild) return -1;
411 
412  cw_inode = node;
413  strcpy(cwd,fullpath);
414  return 0;
415 }
416 
417 
418 void fs_index::free_inode(fs_inode *inode)
419 {
420  //printf("free\n");
421  if(inode->fchild) free_inode(inode->fchild);
422 
423  if(inode->next) free_inode(inode->next);
424 
425  n_inodes--;
426  free(inode->name);
427  free(inode);
428 }
429 
430 void fs_index::umount()
431 {
432  if(index_created)
433  free_inode(root);
434 
435  wfile.close();
436  index_created = 0;
437 }
438 
439 fs_dirent *fs_index::readdirent(const char *dir, fs_dirent *ent)
440 {
441  if(ent == NULL) {
442  ent = &_readdirent_static_;
443  }
444 
445  if(!index_created) return NULL;
446 
447  char fullname[256];
448  getFullPath(fullname,dir);
449  strcpy(ent->full_name, fullname);
450 
451  fs_inode *node = root;
452  char *name = strtok_r(fullname, "/", &_strtok_static_);
453 
454  while(name) {
455  node = find_child(node, name);
456  if(!node) return NULL;
457 
458  name = strtok_r(NULL, "/", &_strtok_static_);
459  }
460 
461 
462  strcpy(ent->d_name, node->name);
463 
464  ent->sz = node->sz;
465  ent->offset = node->offset;
466  if(node->fchild) ent->has_child = 1;
467  else ent->has_child = 0;
468  // ent.token = node->token;
469  //ent.format_ver = node->format_ver;
470  //ent.format_number = node->format_number;
471  ent->swap = node->swap;
472  return ent;
473 }
474 
475 
476 fs_dir *fs_index::opendir(const char *dir)
477 {
478  if(!index_created) return NULL;
479 
480  char fullpathc[256];
481  char fullpath[256];
482 
483  getFullPath(fullpath, dir);
484  if(fullpath[strlen(fullpath)-1] != '/') strcat(fullpath, "/");
485  strcpy(fullpathc, fullpath);
486 
487  //if(debug) printf("opendir: path : (%s)\n",fullpathc);
488 
489  fs_inode *node = root;
490 
491  char *name = strtok_r(fullpath, "/", &_strtok_static_);
492  while(name) {
493 
494  //if(debug) printf("opendir name = %s\n",name);
495  //fflush(stdout);
496 
497  node = find_child(node,name);
498  if(!node) return NULL;
499 
500  name = strtok_r(NULL, "/", &_strtok_static_);
501  }
502 
503  fs_dir *ret = (fs_dir *)malloc(sizeof(fs_dir));
504  if(!ret) return NULL;
505 
506  strcpy(ret->full_name, fullpathc);
507  ret->inode = node;
508  ret->currchild = NULL;
509 
510  LOG(DBG, "returning dir 0x%x",ret);
511  return ret;
512 }
513 
514 void fs_index::closedir(fs_dir *dir)
515 {
516  if(!index_created) return;
517  free(dir);
518 }
519 
520 
521 fs_dirent *fs_index::readdir(fs_dir *dir, fs_dirent *ent)
522 {
523  if(!index_created) return NULL;
524 
525  fs_inode *node = dir->currchild;
526 
527  if(!node)
528  node = dir->inode->fchild;
529  else
530  node = node->next;
531 
532  if(!node) return NULL;
533 
534  dir->currchild = node;
535 
536  if(ent == NULL) {
537  ent = &_readdirent_static_;
538  }
539 
540  strcpy(ent->d_name, node->name);
541 
542  strcpy(ent->full_name, dir->full_name);
543  strcat(ent->full_name, node->name);
544 
545  ent->sz = node->sz;
546  ent->offset = node->offset;
547  if(node->fchild) ent->has_child = 1;
548  else ent->has_child = 0;
549 
550  ent->swap = node->swap;
551 
552  return ent;
553 }
554 
555 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
556 fs_inode *fs_index::alloc_inode(const char *name, long long int off, int sz, int overhead)
557 #else
558  fs_inode *fs_index::alloc_inode(const char *name, int off, int sz, int overhead)
559 #endif
560 {
561  //printf("alloc\n");
562  n_inodes++;
563  fs_inode *n = (fs_inode *)malloc(sizeof(fs_inode));
564  if(!n) return NULL ;
565 
566  n->parent = NULL;
567  n->fchild = NULL;
568  n->lchild = NULL;
569  n->prev = NULL;
570  n->next = NULL;
571  n->offset = off;
572  n->overhead = overhead;
573  n->sz = sz;
574  n->name = (char *)malloc(strlen(name)+1);
575  if(!n->name) {
576  free(n) ;
577  return NULL;
578  }
579 
580  strcpy(n->name,name);
581 
582  return n;
583 }
584 
585 int fs_index::fileSize(const char *fn)
586 {
587  if(!index_created) return -1;
588 
589  fs_dirent *entry = readdirent(fn);
590  if(!entry) {
591  //printf("Can't find file %s\n",fn);
592  return -1;
593  }
594 
595  return entry->sz;
596 }
597 
598 int fs_index::read(const char *fn, char *buff, int maxsize)
599 {
600  if(!index_created) return -1;
601 
602  fs_dirent *entry = readdirent(fn);
603  if(!entry) {
604  //printf("Can't find file %s\n",fn);
605  return -1;
606  }
607 
608  if(entry->sz == 0) {
609  LOG(NOTE,"%s has no data...",fn);
610  return 0;
611  }
612 
613  if(entry->sz > maxsize) {
614  return -1;
615  }
616 
617  int ret = wfile.lseek(entry->offset, SEEK_SET);
618  if(ret != entry->offset) {
619  LOG(ERR,"Invalid seek %d vs %d\n",ret,entry->offset);
620  return -1;
621  }
622 
623  ret = wfile.read(buff, entry->sz);
624  if(ret != entry->sz) {
625  LOG(ERR,"Error reading file %d vs %d\n", ret, entry->sz);
626  return -1;
627  }
628  return ret;
629 }
630 
631 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
632 long long int fs_index::mountsz()
633 #else
634 int fs_index::mountsz()
635 #endif
636 {
637 
638  if(oflags & O_WRONLY) {
639  if(wfile.type == WRAP_MEM) {
640  return wfile.wfpos;
641  }
642  }
643 
644 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
645  struct stat64 stat;
646 #else
647  struct stat stat;
648 #endif
649 
650  wfile.fstat(&stat);
651  return stat.st_size;
652 }
653 
654 int fs_index::mem_ls(fs_filelist *filelist, int recurse, fs_dir *dir)
655 {
656  int ret;
657 
658  fs_dirent *entry;
659  while((entry = readdir(dir))) {
660  if(filelist->n >= filelist->max) return 0;
661 
662  if(!entry->has_child) { // only save files, not dirs
663  strcpy(filelist->filename[filelist->n], entry->full_name);
664  filelist->n++;
665  }
666 
667  if(recurse & entry->has_child) {
668  fs_dir *ndir = opendir(entry->full_name);
669  ret = mem_ls(filelist, recurse, ndir);
670  closedir(ndir);
671  if(ret == 0) return 0;
672  }
673  }
674  return 1;
675 }