00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <stdlib.h>
00004 #include <rts.h>
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <fcntl.h>
00008 #include <unistd.h>
00009 #include <errno.h>
00010 #include <sys/socket.h>
00011 #include <netinet/in.h>
00012 #include <ctype.h>
00013
00014 #include <rts.h>
00015 #include <rtsLog.h>
00016
00017 #include "fs_index.h"
00018
00019
00020
00021 int wrapfile::openmem(char *buff, int size) {
00022 wbuff = buff;
00023 wsize = size;
00024 wfpos = 0;
00025 type = WRAP_MEM;
00026 return 1;
00027 }
00028
00029 int wrapfile::opendisk(char *fn, int flags, int perms)
00030 {
00031 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00032 fd = open64(fn, flags, perms);
00033 #else
00034 fd = open(fn, flags, perms);
00035 #endif
00036 if(fd > 0) {
00037 type = WRAP_DISK;
00038 }
00039 else {
00040 type = 0;
00041 }
00042 return fd;
00043 }
00044
00045 int wrapfile::openfd(int fd)
00046 {
00047 this->fd = fd;
00048 type = WRAP_DISK;
00049 return fd;
00050 }
00051
00052 int wrapfile::read(void *buff, int sz)
00053 {
00054 switch(type) {
00055 case WRAP_MEM:
00056
00057 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00058 LOG(DBG, "read: wfpos=%lld wsize=%lld sz=%d",wfpos,wsize,sz);
00059 #else
00060 LOG(DBG, "read: wfpos=%d wsize=%d sz=%d",wfpos,wsize,sz);
00061 #endif
00062
00063 if((wfpos + sz) > wsize) {
00064 sz = wsize - wfpos;
00065 }
00066 memcpy(buff, wbuff + wfpos, sz);
00067 wfpos += sz;
00068 return sz;
00069
00070 case WRAP_DISK:
00071 return ::read(fd, buff, sz);
00072
00073 case WRAP_SOCKET:
00074 return -1;
00075 }
00076
00077 return -1;
00078 }
00079
00080 int wrapfile::write(void *buff, int sz)
00081 {
00082 switch(type) {
00083 case WRAP_MEM:
00084
00085 if((wfpos + sz) > wsize) {
00086 sz = wsize - wfpos;
00087 }
00088 memcpy(this->wbuff + wfpos, buff, sz);
00089 wfpos += sz;
00090 return sz;
00091
00092 case WRAP_DISK:
00093 case WRAP_SOCKET:
00094 return ::write(fd, buff, sz);
00095 }
00096
00097 return -1;
00098 }
00099
00100 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00101 long long int wrapfile::lseek(long long int offset, int whence)
00102 #else
00103 int wrapfile::lseek(int offset, int whence)
00104 #endif
00105 {
00106 switch(type) {
00107
00108 case WRAP_MEM:
00109 {
00110 switch(whence) {
00111 case SEEK_CUR:
00112 wfpos += offset;
00113 break;
00114 case SEEK_SET:
00115 wfpos = offset;
00116 break;
00117 }
00118 if(wfpos > wsize) {
00119 wfpos = wsize;
00120 }
00121 return wfpos;
00122 }
00123
00124 case WRAP_DISK:
00125 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00126 return ::lseek64(fd, offset, whence);
00127 #else
00128 return ::lseek(fd, offset,whence);
00129 #endif
00130 }
00131
00132 return -1;
00133 }
00134
00135 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00136 int wrapfile::fstat(struct stat64 *stat)
00137 #else
00138 int wrapfile::fstat(struct stat *stat)
00139 #endif
00140 {
00141 stat->st_size = 0;
00142
00143 switch(type) {
00144 case WRAP_MEM:
00145 case WRAP_SOCKET:
00146 return -1;
00147
00148 case WRAP_DISK:
00149 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00150 return ::fstat64(fd, stat);
00151 #else
00152 return ::fstat(fd, stat);
00153 #endif
00154 }
00155 return 0;
00156 }
00157
00158 int wrapfile::close()
00159 {
00160 switch(type) {
00161 case WRAP_DISK:
00162 case WRAP_SOCKET:
00163 {
00164 type = 0;
00165 return ::close(fd);
00166 }
00167 case WRAP_MEM:
00168 {
00169 type = 0;
00170 return 0;
00171 }
00172 }
00173 return 0;
00174 }
00175
00176
00177
00178 fs_index::fs_index()
00179 {
00180 strcpy(cwd, "/");
00181 root = NULL;
00182 n_inodes = 0;
00183 index_created=0;
00184 cdchanged = 0;
00185 writevbuff = NULL;
00186
00187 }
00188
00189 fs_index::~fs_index()
00190 {
00191 if(writevbuff) {
00192 free(writevbuff);
00193 }
00194 }
00195
00196 void fs_index::hexdump(char *buff, int sz)
00197 {
00198 for(int i=0;i<sz;i+=16) {
00199 int k= sz-i;
00200 if(k>16) k=16;
00201
00202
00203 printf("0x%08x: ",i);
00204
00205 for(int j=0;j<16;j++) {
00206 if(j==8) printf(" ");
00207 int x = buff[i+j] & 0x00ff;
00208 if(j<k)
00209 printf(" %02x",x);
00210 else printf(" ");
00211 }
00212
00213 printf(" ");
00214 for(int j=0;j<16;j++) {
00215
00216 if(j == 8) printf(" ");
00217
00218 if(j<k) {
00219 if(isprint(buff[i+j]))
00220 printf("%c",buff[i+j]);
00221 else
00222 printf(".");
00223 }
00224 }
00225 printf("\n");
00226 }
00227 }
00228
00229 int fs_index::mountmem(char *buffer, int sz, int flags)
00230 {
00231 oflags = flags;
00232 wfile.openmem(buffer, sz);
00233 return initmount();
00234 }
00235
00236
00237
00238
00239
00240 int fs_index::mount(int fd)
00241 {
00242 oflags = O_WRONLY;
00243 wfile.openfd(fd);
00244 return wfile.fd;
00245 }
00246
00247
00248
00249
00250
00251 int fs_index::mount(char *filename, int flags, int perms)
00252 {
00253 oflags = flags;
00254 wfile.opendisk(filename,flags,perms);
00255
00256 if(wfile.fd < 0) return wfile.fd;
00257
00258 return initmount();
00259 }
00260
00261 int fs_index::mount(int ip, int port)
00262 {
00263 int fd ;
00264 int ret;
00265 int optval ;
00266 sockaddr_in addr ;
00267
00268 errno = 0 ;
00269 fd = socket(AF_INET, SOCK_STREAM, 0) ;
00270 if(fd < 0) {
00271
00272 return -1 ;
00273 }
00274
00275 optval = 1 ;
00276 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) ;
00277 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) ;
00278
00279 memset((char *)&addr,0,sizeof(addr)) ;
00280 addr.sin_family = AF_INET ;
00281 addr.sin_port = htons(port) ;
00282 addr.sin_addr.s_addr = htonl(ip) ;
00283
00284 errno = 0 ;
00285 ret = connect(fd, (sockaddr *)&addr,sizeof(addr)) ;
00286 if(ret < 0) {
00287
00288 return -1 ;
00289 }
00290
00291 optval = 64*1024*1024 ;
00292 for(;;) {
00293 ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&optval, sizeof(optval)) ;
00294 if(ret==0) break ;
00295 optval /= 2 ;
00296 }
00297
00298
00299 int new_val ;
00300 socklen_t new_val_len = sizeof(new_val) ;
00301 ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &new_val, &new_val_len) ;
00302
00303 LOG(NOTE,"mount: IP 0x%08X:%d claims %d buffer bytes, reports %d (%d)",ip,port,optval,new_val,ret) ;
00304
00305
00306 return mount(fd) ;
00307
00308
00309 }
00310
00311 int fs_index::initmount()
00312 {
00313 int ret;
00314 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00315 struct stat64 stat;
00316 #else
00317 struct stat stat;
00318 #endif
00319
00320 strcpy(cwd, "/");
00321 root = NULL;
00322 n_inodes = 0;
00323 index_created=0;
00324
00325
00326 if(oflags & O_WRONLY) {
00327 wfile.fstat(&stat);
00328
00329 if(stat.st_size > 0) {
00330 if(!(oflags & O_APPEND)) {
00331 wfile.close();
00332 return -1;
00333 }
00334 }
00335 else {
00336 ret = writeFsHeader();
00337 if(ret < 0) return ret;
00338 }
00339 }
00340 else {
00341 ret = _create();
00342
00343 if(ret < 0) return ret;
00344 index_created = 1;
00345 }
00346 return 0;
00347 }
00348
00349 void fs_index::getFullPath(char *fullpath, char *name)
00350 {
00351 if(name[0] == '/') {
00352 strcpy(fullpath,name);
00353 }
00354 else {
00355 strcpy(fullpath,cwd);
00356 int n = strlen(fullpath)-1;
00357 if(fullpath[n] != '/') strcat(fullpath, "/");
00358 strcat(fullpath,name);
00359 }
00360 }
00361
00362 fs_inode *fs_index::find_child(fs_inode *parent, char *name) {
00363 fs_inode *next = parent->fchild;
00364 while(next) {
00365
00366 if(strcmp(name, next->name) == 0) return next;
00367 next = next->next;
00368 }
00369 return NULL;
00370 }
00371
00372
00373 int fs_index::cd(char *name)
00374 {
00375 char fullpath[256];
00376 getFullPath(fullpath,name);
00377 cdchanged = 1;
00378
00379 if(oflags & O_WRONLY) {
00380 strcpy(cwd, fullpath);
00381 return 0;
00382 }
00383
00384
00385 if(!index_created) return -1;
00386
00387 char tokes[256];
00388 strcpy(tokes,fullpath);
00389
00390 char *token = strtok(tokes,"/");
00391 fs_inode *node = root;
00392
00393 while(token) {
00394 fs_inode *newn = find_child(node, token);
00395 if(!newn) return -1;
00396 node = newn;
00397 token = strtok(NULL, "/");
00398 }
00399
00400 if(!node->fchild) return -1;
00401
00402 cw_inode = node;
00403 strcpy(cwd,fullpath);
00404 return 0;
00405 }
00406
00407
00408 void fs_index::free_inode(fs_inode *inode)
00409 {
00410 if(inode->fchild) free_inode(inode->fchild);
00411
00412 if(inode->next) free_inode(inode->next);
00413
00414 n_inodes--;
00415 free(inode->name);
00416 free(inode);
00417 }
00418
00419 void fs_index::umount()
00420 {
00421 if(index_created)
00422 free_inode(root);
00423
00424 wfile.close();
00425 index_created = 0;
00426 }
00427
00428 fs_dirent *fs_index::readdirent(char *dir)
00429 {
00430 fs_dirent *ent = &_readdirent_static_;
00431
00432 if(!index_created) return NULL;
00433
00434 char fullname[256];
00435 getFullPath(fullname,dir);
00436 strcpy(ent->full_name, fullname);
00437
00438 fs_inode *node = root;
00439 char *name = strtok(fullname, "/");
00440
00441 while(name) {
00442 node = find_child(node, name);
00443 if(!node) return NULL;
00444
00445 name = strtok(NULL, "/");
00446 }
00447
00448
00449 strcpy(ent->d_name, node->name);
00450
00451 ent->sz = node->sz;
00452 ent->offset = node->offset;
00453 if(node->fchild) ent->has_child = 1;
00454 else ent->has_child = 0;
00455
00456
00457
00458 ent->swap = node->swap;
00459 return ent;
00460 }
00461
00462
00463 fs_dir *fs_index::opendir(char *dir)
00464 {
00465 if(!index_created) return NULL;
00466
00467 char fullpathc[256];
00468 char fullpath[256];
00469
00470 getFullPath(fullpath, dir);
00471 if(fullpath[strlen(fullpath)-1] != '/') strcat(fullpath, "/");
00472 strcpy(fullpathc, fullpath);
00473
00474
00475
00476 fs_inode *node = root;
00477
00478 char *name = strtok(fullpath, "/");
00479 while(name) {
00480
00481
00482
00483
00484 node = find_child(node,name);
00485 if(!node) return NULL;
00486
00487 name = strtok(NULL, "/");
00488 }
00489
00490 fs_dir *ret = (fs_dir *)malloc(sizeof(fs_dir));
00491 if(!ret) return NULL;
00492
00493 strcpy(ret->full_name, fullpathc);
00494 ret->inode = node;
00495 ret->currchild = NULL;
00496
00497 LOG(DBG, "returning dir 0x%x",ret);
00498 return ret;
00499 }
00500
00501 void fs_index::closedir(fs_dir *dir)
00502 {
00503 if(!index_created) return;
00504 free(dir);
00505 }
00506
00507
00508 fs_dirent *fs_index::readdir(fs_dir *dir)
00509 {
00510 if(!index_created) return NULL;
00511
00512 fs_inode *node = dir->currchild;
00513
00514 if(!node)
00515 node = dir->inode->fchild;
00516 else
00517 node = node->next;
00518
00519 if(!node) return NULL;
00520
00521 dir->currchild = node;
00522
00523 fs_dirent *ent = &_readdirent_static_;
00524
00525 strcpy(ent->d_name, node->name);
00526
00527 strcpy(ent->full_name, dir->full_name);
00528 strcat(ent->full_name, node->name);
00529
00530 ent->sz = node->sz;
00531 ent->offset = node->offset;
00532 if(node->fchild) ent->has_child = 1;
00533 else ent->has_child = 0;
00534
00535 ent->swap = node->swap;
00536
00537 return ent;
00538 }
00539
00540 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00541 fs_inode *fs_index::alloc_inode(char *name, long long int off, int sz, int overhead)
00542 #else
00543 fs_inode *fs_index::alloc_inode(char *name, int off, int sz, int overhead)
00544 #endif
00545 {
00546 n_inodes++;
00547 fs_inode *n = (fs_inode *)malloc(sizeof(fs_inode));
00548 n->parent = NULL;
00549 n->fchild = NULL;
00550 n->lchild = NULL;
00551 n->prev = NULL;
00552 n->next = NULL;
00553 n->offset = off;
00554 n->overhead = overhead;
00555 n->sz = sz;
00556 n->name = (char *)malloc(strlen(name)+1);
00557 if(!n->name) return NULL;
00558 strcpy(n->name,name);
00559
00560 return n;
00561 }
00562
00563 int fs_index::fileSize(char *fn)
00564 {
00565 if(!index_created) return -1;
00566
00567 fs_dirent *entry = readdirent(fn);
00568 if(!entry) {
00569
00570 return -1;
00571 }
00572
00573 return entry->sz;
00574 }
00575
00576 int fs_index::read(char *fn, char *buff, int maxsize)
00577 {
00578 if(!index_created) return -1;
00579
00580 fs_dirent *entry = readdirent(fn);
00581 if(!entry) {
00582
00583 return -1;
00584 }
00585
00586 if(entry->sz == 0) {
00587 LOG(NOTE,"%s has no data...",fn);
00588 return 0;
00589 }
00590
00591 if(entry->sz > maxsize) {
00592 return -1;
00593 }
00594
00595 int ret = wfile.lseek(entry->offset, SEEK_SET);
00596 if(ret != entry->offset) {
00597 LOG(ERR,"Invalid seek %d vs %d\n",ret,entry->offset);
00598 return -1;
00599 }
00600
00601 ret = wfile.read(buff, entry->sz);
00602 if(ret != entry->sz) {
00603 LOG(ERR,"Error reading file %d vs %d\n", ret, entry->sz);
00604 return -1;
00605 }
00606 return ret;
00607 }
00608
00609 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00610 long long int fs_index::mountsz()
00611 #else
00612 int fs_index::mountsz()
00613 #endif
00614 {
00615
00616 if(oflags & O_WRONLY) {
00617 if(wfile.type == WRAP_MEM) {
00618 return wfile.wfpos;
00619 }
00620 }
00621
00622 #if defined(__USE_LARGEFILE64) || defined(_LARGEFILE64_SOURCE)
00623 struct stat64 stat;
00624 #else
00625 struct stat stat;
00626 #endif
00627
00628 wfile.fstat(&stat);
00629 return stat.st_size;
00630 }
00631
00632 int fs_index::mem_ls(fs_filelist *filelist, int recurse, fs_dir *dir)
00633 {
00634 int ret;
00635
00636 fs_dirent *entry;
00637 while((entry = readdir(dir))) {
00638 if(filelist->n >= filelist->max) return 0;
00639
00640 if(!entry->has_child) {
00641 strcpy(filelist->filename[filelist->n], entry->full_name);
00642 filelist->n++;
00643 }
00644
00645 if(recurse & entry->has_child) {
00646 fs_dir *ndir = opendir(entry->full_name);
00647 ret = mem_ls(filelist, recurse, ndir);
00648 closedir(ndir);
00649 if(ret == 0) return 0;
00650 }
00651 }
00652 return 1;
00653 }