int isofs_open(const char *path) { struct iso_inode *inode = isofs_lookup(path); if(!inode) { fprintf(stderr,"no such file or directory found \n"); return -ENOENT; } if(ISO_FLAGS_DIR(inode->record->flags)) { fprintf(stderr,"not a regular file may be a directory\n"); return -EINVAL; } return 0; }
int isofs_read(const char *path,char *read_buf,size_t size,off_t offset) { log_msg("i am now in read_block\n"); struct iso_inode *inode = isofs_lookup(path); if(!inode) { fprintf(stderr,"no such file or directory found \n"); return -ENOENT; } if(ISO_FLAGS_DIR(inode->record->flags)) { fprintf(stderr,"not a regular file may be a directory\n"); return -EINVAL; } int data_size = gvar->data_size; struct iso_directory_record *dr = inode->record; int start_block = isonum_733(dr->extent); int end_block = isonum_733(dr->size)/data_size; int in_block = end_block - start_block ; int offset_block_start = offset / data_size; int offset_block_end = (offset + size) / data_size; int offset_shift_point = (offset%data_size); int block = offset_block_start + start_block; log_msg("malloced .....\n"); char *buf = (char *) malloc(data_size); if(!buf) { perror("isofs_read:cannot malloc"); exit(0); } int total = 0; int count = 0; int len; do{ log_msg("read_raw_block.....\n"); len = read_raw_block(block,buf); log_msg("buffer is now ....%s\n",buf); memcpy(read_buf+count*data_size,buf+offset_shift_point,data_size); log_msg("the read_buf is %s",read_buf); offset_shift_point = 0; count ++; block++; total += len; }while(count <= in_block); return total; }
int fs_real_open(const char *path) { char ppath[FS_MAXPATH]; char *newpath=ppath; fusioniso_data *data=fusioniso_get_data(); FSDEBUG("path=%s",path); isofs_inode *inode = fs_lookup(path); if (inode == NULL) { struct stat v_stbuf; if (fs_home_stat(path,&newpath,&v_stbuf) == 0) { if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL; return 0; } if (data->union_mounting && stat(path,&v_stbuf)==0) { if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL; return 0; } FSDEBUG("know nothing about %s",path); return -ENOENT; } if (ISO_FLAGS_DIR(inode->record->flags)) { FSDEBUG("%s not a file",path); return -EINVAL; } if (ISO_FLAGS_HIDDEN(inode->record->flags)) { FSDEBUG("%s is a hidden file",path); // return -EPERM; } return 0; }
int fs_real_opendir(const char *path) { char ppath[FS_MAXPATH]; char *newpath=ppath; fusioniso_data *data=fusioniso_get_data(); FSDEBUG("path=%s", path); isofs_inode *inode = fs_lookup(path); if (inode==NULL) { struct stat v_stbuf; if (fs_home_stat(path,&newpath,&v_stbuf) == 0) { if (!S_ISDIR(v_stbuf.st_mode)) return -ENOENT; return 0; } if (data->union_mounting && lstat(path,&v_stbuf)==0) { if (!S_ISDIR(v_stbuf.st_mode)) return -ENOENT; return 0; } FSDEBUG("know nothing about %s",path); return -ENOENT; } if (!ISO_FLAGS_DIR(inode->record->flags)) { FSDEBUG("%s not a dir",path); return -ENOTDIR; } return 0; }
int fs_real_read(const char *path, char *out_buf, size_t size, off_t offset) { char ppath[FS_MAXPATH]; char *newpath=ppath; fusioniso_data *data=fusioniso_get_data(); FSDEBUG("path=%s",path); isofs_inode *inode = fs_lookup(path); if (inode == NULL) { struct stat v_stbuf; int v_file; ssize_t v_count; // Use our own loader if (data->glibc && strcmp(path,"/lib/ld-linux.so.2")==0) { v_file = open("/lib/ld-klik2.so.2", O_RDONLY); if (v_file == -1) return -EACCES; lseek(v_file, offset, SEEK_SET); v_count = read(v_file, out_buf, size); close(v_file); return v_count; } if (fs_home_stat(path,&newpath,&v_stbuf) == 0) { if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL; v_file = open(newpath, O_RDONLY); if (v_file == -1) return -EACCES; lseek(v_file, offset, SEEK_SET); v_count = read(v_file, out_buf, size); close(v_file); if (data->glibc && offset==0 && v_count>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC) { fs_rewrite_loader(out_buf, v_count); } return v_count; } if (data->union_mounting && stat(path,&v_stbuf)==0) { if (!S_ISREG(v_stbuf.st_mode)) return -EINVAL; v_file = open(path, O_RDONLY); if (v_file == -1) return -EACCES; lseek(v_file, offset, SEEK_SET); v_count = read(v_file, out_buf, size); close(v_file); if (data->glibc && offset==0 && v_count>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC) { fs_rewrite_loader(out_buf, v_count); } return v_count; } FSDEBUG("know nothing about %s",path); return -ENOENT; } struct iso_directory_record *record = inode->record; if (ISO_FLAGS_DIR(record->flags)) { FSDEBUG("%s not a file",path); return -EISDIR; } if (ISO_FLAGS_HIDDEN(record->flags)) { FSDEBUG("%s is a hidden file",path); // return -EPERM; } if (inode->ZF) // this file is compressed, handle it specially { int v_count = isofs_real_read_zf(inode, out_buf, size, offset); if (v_count<0) return -EINVAL; if (data->glibc && offset==0 && v_count>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC) { fs_rewrite_loader(out_buf, v_count); } return v_count; } size_t fsize = isonum_733(record->size); if (offset + size > fsize) { size = fsize - offset; } if (size < 1) { return 0; } int start_block = isonum_733(record->extent); if (start_block == 0) // empty file { return 0; } int start = offset / data->isofs->data_size; int end = (offset + size) / data->isofs->data_size; int shift = offset % data->isofs->data_size; int block = start_block + start; // printf("read: path %s, size %d, offset %d, fsize %d, start %d, end %d, shift %d\n", // path, size, (int) offset, fsize, start, end, shift); char *buf = (char *) malloc(data->isofs->data_size); if (!buf) { FSDEBUG("can\'t malloc: %s",strerror(errno)); return -ENOMEM; } int i; size_t total_size = 0; size_t size_left = size; int count = 0; for (i=start; i<=end; i++) { int len = isofs_read_raw_block(block, buf, data->isofs); if (len < 0) { free(buf); return len; } // printf("read: block %d, len %d, size_left %d\n", block, len, size_left); if (len > size_left) { len = size_left; } total_size += len; memcpy(out_buf + count * data->isofs->data_size, buf + shift, len - shift); count++; shift = 0; size_left -= len; block++; } free(buf); if (data->glibc && offset==0 && total_size>18 && memcmp(out_buf, ELFMAG, SELFMAG)==0 && out_buf[16]==ET_EXEC) { fs_rewrite_loader(out_buf, total_size); } return total_size; }
int fs_real_readdir(int real, const char *path, void *filler_buf, fs_dir_fill_t filler) { char ppath[FS_MAXPATH]; char v_chemin[2048]; char *newpath=ppath; struct dirent *v_dirent; struct stat v_stbuf; int retval1, retval2; DIR *v_dir; char *buf = NULL; fusioniso_data *data=fusioniso_get_data(); if (path[0] == '\0') { FSDEBUG("attempt to read empty path name"); return -EINVAL; } FSDEBUG("path=%s flag=%d",path,real); isofs_inode *current_inode = fs_lookup(path); isofs_inode *inode2 = NULL; if (!data->union_mounting && current_inode==NULL) { FSDEBUG("know nothing about %s",path); return -ENOENT; } retval2 = fs_home(path,&newpath); if (current_inode == NULL) { if (real && retval2!=1) goto out_readdir; if (!real && retval2!=1) { g_hash_table_insert(data->real_lookup_table, g_strdup(path), "real"); return 0; } if (data->union_mounting) { retval1 = stat(path, &v_stbuf); if (real && retval1==0) goto out_readdir; if (!real && retval1==0) { g_hash_table_insert(data->real_lookup_table, g_strdup(path), "real"); return 0; } } if (!real) FSDEBUG("know nothing about %s",path); return -ENOENT; } struct iso_directory_record *current = current_inode->record; if (!ISO_FLAGS_DIR(current->flags)) { FSDEBUG("%s not a dir", path); return -ENOTDIR; } size_t current_size = isonum_733(current->size); int block = isonum_733(current->extent); buf = (char *) malloc(data->isofs->data_size); if (!buf) { FSDEBUG("can\'t malloc: %s",strerror(errno)); return -ENOMEM; } int rc; // printf("path %s, current_size %d, block %d\n", path, current_size, block); size_t total_size = 0; int count = 1; int block_count = 0; off_t boff = 0; while (total_size <= current_size - sizeof(struct iso_directory_record)) { rc = isofs_read_raw_block(block, buf, data->isofs); if (rc < 0) { return rc; } if (rc != data->isofs->data_size) { // can`t be allowed FSDEBUG("can`t read whole block, read only %d bytes, block %d",rc,block); free(buf); return -EIO; } block_count++; if (boff > 0) { total_size += (data->isofs->data_size - boff); boff = 0; } while (boff + sizeof(struct iso_directory_record) <= data->isofs->data_size && total_size <= current_size - sizeof(struct iso_directory_record)) { struct iso_directory_record *record = (struct iso_directory_record *) (buf + boff); size_t record_length = isonum_711((unsigned char *) record->length); size_t name_len = isonum_711(record->name_len); size_t pad_len = ((name_len & 1) ? 0 : 1); // padding byte if name_len is even size_t sa_len = record_length - name_len - sizeof(struct iso_directory_record) - pad_len; // printf("block %d, boff %d, total_size %d, current_size %d, record length %d, name_len %d, pad_len %d, sa_len %d\n", // block, (int) boff, total_size, current_size, record_length, name_len, pad_len, sa_len); if (record_length == 0) { // possible end of directory or end of block total_size += (data->isofs->data_size - boff); boff = 0; break; } if (record_length < sizeof(struct iso_directory_record)) { if (count > 2) // check if . and .. is already read { // possible end of directory // at least mkisofs does not set iso_directory_record.size correct // (this is much possible it was my fault and misunderstanding -- dmiceman) // but we need to try next block to be sure /// TODO this is not clear: what to do if next block not contain next directory? total_size += (data->isofs->data_size - boff); boff = 0; break; } else { FSDEBUG("directory record length too small: %d",record_length); free(buf); return -EIO; } } if (name_len > NAME_MAX - 1) { FSDEBUG("file name length too big: %d",name_len); free(buf); return -EIO; } if (sa_len < 0) { // probably something wrong with name_len FSDEBUG("wrong name_len in directory entry: %d, record_length %d",name_len,record_length); free(buf); return -EIO; } if (count > 2 && name_len == 1 && record->name[0] == 0) { // looks like this is normal situation to meet another directory because // there is no clear way to find directory end // fprintf(stderr, "readdir: next directory found while processing another directory! boff %d, total_size %d, current_size %d, block %d, count %d\n", // (int) boff, total_size, current_size, block, count); goto out_readdir; } isofs_inode *inode = (isofs_inode *) malloc(sizeof(isofs_inode)); if (inode == NULL) { FSDEBUG("can\'t malloc: %s",strerror(errno)); return -ENOMEM; } memset(inode, 0, sizeof(isofs_inode)); inode->st_ino = data->isofs->last_ino; data->isofs->last_ino++; struct iso_directory_record *n_rec = (struct iso_directory_record *) malloc (sizeof(struct iso_directory_record)); if (!n_rec) { FSDEBUG("can\'t malloc: %s",strerror(errno)); return -ENOMEM; } memcpy(n_rec, record, sizeof(struct iso_directory_record)); inode->record = n_rec; if (data->isofs->susp || path[1] == '\0') // if susp is known to be present or this is a root dir ("/") { /* printf("sa offset %d, sa_len %d\n", sizeof(struct iso_directory_record) + name_len + pad_len, sa_len);*/ rc = isofs_parse_sa(inode, ((char *) record) + sizeof(struct iso_directory_record) + name_len + pad_len + data->isofs->susp_skip, sa_len); if (rc<0) { free(buf); isofs_free_inode(inode); return -EIO; } } char *entry = (char *) malloc(NAME_MAX); if (!entry) { FSDEBUG("can\'t malloc: %s",strerror(errno)); return -ENOMEM; } if (count == 1) // . entry ('\0' on disk) { strcpy(entry, "."); } // .. entry ('\1' on disk) else if (count == 2) { strcpy(entry, ".."); } // regular entry else { if (inode->NM) // rrip NM entry present and in effect { //FSDEBUG("NM entry is in effect"); strncpy(entry, inode->nm, inode->nm_len); entry[inode->nm_len] = '\0'; } // regular ISO9660 filename else { //FSDEBUG("readdir: no NM entry found, name len %d",name_len); // because there can be '\0' characters because using of UCS-2 encoding we need to use memcpy memcpy(entry, (char *) record->name, name_len); entry[name_len] = '\0'; // fixup entry -- lowercase, strip leading ';', etc.. if (isofs_fix_entry(&entry,name_len,data->isofs->joliet_level,data->iocharset)<0) { FSDEBUG("error during entry fixup"); isofs_free_inode(inode); free(buf); return -EIO; } } } // fprintf(stderr, "%d -- %s\n\n", count, entry); if (filler) { struct stat st; memset(& st, '\0', sizeof(struct stat)); isofs_direntry2stat(& st, inode); rc = filler(filler_buf, entry, &st, 0); if (rc) { // printf("readdir: filler return with %d, entry %s\n", rc, entry); isofs_free_inode(inode); free(buf); free(entry); return -rc; } } char absolute_entry[PATH_MAX]; strcpy(absolute_entry, path); if (path[1] != '\0') // not root dir { strcat(absolute_entry, "/"); } strcat(absolute_entry, entry); if (g_hash_table_lookup(data->lookup_table, absolute_entry)) { // already in lookup cache isofs_free_inode(inode); } else { FSDEBUG("REGISTER [%s] IN LOOKUP_TABLE",absolute_entry); g_hash_table_insert(data->lookup_table, g_strdup(absolute_entry), inode); } free(entry); boff += record_length; total_size += record_length; count++; } // read next block block++; } out_readdir: if (retval2!=1 && real) { v_dir = opendir(newpath); if (v_dir) { for (;;) { v_dirent = readdir(v_dir); if (v_dirent == NULL) break; v_chemin[0] = '\0'; if (!strcmp(newpath,"/")) sprintf(v_chemin, "/%s", v_dirent->d_name); else sprintf(v_chemin, "%s/%s", newpath, v_dirent->d_name); inode2 = fs_lookup(v_chemin); if (inode2 == NULL) { memset(&v_stbuf, '\0', sizeof(struct stat)); if (filler && !lstat(v_chemin,&v_stbuf)) { filler(filler_buf, v_dirent->d_name, &v_stbuf, 0); FSDEBUG("FILLER #1 [%s]",v_dirent->d_name); } } } closedir(v_dir); } } if (real && data->union_mounting) { // Read the real path v_dir = opendir(path); if (v_dir) { for (;;) { retval1 = 1; v_dirent = readdir(v_dir); if (v_dirent == NULL) break; if (retval2 != 1) { v_chemin[0] = '\0'; if (!strcmp(newpath,"/")) sprintf(v_chemin, "/%s", v_dirent->d_name); else sprintf(v_chemin, "%s/%s", newpath, v_dirent->d_name); retval1 = stat(v_chemin, &v_stbuf); } v_chemin[0] = '\0'; if (!strcmp(path,"/")) sprintf(v_chemin, "/%s", v_dirent->d_name); else sprintf(v_chemin, "%s/%s", path, v_dirent->d_name); inode2 = fs_lookup(v_chemin); if (inode2==NULL && retval1!=0) { memset(&v_stbuf, '\0', sizeof(struct stat)); if (filler && !lstat(v_chemin,&v_stbuf)) if (g_hash_table_lookup(data->removed_lookup_table,v_chemin) == NULL) { filler(filler_buf, v_dirent->d_name, &v_stbuf, 0); FSDEBUG("FILLER #2 [%s]",v_dirent->d_name); } } } closedir(v_dir); } } if (buf != NULL) free(buf); return 0; }