static int namei_iscan(ext2_ino_t ino, struct ext2_inode *inode, struct ea_info *eas) { struct target_inode *t = namei_find_inode(ino); /* If it isn't in our tree, we don't care about it */ if (!t) return ACTION_COMPLETE; if (namei_all_names && !LINUX_S_ISDIR(inode->i_mode)) t->nlinks = inode->i_links_count; else t->nlinks = 1; return ACTION_WANT_PATH; }
/* * This fuction deallocates an inode */ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) { ext2_filsys fs = ctx->fs; struct ext2_inode inode; struct problem_context pctx; ext2fs_icount_store(ctx->inode_link_info, ino, 0); e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); inode.i_links_count = 0; inode.i_dtime = time(0); e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode"); clear_problem_context(&pctx); pctx.ino = ino; /* * Fix up the bitmaps... */ e2fsck_read_bitmaps(ctx); ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); if (ctx->inode_bad_map) ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); ext2fs_unmark_inode_bitmap(fs->inode_map, ino); ext2fs_mark_ib_dirty(fs); if (!ext2fs_inode_has_valid_blocks(&inode)) return; if (!LINUX_S_ISDIR(inode.i_mode) && (inode.i_size_high || inode.i_size & 0x80000000UL)) ctx->large_files--; if (inode.i_file_acl) { ext2fs_unmark_block_bitmap(ctx->block_found_map, inode.i_file_acl); ext2fs_unmark_block_bitmap(fs->block_map, inode.i_file_acl); } ext2fs_mark_bb_dirty(fs); pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, deallocate_inode_block, ctx); if (pctx.errcode) { fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); ctx->flags |= E2F_FLAG_ABORT; return; } }
int ext2_chdir_r (struct _reent *r, const char *name) { ext2_log_trace("name %s\n", name); ext2_vd *vd = NULL; ext2_inode_t *ni = NULL; // Get the volume descriptor for this path vd = ext2GetVolume(name); if (!vd) { r->_errno = ENODEV; return -1; } // Lock ext2Lock(vd); // Find the directory ni = ext2OpenEntry(vd, name); if (!ni) { ext2Unlock(vd); r->_errno = ENOENT; return -1; } // Ensure that this directory is indeed a directory if (!LINUX_S_ISDIR(ni->ni.i_mode)) { ext2CloseEntry(vd, ni); ext2Unlock(vd); r->_errno = ENOTDIR; return -1; } // Close the old current directory (if any) if (vd->cwd_ni) ext2CloseEntry(vd, vd->cwd_ni); // Set the new current directory vd->cwd_ni = ni; // Unlock ext2Unlock(vd); return 0; }
// Top-level function to find the inode number for a file by its full path. __u32 _ref_get_inode_by_path(void * fs, char * path) { char ** parts = split_path(path); __u32 ino_num = EXT2_ROOT_INO; for (char ** part = parts; *part != NULL; part++) { struct ext2_inode * ino = get_inode(fs, ino_num); if (!LINUX_S_ISDIR(ino->i_mode)) break; ino_num = get_inode_from_dir(fs, ino, *part); if (ino_num == 0) { break; } } if (ino_num == EXT2_ROOT_INO){ return 0; } else { return ino_num; } }
errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino) { struct ext2_inode inode; errcode_t retval; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); if (ino > fs->super->s_inodes_count) return EXT2_ET_BAD_INODE_NUM; if (fs->check_directory) { retval = (fs->check_directory)(fs, ino); if (retval != EXT2_ET_CALLBACK_NOTHANDLED) return retval; } retval = ext2fs_read_inode(fs, ino, &inode); if (retval) return retval; if (!LINUX_S_ISDIR(inode.i_mode)) return EXT2_ET_NO_DIRECTORY; return 0; }
/* * This function expands '%IX' expressions */ static _INLINE_ void expand_inode_expression(char ch, struct problem_context *ctx) { struct ext2_inode *inode; struct ext2_inode_large *large_inode; const char * time_str; time_t t; int do_gmt = -1; if (!ctx || !ctx->inode) goto no_inode; inode = ctx->inode; large_inode = (struct ext2_inode_large *) inode; switch (ch) { case 's': if (LINUX_S_ISDIR(inode->i_mode)) printf("%u", inode->i_size); else { #ifdef EXT2_NO_64_TYPE if (inode->i_size_high) printf("0x%x%08x", inode->i_size_high, inode->i_size); else printf("%u", inode->i_size); #else printf("%llu", inode->i_size | ((long long)inode->i_size_high << 32)); #endif } break; case 'S': printf("%u", large_inode->i_extra_isize); break; case 'b': printf("%u", inode->i_blocks); break; case 'l': printf("%d", inode->i_links_count); break; case 'm': printf("0%o", inode->i_mode); break; case 'M': /* The diet libc doesn't respect the TZ environemnt variable */ if (do_gmt == -1) { time_str = getenv("TZ"); if (!time_str) time_str = ""; do_gmt = !strcmp(time_str, "GMT"); } t = inode->i_mtime; time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t)); printf("%.24s", time_str); break; case 'F': printf("%u", inode->i_faddr); break; case 'f': printf("%u", inode->i_file_acl); break; case 'd': printf("%u", (LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0)); break; case 'u': printf("%d", inode_uid(*inode)); break; case 'g': printf("%d", inode_gid(*inode)); break; case 't': if (LINUX_S_ISREG(inode->i_mode)) printf(_("regular file")); else if (LINUX_S_ISDIR(inode->i_mode)) printf(_("directory")); else if (LINUX_S_ISCHR(inode->i_mode)) printf(_("character device")); else if (LINUX_S_ISBLK(inode->i_mode)) printf(_("block device")); else if (LINUX_S_ISFIFO(inode->i_mode)) printf(_("named pipe")); else if (LINUX_S_ISLNK(inode->i_mode)) printf(_("symbolic link")); else if (LINUX_S_ISSOCK(inode->i_mode)) printf(_("socket")); else printf(_("unknown file type with mode 0%o"), inode->i_mode); break; default: no_inode: printf("%%I%c", ch); break; } }
int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino, void *priv_data) { struct dir_context *ctx; struct ext2_inode inode; struct ext2_dir_entry dirent; struct ext2_inline_data data; int ret = BLOCK_ABORT; e2_blkcnt_t blockcnt = 0; char *old_buf; unsigned int old_buflen; int old_flags; ctx = (struct dir_context *)priv_data; old_buf = ctx->buf; old_buflen = ctx->buflen; old_flags = ctx->flags; ctx->flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA; ctx->errcode = ext2fs_read_inode(fs, ino, &inode); if (ctx->errcode) goto out; if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) { ctx->errcode = EXT2_ET_NO_INLINE_DATA; goto out; } if (!LINUX_S_ISDIR(inode.i_mode)) { ctx->errcode = EXT2_ET_NO_DIRECTORY; goto out; } ret = 0; /* we first check '.' and '..' dir */ dirent.inode = ino; dirent.name_len = 1; ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent); dirent.name[0] = '.'; dirent.name[1] = '\0'; ctx->buf = (char *)&dirent; ext2fs_get_rec_len(fs, &dirent, &ctx->buflen); ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); if (ret & BLOCK_ABORT) goto out; dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]); dirent.name_len = 2; ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent); dirent.name[0] = '.'; dirent.name[1] = '.'; dirent.name[2] = '\0'; ctx->buf = (char *)&dirent; ext2fs_get_rec_len(fs, &dirent, &ctx->buflen); ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); if (ret & BLOCK_INLINE_DATA_CHANGED) { errcode_t err; inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode); err = ext2fs_write_inode(fs, ino, &inode); if (err) goto out; ret &= ~BLOCK_INLINE_DATA_CHANGED; } if (ret & BLOCK_ABORT) goto out; ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE; ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE; #ifdef WORDS_BIGENDIAN ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0); if (ctx->errcode) { ret |= BLOCK_ABORT; goto out; } #endif ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); if (ret & BLOCK_INLINE_DATA_CHANGED) { #ifdef WORDS_BIGENDIAN ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf, ctx->buflen, 0); if (ctx->errcode) { ret |= BLOCK_ABORT; goto out; } #endif ctx->errcode = ext2fs_write_inode(fs, ino, &inode); if (ctx->errcode) ret |= BLOCK_ABORT; ret &= ~BLOCK_INLINE_DATA_CHANGED; } if (ret & BLOCK_ABORT) goto out; data.fs = fs; data.ino = ino; ctx->errcode = ext2fs_inline_data_ea_get(&data); if (ctx->errcode) { ret |= BLOCK_ABORT; goto out; } if (data.ea_size <= 0) goto out1; ctx->buf = data.ea_data; ctx->buflen = data.ea_size; #ifdef WORDS_BIGENDIAN ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0); if (ctx->errcode) { ret |= BLOCK_ABORT; goto out1; } #endif ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data); if (ret & BLOCK_INLINE_DATA_CHANGED) { #ifdef WORDS_BIGENDIAN ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf, ctx->buflen, 0); if (ctx->errcode) { ret |= BLOCK_ABORT; goto out1; } #endif ctx->errcode = ext2fs_inline_data_ea_set(&data); if (ctx->errcode) ret |= BLOCK_ABORT; } out1: ext2fs_free_mem(&data.ea_data); out: ctx->buf = old_buf; ctx->buflen = old_buflen; ctx->flags = old_flags; ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED); return ret; }
/* * This function expands '%IX' expressions */ static _INLINE_ void expand_inode_expression(char ch, struct problem_context *ctx) { struct ext2_inode *inode; char * time_str; time_t t; if (!ctx || !ctx->inode) goto no_inode; inode = ctx->inode; switch (ch) { case 's': if (LINUX_S_ISDIR(inode->i_mode)) printf("%u", inode->i_size); else { #ifdef EXT2_NO_64_TYPE if (inode->i_size_high) printf("0x%x%08x", inode->i_size_high, inode->i_size); else printf("%u", inode->i_size); #else printf("%llu", (inode->i_size | ((__u64) inode->i_size_high << 32))); #endif } break; case 'b': printf("%u", inode->i_blocks); break; case 'l': printf("%d", inode->i_links_count); break; case 'm': printf("0%o", inode->i_mode); break; case 'M': t = inode->i_mtime; time_str = ctime(&t); printf("%.24s", time_str); break; case 'F': printf("%u", inode->i_faddr); break; case 'f': printf("%u", inode->i_file_acl); break; case 'd': printf("%u", (LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0)); break; case 'u': printf("%d", (inode->i_uid | (inode->osd2.linux2.l_i_uid_high << 16))); break; case 'g': printf("%d", (inode->i_gid | (inode->osd2.linux2.l_i_gid_high << 16))); break; default: no_inode: printf("%%I%c", ch); break; } }
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, ext2_ino_t ino, char *buf) { ext2_filsys fs = ctx->fs; struct ext2_inode inode; int inode_modified = 0; int not_fixed = 0; unsigned char *frag, *fsize; struct problem_context pctx; int problem = 0; e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); clear_problem_context(&pctx); pctx.ino = ino; pctx.dir = dir; pctx.inode = &inode; if (ext2fs_file_acl_block(fs, &inode) && !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { ext2fs_file_acl_block_set(fs, &inode, 0); inode_modified++; } else not_fixed++; } if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && !(LINUX_S_ISSOCK(inode.i_mode))) problem = PR_2_BAD_MODE; else if (LINUX_S_ISCHR(inode.i_mode) && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_CHAR_DEV; else if (LINUX_S_ISBLK(inode.i_mode) && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_BLOCK_DEV; else if (LINUX_S_ISFIFO(inode.i_mode) && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_FIFO; else if (LINUX_S_ISSOCK(inode.i_mode) && !e2fsck_pass1_check_device_inode(fs, &inode)) problem = PR_2_BAD_SOCKET; else if (LINUX_S_ISLNK(inode.i_mode) && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) { problem = PR_2_INVALID_SYMLINK; } if (problem) { if (fix_problem(ctx, problem, &pctx)) { deallocate_inode(ctx, ino, 0); if (ctx->flags & E2F_FLAG_SIGNAL_MASK) return 0; return 1; } else not_fixed++; problem = 0; } if (inode.i_faddr) { if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { inode.i_faddr = 0; inode_modified++; } else not_fixed++; } switch (fs->super->s_creator_os) { case EXT2_OS_HURD: frag = &inode.osd2.hurd2.h_i_frag; fsize = &inode.osd2.hurd2.h_i_fsize; break; default: frag = fsize = 0; } if (frag && *frag) { pctx.num = *frag; if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { *frag = 0; inode_modified++; } else not_fixed++; pctx.num = 0; } if (fsize && *fsize) { pctx.num = *fsize; if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { *fsize = 0; inode_modified++; } else not_fixed++; pctx.num = 0; } if ((fs->super->s_creator_os == EXT2_OS_LINUX) && !(fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && (inode.osd2.linux2.l_i_blocks_hi != 0)) { pctx.num = inode.osd2.linux2.l_i_blocks_hi; if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) { inode.osd2.linux2.l_i_blocks_hi = 0; inode_modified++; } } if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) && inode.osd2.linux2.l_i_file_acl_high != 0) { pctx.num = inode.osd2.linux2.l_i_file_acl_high; if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) { inode.osd2.linux2.l_i_file_acl_high = 0; inode_modified++; } else not_fixed++; } if (ext2fs_file_acl_block(fs, &inode) && ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) || (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) { if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { ext2fs_file_acl_block_set(fs, &inode, 0); inode_modified++; } else not_fixed++; } if (inode.i_dir_acl && LINUX_S_ISDIR(inode.i_mode)) { if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { inode.i_dir_acl = 0; inode_modified++; } else not_fixed++; } if (inode_modified) e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); if (!not_fixed && ctx->inode_bad_map) ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); return 0; }
int ext2_file_to_sectors (struct _reent *r,const char *path,uint32_t *sec_out,uint32_t *size_out,int max,int phys) { ntfs_file_state fileStruct; ext2_file_state* file = STATE(&fileStruct); // Get the volume descriptor for this path file->vd = ext2GetVolume(path); if (!file->vd) { r->_errno = ENODEV; return -1; } // Lock ext2Lock(file->vd); file->flags = 0; file->read = true; file->write = false; file->append = false; // Try and find the file and (if found) ensure that it is not a directory file->ni = ext2OpenEntry(file->vd, path); if (file->ni && LINUX_S_ISDIR(file->ni->ni.i_mode)) { ext2CloseEntry(file->vd, file->ni); ext2Unlock(file->vd); r->_errno = EISDIR; return -1; } // Sanity check, the file should be open by now if (!file->ni) { ext2Unlock(file->vd); r->_errno = ENOENT; return -1; } errcode_t err = ext2fs_file_open2(file->vd->fs, file->ni->ino, &file->ni->ni, 0, &file->fd); if(err != 0) { ext2CloseEntry(file->vd, file->ni); ext2Unlock(file->vd); r->_errno = ENOENT; return -1; } //ext2_log_trace("file->len %lld\n", EXT2_I_SIZE(&file->ni->ni)); // Update file times ext2UpdateTimes(file->vd, file->ni, EXT2_UPDATE_ATIME); // Insert the file into the double-linked FILO list of open files if (file->vd->firstOpenFile) { file->nextOpenFile = file->vd->firstOpenFile; file->vd->firstOpenFile->prevOpenFile = file; } else { file->nextOpenFile = NULL; } file->prevOpenFile = NULL; file->vd->firstOpenFile = file; file->vd->openFileCount++; // Sync access time ext2Sync(file->vd, file->ni); file->is_ntfs = 0; u64 read = 0; err = 0; // Read from the files data attribute //err = ext2fs_file_read(file->fd, ptr, len, &read); u64 len = 0; ext2fs_file_llseek(file->fd, 0, SEEK_END, (__u64 *) &len); // Set the files current position ext2fs_file_llseek(file->fd, 0, SEEK_SET, 0); u32 current_block = 0; err = ext2fs_file_read_sectors(file->fd, len, &read, sec_out, size_out, ¤t_block, max); if (err || read <= 0 || read > len) { ext2Unlock(file->vd); r->_errno = errno; current_block = err ? err : -1; goto end; } end: // Close the file ext2CloseFile(file); // Remove the file from the double-linked FILO list of open files file->vd->openFileCount--; if (file->nextOpenFile) file->nextOpenFile->prevOpenFile = file->prevOpenFile; if (file->prevOpenFile) file->prevOpenFile->nextOpenFile = file->nextOpenFile; else file->vd->firstOpenFile = file->nextOpenFile; ext2Unlock(file->vd); return current_block; }
static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_data_t *dir) { static unsigned int dir_nbr=0; static unsigned long int inode_known[MAX_DIR_NBR]; file_data_t *dir_list; const unsigned int current_directory_namelength=strlen(dir_data->current_directory); file_data_t *current_file; char *dir_name; int copy_bad=0; int copy_ok=0; if(dir_data->get_dir==NULL || dir_data->copy_file==NULL) return -2; inode_known[dir_nbr++]=dir->st_ino; dir_name=mkdir_local(dir_data->local_dir, dir_data->current_directory); dir_list=dir_data->get_dir(disk, partition, dir_data, (const unsigned long int)dir->st_ino); for(current_file=dir_list;current_file!=NULL;current_file=current_file->next) { dir_data->current_directory[current_directory_namelength]='\0'; if(current_directory_namelength+1+strlen(current_file->name)<sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); strcat(dir_data->current_directory,current_file->name); if(LINUX_S_ISDIR(current_file->st_mode)!=0) { const unsigned long int new_inode=current_file->st_ino; unsigned int new_inode_ok=1; unsigned int i; if(new_inode<2) new_inode_ok=0; if(strcmp(current_file->name,"..")==0 || strcmp(current_file->name,".")==0) new_inode_ok=0; for(i=0;i<dir_nbr && new_inode_ok!=0;i++) if(new_inode==inode_known[i]) /* Avoid loop */ new_inode_ok=0; if(new_inode_ok>0) { int tmp; tmp=copy_dir(disk, partition, dir_data, current_file); if(tmp>=-1) copy_ok=1; if(tmp<0) copy_bad=1; } } else if(LINUX_S_ISREG(current_file->st_mode)!=0) { // log_trace("copy_file %s\n",dir_data->current_directory); int tmp; tmp=dir_data->copy_file(disk, partition, dir_data, current_file); if(tmp==0) copy_ok=1; else copy_bad=1; } } } dir_data->current_directory[current_directory_namelength]='\0'; delete_list_file(dir_list); set_date(dir_name, dir->td_atime, dir->td_mtime); free(dir_name); dir_nbr--; return (copy_bad>0?(copy_ok>0?-1:-2):0); }
DIR_ITER *ext2_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path) { ext2_log_trace("dirState %p, path %s\n", dirState, path); if(!dirState) { r->_errno = EINVAL; return NULL; } ext2_dir_state* dir = STATE(dirState); if(!dir) { r->_errno = EINVAL; return NULL; } // Get the volume descriptor for this path dir->vd = ext2GetVolume(path); if (!dir->vd) { r->_errno = ENODEV; return NULL; } // Lock ext2Lock(dir->vd); // Find the directory dir->ni = ext2OpenEntry(dir->vd, path); if (!dir->ni) { ext2Unlock(dir->vd); r->_errno = ENOENT; return NULL; } // Ensure that this directory is indeed a directory if (!LINUX_S_ISDIR(dir->ni->ni.i_mode)) { ext2CloseEntry(dir->vd, dir->ni); ext2Unlock(dir->vd); r->_errno = ENOTDIR; return NULL; } // Read the directory dir->first = dir->current = NULL; if (ext2fs_dir_iterate(dir->vd->fs, dir->ni->ino, 0, 0, DirIterateCallback, dirState) != EXT2_ET_OK) { ext2CloseDir(dir); ext2Unlock(dir->vd); r->_errno = errno; return NULL; } // Move to the first entry in the directory dir->current = dir->first; // Update directory times ext2UpdateTimes(dir->vd, dir->ni, EXT2_UPDATE_ATIME); // Insert the directory into the double-linked FILO list of open directories if (dir->vd->firstOpenDir) { dir->nextOpenDir = dir->vd->firstOpenDir; dir->vd->firstOpenDir->prevOpenDir = dir; } else { dir->nextOpenDir = NULL; } dir->prevOpenDir = NULL; dir->vd->cwd_ni = dir->ni; dir->vd->firstOpenDir = dir; dir->vd->openDirCount++; // Unlock ext2Unlock(dir->vd); return dirState; }
// search inode by use imap (step1: flag 1 = only directory ; step2: flag 0 = only file) static void search_imap_inode(char* des_dir, __u32 t_after, __u32 t_before, int flag) { struct ext2_group_desc *gdp; struct ext2_inode_large *inode; //struct dir_list_head_t *dir = NULL; struct ring_buf* i_list = NULL; r_item* item = NULL; int zero_flag, retval, load, x ,i ; char *pathname = NULL; char *i_pathname = NULL; char *buf= NULL; unsigned char *tmp_buf = NULL; __u32 blocksize, inodesize, inode_max, inode_per_group, block_count; __u32 inode_per_block , inode_block_group, group; blk_t block_nr; __u32 c_time, d_time, mode; ext2_ino_t first_block_inode_nr , inode_nr; pathname = malloc(26); blocksize = current_fs->blocksize; inodesize = current_fs->super->s_inode_size; inode_max = current_fs->super->s_inodes_count; inode_per_group = current_fs->super->s_inodes_per_group; buf = malloc(blocksize); if (! (flag & 0x01) ){ tmp_buf = malloc (12 * blocksize); if (!tmp_buf) goto errout; cookie = magic_open(MAGIC_MIME | MAGIC_NO_CHECK_COMPRESS | MAGIC_NO_CHECK_ELF | MAGIC_CONTINUE); if ((! cookie) || magic_load(cookie, NULL)){ fprintf(stderr,"ERROR: can't find libmagic\n"); goto errout; } } inode_per_block = blocksize / inodesize; inode_block_group = inode_per_group / inode_per_block; for (group = 0 ; group < current_fs->group_desc_count ; group++){ #ifdef EXT2_FLAG_64BITS gdp = ext2fs_group_desc(current_fs, current_fs->group_desc, group); #else gdp = ¤t_fs->group_desc[group]; #endif zero_flag = 0; if (!(flag & 0x02)){ //skip this in disaster mode // NEXT GROUP IF INODE NOT INIT if (gdp->bg_flags & (EXT2_BG_INODE_UNINIT)) continue; // SET ZERO-FLAG IF FREE INODES == INODE/GROUP for fast ext3 if (gdp->bg_free_inodes_count == inode_per_group) zero_flag = 1; } //FIXME for struct ext4_group_desc 48/64BIT for (block_nr = gdp->bg_inode_table , block_count = 0 ; block_nr < (gdp->bg_inode_table + inode_block_group); block_nr++, block_count++) { if (!(flag & 0x02)){ //skip this in disaster mode // break if the first block only zero inode if ((block_count ==1) && (zero_flag == (inode_per_block + 1))) break; } //FIXME inode_max ???? first_block_inode_nr = (group * inode_per_group) + (block_count * inode_per_block) + 1; load = 0; for (i = 0; i<inode_per_block;i++){ if ( ! ext2fs_test_block_bitmap(imap,first_block_inode_nr + i)){ load++; break; } } if (load){ retval = read_block ( current_fs , &block_nr , buf); if (retval) return; for (inode_nr = first_block_inode_nr ,x = 0; x < inode_per_block ; inode_nr++ , x++){ if ( ! ext2fs_test_block_bitmap(imap,inode_nr)){ inode = (struct ext2_inode_large*) (buf + (x*inodesize)); c_time = ext2fs_le32_to_cpu(inode->i_ctime); mode = ext2fs_le32_to_cpu(inode->i_mode); if ( ! ( flag & 0x02)) { //no check this inode in disaster mode if ((! c_time ) && (!(inode->i_mode & LINUX_S_IFMT)) ) { if(zero_flag) zero_flag++ ; continue; } d_time = ext2fs_le32_to_cpu(inode->i_dtime); if ( (! d_time) || d_time <= t_after){ ext2fs_mark_generic_bitmap(imap,inode_nr); continue; } } // 1. magical step if (LINUX_S_ISDIR(mode) && ( flag & 0x01) && (pathname)){ sprintf(pathname,"<%lu>",(long unsigned int)inode_nr); struct dir_list_head_t * dir = NULL; if (flag & 0x02){ //disaster mode //only search for undeleted entry dir = get_dir3(NULL,0, inode_nr , "MAGIC-1",pathname, t_after,t_before, 0); if (dir) { lookup_local(des_dir, dir,t_after,t_before, RECOV_ALL | LOST_DIR_SEARCH ); clear_dir_list(dir); } } else{ //search for all dir = get_dir3(NULL,0, inode_nr , "MAGIC-1",pathname, t_after,t_before, DELETED_OPT); if (dir) { lookup_local(des_dir,dir,t_after,t_before,DELETED_OPT|RECOV_ALL|LOST_DIR_SEARCH); clear_dir_list(dir); } } } // 2. magical step if (! (flag & 0x01) ){ i_list = get_j_inode_list(current_fs->super, inode_nr); item = get_undel_inode(i_list,t_after,t_before); ext2fs_mark_generic_bitmap(imap,inode_nr); if (item) { if (! LINUX_S_ISDIR(item->inode->i_mode) ) { i_pathname = identify_filename(i_pathname, tmp_buf, (struct ext2_inode*)item->inode, inode_nr); sprintf(pathname,"<%lu>",(long unsigned int)inode_nr); recover_file(des_dir,"MAGIC-2", ((i_pathname)?i_pathname : pathname), (struct ext2_inode*)item->inode, inode_nr, 0); if(i_pathname){ free(i_pathname); i_pathname = NULL; } } } if (i_list) ring_del(i_list); } } } } } } errout: if (pathname) free(pathname); if(buf) { free(buf); buf = NULL; } if (tmp_buf){ free(tmp_buf); tmp_buf = NULL; } if (cookie){ magic_close(cookie); cookie = 0; } return; }
void addPath(const char *path, int squash_uids, int squash_perms) { size_t len; char *full_name = NULL, *lnk = NULL; struct dirent *file = NULL; DIR *direc = NULL; struct stat st; int overWrite; __u16 inodeType; direc = opendir(path); if ( !direc ) log_error("[Local fs opendir] Cannot open directory %s", path); while (( file = readdir(direc)) != NULL ) { if (( !strcmp(file->d_name, "." )) || ( !strcmp(file->d_name, ".." ))) continue; len = strlen(path) + strlen( file->d_name ) + 3; if ( full_name ) { free( full_name ); full_name = NULL; } full_name = (char*)malloc(len + 2); if ( !full_name ) log_error("[Local fs stat]Â Memory allocation error ( full_name --> %s/%s )", path, file->d_name); memset(full_name, 0, len + 2); snprintf(full_name, len, "%s/%s", path, file->d_name); lstat(full_name, &st); mode_t fmt = st.st_mode & S_IFMT; if ( squash_uids ) st.st_uid = st.st_gid = 0; if ( squash_perms ) st.st_mode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO ); overWrite = name_to_inode( file->d_name ); if ( st.st_nlink > 1 ) { if (( lnk = linklist_add(st.st_dev, st.st_ino, full_name + modPath_path_len))) { if ( overWrite ) { log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(file->d_name)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name); } log_action(ACT_HARDLINK, file->d_name, lnk, 0, 0, 0, 0, 0, 0, overWrite); if (!do_hardlink(&st, lnk, file->d_name)) log_error("[Filesystem error] cannot hardlink %s --> %s", file->d_name, lnk); continue; } } if ( overWrite ) inodeType = inode_mode( file->d_name ); if (( fmt == S_IFDIR ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType))) log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), file->d_name); else if (( fmt != S_IFDIR) && ( overWrite )) { if ( LINUX_S_ISDIR(inodeType)) log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), file->d_name); if ((!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) && (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) && (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType))) log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].", log_cwd(), file->d_name); } switch ( fmt ) { case S_IFDIR: // Directory log_action(ACT_MKDIR, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !overWrite ) if ( !do_mkdir( &st, file->d_name )) log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), file->d_name); log_action(ACT_CHMODE, file->d_name, NULL, st.st_mode, 0, 0, 0, 0, 0, overWrite); if ( !do_chmode(file->d_name, st.st_mode)) log_error("[Filesystem error] Failed to chmode 0x%x for directory %s/%s", st.st_mode, log_cwd(), file->d_name); log_action(ACT_CHOWN, file->d_name, NULL, 0, st.st_uid, st.st_gid, 0, 0, 0, 0); if ( !do_chown(file->d_name, st.st_uid, st.st_gid)) log_error("[Filesystem error] Failed to chown %ld, %ld for directory %s/%s", st.st_uid, st.st_gid, log_cwd(), file->d_name); log_action(ACT_CHDIR, file->d_name, NULL, 0, 0, 0, 0, 0, 0, 0); if ( !do_chdir( file->d_name )) log_error("[Filesystem error] cannot chdir to newly created %s/%s", log_cwd(), file->d_name); addPath(full_name, squash_uids, squash_perms); log_action(ACT_CHDIR, "..", NULL, 0, 0, 0, 0, 0, 0, 0); if ( !do_chdir("..")) log_error("[Filesystem error] cannot chdir to parent directory"); break; case S_IFREG: // Regular file if ( overWrite ) { log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(file->d_name)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name); } log_action(ACT_WRITE, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_write(full_name, file->d_name)) log_error("[Filesystem error] cannot write %s/%s", log_cwd(), file->d_name); break; case S_IFLNK: // Symbolic link lnk = (char*)malloc(MAX_PATHSIZE + 2); if ( !lnk ) log_error("[symlink] Memory allocation error (lnk)"); int len = readlink(full_name, lnk, MAX_PATHSIZE); if ( len == -1 ) { free(lnk); log_error("[Local filesystem error] Cannot read destination for link %s/%s", log_cwd(), file->d_name); } else lnk[len] = '\0'; if ( overWrite ) { log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(file->d_name)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name); } log_action(ACT_SYMLINK, file->d_name, lnk, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_symlink(&st, lnk, file->d_name)) log_error("[Filesystem error] cannot symlink %s/%s --> %s", log_cwd(), file->d_name, lnk); free(lnk); break; case S_IFBLK: // Block device node case S_IFCHR: // Character device node case S_IFSOCK: // socket case S_IFIFO: // fifo if ( overWrite ) { log_action(ACT_RM, file->d_name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(file->d_name)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), file->d_name); } char nodetype = ( fmt == S_IFBLK ? 'b' : ( fmt == S_IFCHR ? 'c' : ( fmt == S_IFSOCK ? 's' : 'p' ))); unsigned long major = 0, minor = 0; if (( nodetype == 'b' ) || ( nodetype == 'c' )) { major = (long)major(st.st_rdev); minor = (long)minor(st.st_rdev); } log_action(ACT_MKNOD, file->d_name, NULL, 0, 0, 0, nodetype, major, minor, overWrite); if ( !do_mknod(file->d_name, nodetype, major, minor)) log_error("[Filesystem error] cannot mknod %c %ld,%ld %s/%s", log_cwd(), nodetype, major, minor, log_cwd(), file->d_name); break; } if ( fmt != S_IFDIR ) { // Not dir ? log_action(ACT_CHMODE, file->d_name, NULL, st.st_mode, 0, 0, 0, 0, 0, overWrite); if ( !do_chmode(file->d_name, st.st_mode)) log_error("[Filesystem error] Failed to chmode 0x%x for file %s/%s", st.st_mode, log_cwd(), file->d_name); log_action(ACT_CHOWN, file->d_name, NULL, 0, st.st_uid, st.st_gid, 0, 0, 0, 0); if ( !do_chown(file->d_name, st.st_uid, st.st_gid)) log_error("[Filesystem error] Failed to chown %ld, %ld for file %s/%s", st.st_uid, st.st_gid, log_cwd(), file->d_name); } if ( full_name ) { free( full_name ); full_name = NULL; } } closedir(direc); }
int op_unlink (const char *path) { int rt; errcode_t rc; char *p_path; char *r_path; ext2_ino_t p_ino; struct ext2_inode p_inode; ext2_ino_t r_ino; struct ext2_vnode *r_vnode; struct ext2_inode *r_inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt=do_check_split(path, &p_path, &r_path); if (rt != 0) { debugf("do_check_split: failed"); goto err; } debugf("parent: %s, child: %s", p_path, r_path); rt = do_readinode(e2fs, p_path, &p_ino, &p_inode); if (rt) { debugf("do_readinode(%s, &p_ino, &p_inode); failed", p_path); goto err_free_split; } rt = do_readvnode(e2fs, path, &r_ino, &r_vnode, DONT_OPEN_FILE); if (rt) { debugf("do_readvnode(%s, &r_ino, &r_vnode); failed", path); goto err_free_split; } r_inode = vnode2inode(r_vnode); if(LINUX_S_ISDIR(r_inode->i_mode)) { debugf("%s is a directory", path); vnode_put(r_vnode,0); rt = -EISDIR; goto err_free_split; } rc = ext2fs_unlink(e2fs, p_ino, r_path, r_ino, 0); if (rc) { debugf("ext2fs_unlink(e2fs, %d, %s, %d, 0); failed", p_ino, r_path, r_ino); vnode_put(r_vnode,0); rt = -EIO; goto err_free_split; } if (r_inode->i_links_count > 0) { r_inode->i_links_count -= 1; } p_inode.i_ctime = p_inode.i_mtime = e2fs->now ? e2fs->now : time(NULL); rc = ext2fs_write_inode(e2fs, p_ino, &p_inode); if (rc) { debugf("ext2fs_write_inode(e2fs, p_ino, &p_inode); failed"); vnode_put(r_vnode,1); rt = -EIO; goto err_free_split; } r_inode->i_ctime = e2fs->now ? e2fs->now : time(NULL); rc = vnode_put(r_vnode,1); if (rc) { debugf("vnode_put(r_vnode,1); failed"); rt = -EIO; goto err_free_split; } free_split(p_path, r_path); debugf("leave"); FUSE_EXT2_UNLOCK; return 0; err_free_split: free_split(p_path, r_path); err: FUSE_EXT2_UNLOCK; return rt; }
// recover files from a "double quotes" listfile void recover_list(char *des_dir, char *input_file,__u32 t_after, __u32 t_before, int flag){ FILE *f; char *lineptr = NULL ; char *filename = NULL ; char *p1 , *p2; size_t maxlen; size_t got; ext2_ino_t inode_nr; struct ring_buf *i_list; struct ext2_inode* r_inode; r_item *item = NULL; f = fopen(input_file,"r"); if (f) { rewind(f); maxlen = 512; lineptr = malloc(maxlen); filename = malloc(maxlen); if ((!lineptr) || (!filename)) goto errout; while (! (feof(f))){ got = getline (&lineptr, &maxlen, f); if (got != -1){ p1 = strchr(lineptr,'"'); p2 = strrchr(lineptr,'"'); if ((p1) && (p2) && (p1 != p2)){ p1++; *p2 = 0; strcpy(filename,p1); if (*filename == 0) continue; inode_nr = local_namei(NULL,filename,t_after,t_before,DELETED_OPT); if(! inode_nr){ #ifdef DEBUG printf("Filename %s not found\n",filename); #endif continue; } i_list = get_j_inode_list(current_fs->super, inode_nr); item = get_undel_inode(i_list,t_after,t_before); if (item) { r_inode = (struct ext2_inode*)item->inode; if (! LINUX_S_ISDIR(r_inode->i_mode) ) recover_file(des_dir,"", filename, r_inode, inode_nr ,flag); } #ifdef DEBUG else printf("no Inode found for %s\n",filename); #endif if (i_list) ring_del(i_list); } #ifdef DEBUG else printf("Filename not found in : \"%s\"",lineptr); #endif } } } errout: if (f) fclose(f); if (lineptr) free(lineptr); if (filename) free(filename); return ; }
void e2fsck_pass4(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; ext2_ino_t i; struct ext2_inode *inode; #ifdef RESOURCE_TRACK struct resource_track rtrack; #endif struct problem_context pctx; __u16 link_count, link_counted; char *buf = 0; int group, maxgroup; init_resource_track(&rtrack, ctx->fs->io); #ifdef MTRACE mtrace_print("Pass 4"); #endif clear_problem_context(&pctx); if (!(ctx->options & E2F_OPT_PREEN)) fix_problem(ctx, PR_4_PASS_HEADER, &pctx); group = 0; maxgroup = fs->group_desc_count; if (ctx->progress) if ((ctx->progress)(ctx, 4, 0, maxgroup)) return; inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super), "scratch inode"); /* Protect loop from wrap-around if s_inodes_count maxed */ for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) { if (ctx->flags & E2F_FLAG_SIGNAL_MASK) goto errout; if ((i % fs->super->s_inodes_per_group) == 0) { group++; if (ctx->progress) if ((ctx->progress)(ctx, 4, group, maxgroup)) goto errout; } if (i == EXT2_BAD_INO || (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super))) continue; if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) || (ctx->inode_imagic_map && ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) || (ctx->inode_bb_map && ext2fs_test_inode_bitmap(ctx->inode_bb_map, i))) continue; ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count); ext2fs_icount_fetch(ctx->inode_count, i, &link_counted); if (link_counted == 0) { if (!buf) buf = e2fsck_allocate_memory(ctx, fs->blocksize, "bad_inode buffer"); if (e2fsck_process_bad_inode(ctx, 0, i, buf)) continue; if (disconnect_inode(ctx, i, inode)) continue; ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count); ext2fs_icount_fetch(ctx->inode_count, i, &link_counted); } if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i) && (link_counted > EXT2_LINK_MAX)) link_counted = 1; if (link_counted != link_count) { e2fsck_read_inode(ctx, i, inode, "pass4"); pctx.ino = i; pctx.inode = inode; if (link_count != inode->i_links_count) { pctx.num = link_count; fix_problem(ctx, PR_4_INCONSISTENT_COUNT, &pctx); } pctx.num = link_counted; /* i_link_count was previously exceeded, but no longer * is, fix this but don't consider it an error */ if ((LINUX_S_ISDIR(inode->i_mode) && link_counted > 1 && (inode->i_flags & EXT2_INDEX_FL) && link_count == 1 && !(ctx->options & E2F_OPT_NO)) || (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx))) { inode->i_links_count = link_counted; e2fsck_write_inode(ctx, i, inode, "pass4"); } } } ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0; ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0; ext2fs_free_inode_bitmap(ctx->inode_bb_map); ctx->inode_bb_map = 0; ext2fs_free_inode_bitmap(ctx->inode_imagic_map); ctx->inode_imagic_map = 0; errout: if (buf) ext2fs_free_mem(&buf); ext2fs_free_mem(&inode); print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io); }
int fstat(int fd, struct stat *st) { int ret; struct linux_stat lst; struct ifreq ifr; ret = syscall(SYS_fstat, fd, &lst); if (ret == -1) { errno = EBADF; return -1; } st->st_size = lst.st_size; switch (lst.st_mode & LINUX_S_IFMT) { case LINUX_S_IFSOCK: __platform_socket_fd = fd; /* currently no support for raw socket networking */ lst.st_mode = 0; break; case LINUX_S_IFBLK: syscall(SYS_ioctl, fd, BLKGETSIZE64, &st->st_size); break; case LINUX_S_IFCHR: /* macvtap has a dynamic major number, so hard to test */ if (lst.st_rdev != makedev(10, 200) && major(lst.st_rdev) < 128) break; ret = syscall(SYS_ioctl, fd, TUNGETIFF, &ifr); if (ret == 0) { /* we do not yet support macvtap offload facilities */ if (ifr.ifr_flags & IFF_VNET_HDR) { ifr.ifr_flags &= ~IFF_VNET_HDR; syscall(SYS_ioctl, fd, TUNSETIFF, &ifr); } /* use sock type to tell config we are network */ lst.st_mode = LINUX_S_IFSOCK; /* find mac address */ ret = syscall(SYS_ioctl, fd, SIOCGIFHWADDR, &ifr); if (ret == -1 && __platform_socket_fd != -1) ret = syscall(SYS_ioctl, __platform_socket_fd, SIOCGIFHWADDR, &ifr); if (ret == 0) { memcpy(st->st_hwaddr, ifr.ifr_addr.sa_data, 6); } __platform_pollfd[__platform_npoll].fd = fd; __platform_pollfd[__platform_npoll].events = POLLIN | POLLPRI; __platform_npoll++; } break; } st->st_mode = (LINUX_S_ISDIR (lst.st_mode) ? S_IFDIR : 0) | (LINUX_S_ISCHR (lst.st_mode) ? S_IFCHR : 0) | (LINUX_S_ISBLK (lst.st_mode) ? S_IFBLK : 0) | (LINUX_S_ISREG (lst.st_mode) ? S_IFREG : 0) | (LINUX_S_ISFIFO(lst.st_mode) ? S_IFIFO : 0) | (LINUX_S_ISLNK (lst.st_mode) ? S_IFLNK : 0) | (LINUX_S_ISSOCK(lst.st_mode) ? S_IFSOCK : 0); /* if we are passed in /dev/urandom use as a random source */ if (LINUX_S_ISCHR(lst.st_mode) && lst.st_rdev == makedev(1, 9)) __platform_random_fd = fd; return 0; }
errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino) { struct ext2_inode inode; struct ext2_inline_data data; errcode_t retval; size_t inline_size; char *inline_buf = 0; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); retval = ext2fs_read_inode(fs, ino, &inode); if (retval) return retval; if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) return EXT2_ET_NO_INLINE_DATA; data.fs = fs; data.ino = ino; retval = ext2fs_inline_data_ea_get(&data); if (retval) return retval; inline_size = data.ea_size + EXT4_MIN_INLINE_DATA_SIZE; retval = ext2fs_get_mem(inline_size, &inline_buf); if (retval) goto errout; memcpy(inline_buf, (void *)inode.i_block, EXT4_MIN_INLINE_DATA_SIZE); if (data.ea_size > 0) { memcpy(inline_buf + EXT4_MIN_INLINE_DATA_SIZE, data.ea_data, data.ea_size); } memset((void *)inode.i_block, 0, EXT4_MIN_INLINE_DATA_SIZE); /* * NOTE: We must do this write -> ea_remove -> read cycle here because * removing the inline data EA can free the EA block, which is a change * that our stack copy of the inode will never see. If that happens, * we can end up with the EA block and lblk 0 pointing to the same * pblk, which is bad news. */ retval = ext2fs_write_inode(fs, ino, &inode); if (retval) goto errout; retval = ext2fs_inline_data_ea_remove(fs, ino); if (retval) goto errout; retval = ext2fs_read_inode(fs, ino, &inode); if (retval) goto errout; if (LINUX_S_ISDIR(inode.i_mode)) { retval = ext2fs_inline_data_dir_expand(fs, ino, &inode, inline_buf, inline_size); } else { retval = ext2fs_inline_data_file_expand(fs, ino, &inode, inline_buf, inline_size); } errout: if (inline_buf) ext2fs_free_mem(&inline_buf); ext2fs_free_mem(&data.ea_data); return retval; }
/* * This function expands '%IX' expressions */ static _INLINE_ void expand_inode_expression(FILE *f, ext2_filsys fs, char ch, struct problem_context *ctx) { struct ext2_inode *inode; struct ext2_inode_large *large_inode; if (!ctx || !ctx->inode) goto no_inode; inode = ctx->inode; large_inode = (struct ext2_inode_large *) inode; switch (ch) { case 's': if (LINUX_S_ISDIR(inode->i_mode)) fprintf(f, "%u", inode->i_size); else { #ifdef EXT2_NO_64_TYPE if (inode->i_size_high) fprintf(f, "0x%x%08x", inode->i_size_high, inode->i_size); else fprintf(f, "%u", inode->i_size); #else fprintf(f, "%llu", EXT2_I_SIZE(inode)); #endif } break; case 'S': fprintf(f, "%u", large_inode->i_extra_isize); break; case 'b': if (ext2fs_has_feature_huge_file(fs->super)) fprintf(f, "%llu", inode->i_blocks + (((long long) inode->osd2.linux2.l_i_blocks_hi) << 32)); else fprintf(f, "%u", inode->i_blocks); break; case 'l': fprintf(f, "%d", inode->i_links_count); break; case 'm': fprintf(f, "0%o", inode->i_mode); break; case 'M': print_time(f, inode->i_mtime); break; case 'F': fprintf(f, "%u", inode->i_faddr); break; case 'f': fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode)); break; case 'd': fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0)); break; case 'u': fprintf(f, "%d", inode_uid(*inode)); break; case 'g': fprintf(f, "%d", inode_gid(*inode)); break; case 't': if (LINUX_S_ISREG(inode->i_mode)) fputs(_("regular file"), f); else if (LINUX_S_ISDIR(inode->i_mode)) fputs(_("directory"), f); else if (LINUX_S_ISCHR(inode->i_mode)) fputs(_("character device"), f); else if (LINUX_S_ISBLK(inode->i_mode)) fputs(_("block device"), f); else if (LINUX_S_ISFIFO(inode->i_mode)) fputs(_("named pipe"), f); else if (LINUX_S_ISLNK(inode->i_mode)) fputs(_("symbolic link"), f); else if (LINUX_S_ISSOCK(inode->i_mode)) fputs(_("socket"), f); else fprintf(f, _("unknown file type with mode 0%o"), inode->i_mode); break; default: no_inode: fprintf(f, "%%I%c", ch); break; } }
void do_htree_dump(int argc, char *argv[]) { ext2_ino_t ino; struct ext2_inode inode; blk64_t blk; char *buf = NULL; struct ext2_dx_root_info *rootnode; struct ext2_dx_entry *ent; errcode_t errcode; if (check_fs_open(argv[0])) return; pager = open_pager(); if (common_inode_args_process(argc, argv, &ino, 0)) goto errout; if (debugfs_read_inode(ino, &inode, argv[1])) goto errout; if (!LINUX_S_ISDIR(inode.i_mode)) { com_err(argv[0], 0, "Not a directory"); goto errout; } if ((inode.i_flags & EXT2_BTREE_FL) == 0) { com_err(argv[0], 0, "Not a hash-indexed directory"); goto errout; } buf = malloc(2*current_fs->blocksize); if (!buf) { com_err(argv[0], 0, "Couldn't allocate htree buffer"); goto errout; } errcode = ext2fs_bmap2(current_fs, ino, &inode, buf, 0, 0, 0, &blk); if (errcode) { com_err("do_htree_block", errcode, "while mapping logical block 0\n"); goto errout; } errcode = io_channel_read_blk64(current_fs->io, blk, 1, buf); if (errcode) { com_err(argv[0], errcode, "Error reading root node"); goto errout; } rootnode = (struct ext2_dx_root_info *) (buf + 24); fprintf(pager, "Root node dump:\n"); fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); fprintf(pager, "\t Info length: %d\n", rootnode->info_length); fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, buf + current_fs->blocksize, rootnode->indirect_levels); errout: free(buf); close_pager(pager); }
extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, ext2_ino_t ino) { ext2_filsys fs = ctx->fs; struct ext2_inode inode; int inode_modified = 0; unsigned char *frag, *fsize; struct problem_context pctx; int problem = 0; e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); clear_problem_context(&pctx); pctx.ino = ino; pctx.dir = dir; pctx.inode = &inode; if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && !(LINUX_S_ISSOCK(inode.i_mode))) problem = PR_2_BAD_MODE; else if (LINUX_S_ISCHR(inode.i_mode) && !e2fsck_pass1_check_device_inode(&inode)) problem = PR_2_BAD_CHAR_DEV; else if (LINUX_S_ISBLK(inode.i_mode) && !e2fsck_pass1_check_device_inode(&inode)) problem = PR_2_BAD_BLOCK_DEV; else if (LINUX_S_ISFIFO(inode.i_mode) && !e2fsck_pass1_check_device_inode(&inode)) problem = PR_2_BAD_FIFO; else if (LINUX_S_ISSOCK(inode.i_mode) && !e2fsck_pass1_check_device_inode(&inode)) problem = PR_2_BAD_SOCKET; else if (LINUX_S_ISLNK(inode.i_mode) && !e2fsck_pass1_check_symlink(fs, &inode)) { problem = PR_2_SYMLINK_SIZE; } if (problem) { if (fix_problem(ctx, problem, &pctx)) { deallocate_inode(ctx, ino, 0); if (ctx->flags & E2F_FLAG_SIGNAL_MASK) return 0; return 1; } problem = 0; } if (inode.i_faddr && fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { inode.i_faddr = 0; inode_modified++; } switch (fs->super->s_creator_os) { case EXT2_OS_LINUX: frag = &inode.osd2.linux2.l_i_frag; fsize = &inode.osd2.linux2.l_i_fsize; break; case EXT2_OS_HURD: frag = &inode.osd2.hurd2.h_i_frag; fsize = &inode.osd2.hurd2.h_i_fsize; break; case EXT2_OS_MASIX: frag = &inode.osd2.masix2.m_i_frag; fsize = &inode.osd2.masix2.m_i_fsize; break; default: frag = fsize = 0; } if (frag && *frag) { pctx.num = *frag; if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { *frag = 0; inode_modified++; } pctx.num = 0; } if (fsize && *fsize) { pctx.num = *fsize; if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { *fsize = 0; inode_modified++; } pctx.num = 0; } if (inode.i_file_acl && !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) && fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { inode.i_file_acl = 0; inode_modified++; } if (inode.i_file_acl && ((inode.i_file_acl < fs->super->s_first_data_block) || (inode.i_file_acl >= fs->super->s_blocks_count)) && fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { inode.i_file_acl = 0; inode_modified++; } if (inode.i_dir_acl && LINUX_S_ISDIR(inode.i_mode) && fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { inode.i_dir_acl = 0; inode_modified++; } if (inode_modified) e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); return 0; }
errcode_t ext2fs_move_blocks(ext2_filsys fs, ext2fs_block_bitmap reserve, ext2fs_block_bitmap alloc_map, int flags) { ext2_ino_t ino; struct ext2_inode inode; errcode_t retval; struct process_block_struct pb; ext2_inode_scan scan; char *block_buf; retval = ext2fs_open_inode_scan(fs, 0, &scan); if (retval) return retval; pb.reserve = reserve; pb.error = 0; pb.alloc_map = alloc_map ? alloc_map : fs->block_map; pb.flags = flags; retval = ext2fs_get_array(4, fs->blocksize, &block_buf); if (retval) return retval; pb.buf = block_buf + fs->blocksize * 3; /* * If GET_DBLIST is set in the flags field, then we should * gather directory block information while we're doing the * block move. */ if (flags & EXT2_BMOVE_GET_DBLIST) { if (fs->dblist) { ext2fs_free_dblist(fs->dblist); fs->dblist = NULL; } retval = ext2fs_init_dblist(fs, 0); if (retval) return retval; } retval = ext2fs_get_next_inode(scan, &ino, &inode); if (retval) return retval; while (ino) { if ((inode.i_links_count == 0) || !ext2fs_inode_has_valid_blocks(&inode)) goto next; pb.ino = ino; pb.inode = &inode; pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && flags & EXT2_BMOVE_GET_DBLIST); retval = ext2fs_block_iterate2(fs, ino, 0, block_buf, process_block, &pb); if (retval) return retval; if (pb.error) return pb.error; next: retval = ext2fs_get_next_inode(scan, &ino, &inode); if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) goto next; } return 0; }
void addFilespec(FILE *fd, int squash_uids, int squash_perms) { unsigned long rmode, mode, uid, gid, major, minor, i; unsigned long start, increment, count, octmode, decmode; char *c, *dir, *name, *dname = NULL, *path = NULL, *path2 = NULL, *line = NULL; char type; size_t len; int argv, i2, overWrite = 0, lineno = 0; __u16 inodeType; while ( getline(&line, &len, fd) >= 0 ) { rmode = mode = uid = gid = major = minor = start = count = overWrite = 0; increment = 1; lineno++; if (( c = strchr(line, '#'))) *c = 0; if ( path ) { free( path ); path = NULL; } if ( path2 ) { free( path2 ); path2 = NULL; } argv = sscanf(line, "%" SCANF_PREFIX "s %c %ld %lu %lu %lu %lu %lu %lu %lu", SCANF_STRING(path), &type, &rmode, &uid, &gid, &major, &minor, &start, &increment, &count); if ( argv < 3 ) { if ( argv > 0 ) log_warning("device table[%d]: bad format for entry '%s' [skip]", lineno, path); continue; } i2 = 0; octmode = rmode; decmode = 0; while ( octmode != 0 ) { decmode = decmode + (octmode % 10) * pow(8, i2++); octmode = octmode / 10; } if ( squash_uids ) uid = gid = 0; mode = decmode; path2 = strdup( path ); name = basename( path ); dir = dirname( path2 ); if (( !strcmp(name, ".")) || ( !strcmp(name, "..")) || ( !strcmp(name, "/"))) { log_warning("device table[%d]: [skip]", lineno); continue; } log_action(ACT_CHDIR, dir, NULL, 0, 0, 0, 0, 0, 0, 0); if ( !do_chdir(dir)) { log_warning("device table[%d]: target directory '%s' for entry '%s' does not exist [skip]", lineno, dir, name); log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0); if ( !do_chdir("/")) log_error("[Filesystem error] cannot chdir to root"); continue; } if (( type != 'd' ) && ( type != 'f' ) && ( type != 'p' ) && ( type != 'c' ) && ( type != 'b' ) && ( type != 's')) { log_warning("device table[%d]: bad type '%c' for entry '%s' [skip]", lineno, type, name); continue; } if (squash_perms) { mode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO ); rmode &= ~( LINUX_S_IRWXG | LINUX_S_IRWXO); } if ( count > 0 ) { if ( dname ) { free( dname ); dname = NULL; } unsigned len; len = strlen(name) + 10; dname = malloc(len + 1); for ( i = start; i < count; i++ ) { snprintf(dname, len, "%s%lu", name, i); if (( overWrite = name_to_inode(dname))) inodeType = inode_mode(dname); if (( type == 'd' ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType))) log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), dname); else if (( type != 'd' ) && ( overWrite )) { if ( LINUX_S_ISDIR(inodeType)) log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), dname); if ((!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) && (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) && (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType))) log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].", log_cwd(), dname, inodeType); } switch ( type ) { case 'd': mode |= LINUX_S_IFDIR; log_action(ACT_MKDIR, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !overWrite ) if ( !do_mkdir(dname)) log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), dname); break; case 'c': case 'b': if ( type == 'c' ) mode |= LINUX_S_IFCHR; else mode |= LINUX_S_IFBLK; if ( overWrite ) { log_action(ACT_RM, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(dname)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), dname); } log_action(ACT_MKNOD, dname, NULL, 0, 0, 0, type, major, minor + ((i * increment) - start), overWrite); if ( !do_mknod(dname, type, major, minor + ((i * increment) - start))) log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), dname); break; case 's': case 'p': if ( type == 's' ) mode |= LINUX_S_IFSOCK; else mode |= LINUX_S_IFIFO; if ( overWrite ) { log_action(ACT_RM, dname, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(dname)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), dname); } log_action(ACT_MKNOD, dname, NULL, 0, 0, 0, type, 0, 0, overWrite); if ( !do_mknod(dname, type, 0, 0)) log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), dname); break; } log_action(ACT_CHMOD, dname, NULL, rmode, 0, 0, 0, 0, 0, 0); if ( !do_chmod(dname, rmode)) log_error("[Filesystem error] cannot chmod %s/%s", log_cwd(), dname); log_action(ACT_CHOWN, dname, NULL, 0, uid, gid, 0, 0, 0, 0); if ( !do_chown(dname, uid, gid)) log_error("[Filesystem error] cannot chown %s/%s", log_cwd(), dname); } log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0); if ( !do_chdir("/")) log_error("[Filesystem error] cannot chdir to root"); free(dname); dname = NULL; } else { if (( overWrite = name_to_inode(name))) inodeType = inode_mode(name); if (( type == 'd' ) && ( overWrite ) && ( !LINUX_S_ISDIR(inodeType))) log_error("[Remote fs mismatch] %s/%s exists but isn't a directory when it should be.", log_cwd(), dname); else if ( type != 'd' ) { if (( overWrite ) && ( LINUX_S_ISDIR(inodeType))) log_error("[Remote fs mismatch] %s/%s exists but is a directory when it shouldn't be.", log_cwd(), dname); if (( overWrite ) && (!LINUX_S_ISREG(inodeType)) && (!LINUX_S_ISLNK(inodeType)) && (!LINUX_S_ISBLK(inodeType)) && (!LINUX_S_ISCHR(inodeType)) && (!LINUX_S_ISFIFO(inodeType)) && (!LINUX_S_ISSOCK(inodeType))) log_error("[Remote fs mismatch] Existing file %s/%s has unknown/unsupported type [0x%x].", log_cwd(), dname, inodeType); } switch ( type ) { case 'd': mode |= LINUX_S_IFDIR; log_action(ACT_MKDIR, name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !overWrite ) if ( !do_mkdir(name)) log_error("[Filesystem error] cannot mkdir %s/%s", log_cwd(), name); break; case 'c': case 'b': if ( type == 'c' ) mode |= LINUX_S_IFCHR; else mode |= LINUX_S_IFBLK; if ( overWrite ) { log_action(ACT_RM, name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(name)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), name); } log_action(ACT_MKNOD, name, NULL, 0, 0, 0, type, major, minor, overWrite); if ( !do_mknod(name, type, major, minor)) log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), name); break; case 's': case 'p': if ( type == 's' ) mode |= LINUX_S_IFSOCK; else mode |= LINUX_S_IFIFO; if ( overWrite ) { log_action(ACT_RM, name, NULL, 0, 0, 0, 0, 0, 0, overWrite); if ( !do_rm(name)) log_error("[Filesystem error] cannot rm %s/%s", log_cwd(), name); } log_action(ACT_MKNOD, name, NULL, 0, 0, 0, type, 0, 0, overWrite); if ( !do_mknod(name, type, 0, 0)) log_error("[Filesystem error] cannot mknod %s/%s", log_cwd(), name); break; } log_action(ACT_CHMOD, name, NULL, rmode, 0, 0, 0, 0, 0, 0); if ( !do_chmod(name, rmode)) log_error("[Filesystem error] cannot chmod %s/%s", log_cwd(), name); log_action(ACT_CHOWN, name, NULL, 0, uid, gid, 0, 0, 0, 0); if ( !do_chown(name, uid, gid)) log_error("[Filesystem error] cannot chown %s/%s", log_cwd(), name); log_action(ACT_CHDIR, "/", NULL, 0, 0, 0, 0, 0, 0, 0); if ( !do_chdir("/")) log_error("[Filesystem error] cannot chdir to root"); } } if ( line ) { free( line ); line = NULL; } if ( path ) { free( path ); path = NULL; } if ( path2 ) { free( path2 ); path2 = NULL; } }
static int fat_unformat_aux(struct ph_param *params, const struct ph_options *options, const uint64_t start_offset, alloc_data_t *list_search_space) { int ind_stop=0; uint64_t offset; uint64_t offset_end; unsigned char *buffer_start; unsigned char *buffer; time_t start_time; time_t previous_time; const unsigned int blocksize=params->blocksize; const unsigned int read_size=(blocksize>65536?blocksize:65536); alloc_data_t *current_search_space; file_recovery_t file_recovery; disk_t *disk=params->disk; const partition_t *partition=params->partition; reset_file_recovery(&file_recovery); file_recovery.blocksize=blocksize; buffer_start=(unsigned char *)MALLOC(READ_SIZE); buffer=buffer_start; start_time=time(NULL); previous_time=start_time; current_search_space=td_list_entry(list_search_space->list.prev, alloc_data_t, list); if(current_search_space==list_search_space) { free(buffer_start); return 0; } offset_end=current_search_space->end; current_search_space=td_list_entry(list_search_space->list.next, alloc_data_t, list); offset=set_search_start(params, ¤t_search_space, list_search_space); if(options->verbose>0) info_list_search_space(list_search_space, current_search_space, disk->sector_size, 0, options->verbose); disk->pread(disk, buffer, READ_SIZE, offset); for(;offset < offset_end; offset+=blocksize) { if(memcmp(buffer, ". ", 8+3)==0 && memcmp(&buffer[0x20], ".. ", 8+3)==0) { file_data_t *dir_list; dir_list=dir_fat_aux(buffer,read_size,0,0); if(dir_list!=NULL) { const file_data_t *current_file; log_info("Sector %llu\n", (long long unsigned)offset/disk->sector_size); dir_aff_log(NULL, dir_list); del_search_space(list_search_space, offset, offset + blocksize -1); current_file=dir_list; while(current_file!=NULL) { if(strcmp(current_file->name,".")==0 && LINUX_S_ISDIR(current_file->stat.st_mode)!=0 && current_file!=dir_list) current_file=NULL; else if(current_file->stat.st_ino>2 && LINUX_S_ISREG(current_file->stat.st_mode)!=0) { const uint64_t file_start=start_offset + (uint64_t)(current_file->stat.st_ino - 2) * blocksize; #ifdef DJGPP const uint64_t file_end=file_start+(current_file->file_size+blocksize-1)/blocksize*blocksize - 1; #else const uint64_t file_end=file_start+(current_file->stat.st_size+blocksize-1)/blocksize*blocksize - 1; #endif if(file_end < partition->part_offset + partition->part_size) { if(fat_copy_file(disk, partition, blocksize, start_offset, params->recup_dir, params->dir_num, current_file)==0) { params->file_nbr++; del_search_space(list_search_space, file_start, file_end); } current_file=current_file->next; } else current_file=NULL; } else current_file=current_file->next; } delete_list_file(dir_list); } } buffer+=blocksize; if(buffer+read_size>buffer_start+READ_SIZE) { buffer=buffer_start; if(options->verbose>1) { log_verbose("Reading sector %10llu/%llu\n", (unsigned long long)((offset-partition->part_offset)/disk->sector_size), (unsigned long long)((partition->part_size-1)/disk->sector_size)); } if(disk->pread(disk, buffer, READ_SIZE, offset) != READ_SIZE) { #ifdef HAVE_NCURSES wmove(stdscr,11,0); wclrtoeol(stdscr); wprintw(stdscr,"Error reading sector %10lu\n", (unsigned long)((offset-partition->part_offset)/disk->sector_size)); #endif } #ifdef HAVE_NCURSES { time_t current_time; current_time=time(NULL); if(current_time>previous_time) { const time_t elapsed_time=current_time - params->real_start_time; previous_time=current_time; wmove(stdscr,9,0); wclrtoeol(stdscr); log_info("Reading sector %10llu/%llu, %u files found\n", (unsigned long long)((offset-partition->part_offset)/disk->sector_size), (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr); wprintw(stdscr,"Reading sector %10llu/%llu, %u files found\n", (unsigned long long)((offset-partition->part_offset)/disk->sector_size), (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr); wmove(stdscr,10,0); wclrtoeol(stdscr); wprintw(stdscr,"Elapsed time %uh%02um%02us", (unsigned)(elapsed_time/60/60), (unsigned)(elapsed_time/60%60), (unsigned)(elapsed_time%60)); if(offset-partition->part_offset!=0) { wprintw(stdscr," - Estimated time to completion %uh%02um%02u\n", (unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/3600), (unsigned)(((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/60)%60), (unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset))%60); } wrefresh(stdscr); if(check_enter_key_or_s(stdscr)) { log_info("PhotoRec has been stopped\n"); params->offset=offset; offset = offset_end; ind_stop=1; } } } #endif } } free(buffer_start); return ind_stop; }
/* * This fuction deallocates an inode */ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) { ext2_filsys fs = ctx->fs; struct ext2_inode inode; struct problem_context pctx; __u32 count; struct del_block del_block; e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); clear_problem_context(&pctx); pctx.ino = ino; /* * Fix up the bitmaps... */ e2fsck_read_bitmaps(ctx); ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); if (ext2fs_file_acl_block(fs, &inode) && (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { pctx.errcode = ext2fs_adjust_ea_refcount2(fs, ext2fs_file_acl_block(fs, &inode), block_buf, -1, &count); if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { pctx.errcode = 0; count = 1; } if (pctx.errcode) { pctx.blk = ext2fs_file_acl_block(fs, &inode); fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); ctx->flags |= E2F_FLAG_ABORT; return; } if (count == 0) { ext2fs_unmark_block_bitmap2(ctx->block_found_map, ext2fs_file_acl_block(fs, &inode)); ext2fs_block_alloc_stats2(fs, ext2fs_file_acl_block(fs, &inode), -1); } ext2fs_file_acl_block_set(fs, &inode, 0); } if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) goto clear_inode; if (LINUX_S_ISREG(inode.i_mode) && ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode))) ctx->large_files--; del_block.ctx = ctx; del_block.num = 0; pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, deallocate_inode_block, &del_block); if (pctx.errcode) { fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); ctx->flags |= E2F_FLAG_ABORT; return; } clear_inode: /* Inode may have changed by block_iterate, so reread it */ e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); }
void do_htree_dump(int argc, char *argv[]) { ext2_ino_t ino; struct ext2_inode inode; int c; int long_opt = 0; blk_t blk; char *buf = NULL; struct ext2_dx_root_info *rootnode; struct ext2_dx_entry *ent; struct ext2_dx_countlimit *limit; errcode_t errcode; if (check_fs_open(argv[0])) return; pager = open_pager(); reset_getopt(); while ((c = getopt (argc, argv, "l")) != EOF) { switch (c) { case 'l': long_opt++; break; default: goto print_usage; } } if (argc > optind+1) { print_usage: com_err(0, 0, "Usage: htree_dump [-l] file"); goto errout; } if (argc == optind) ino = cwd; else ino = string_to_inode(argv[optind]); if (!ino) goto errout; if (debugfs_read_inode(ino, &inode, argv[1])) goto errout; if (!LINUX_S_ISDIR(inode.i_mode)) { com_err(argv[0], 0, "Not a directory"); goto errout; } if ((inode.i_flags & EXT2_BTREE_FL) == 0) { com_err(argv[0], 0, "Not a hash-indexed directory"); goto errout; } buf = malloc(2*current_fs->blocksize); if (!buf) { com_err(argv[0], 0, "Couldn't allocate htree buffer"); goto errout; } errcode = ext2fs_bmap(current_fs, ino, &inode, buf, 0, 0, &blk); if (errcode) { com_err("do_htree_block", errcode, "while mapping logical block 0\n"); goto errout; } errcode = io_channel_read_blk(current_fs->io, blk, 1, buf); if (errcode) { com_err(argv[0], errcode, "Error reading root node"); goto errout; } rootnode = (struct ext2_dx_root_info *) (buf + 24); fprintf(pager, "Root node dump:\n"); fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); fprintf(pager, "\t Info length: %d\n", rootnode->info_length); fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); limit = (struct ext2_dx_countlimit *) ent; htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, buf + current_fs->blocksize, rootnode->indirect_levels); errout: free(buf); close_pager(pager); }
/* * This routine is called when an inode is not connected to the * directory tree. * * This subroutine returns 1 then the caller shouldn't bother with the * rest of the pass 4 tests. */ static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i, struct ext2_inode *inode) { ext2_filsys fs = ctx->fs; struct problem_context pctx; __u32 eamagic = 0; int extra_size = 0; if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) { e2fsck_read_inode_full(ctx, i, inode,EXT2_INODE_SIZE(fs->super), "pass4: disconnect_inode"); extra_size = ((struct ext2_inode_large *)inode)->i_extra_isize; } else { e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode"); } clear_problem_context(&pctx); pctx.ino = i; pctx.inode = inode; if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0) eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE + extra_size); /* * Offer to delete any zero-length files that does not have * blocks. If there is an EA block, it might have useful * information, so we won't prompt to delete it, but let it be * reconnected to lost+found. */ if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC && (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) { if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) { e2fsck_clear_inode(ctx, i, inode, 0, "disconnect_inode"); /* * Fix up the bitmaps... */ e2fsck_read_bitmaps(ctx); ext2fs_inode_alloc_stats2(fs, i, -1, LINUX_S_ISDIR(inode->i_mode)); quota_data_inodes(ctx->qctx, inode, i, -1); return 0; } } /* * Prompt to reconnect. */ if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) { if (e2fsck_reconnect_file(ctx, i)) ext2fs_unmark_valid(fs); } else { /* * If we don't attach the inode, then skip the * i_links_test since there's no point in trying to * force i_links_count to zero. */ ext2fs_unmark_valid(fs); return 1; } return 0; }
int ext2_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) { //ext2_log_trace("fileStruct %p, path %s, flags %i, mode %i\n", fileStruct, path, flags, mode); ext2_file_state* file = STATE(fileStruct); // Get the volume descriptor for this path file->vd = ext2GetVolume(path); if (!file->vd) { r->_errno = ENODEV; return -1; } // Lock ext2Lock(file->vd); // Determine which mode the file is opened for file->flags = flags; if ((flags & 0x03) == O_RDONLY) { file->read = true; file->write = false; file->append = false; } else if ((flags & 0x03) == O_WRONLY) { file->read = false; file->write = true; file->append = (flags & O_APPEND); } else if ((flags & 0x03) == O_RDWR) { file->read = true; file->write = true; file->append = (flags & O_APPEND); } else { r->_errno = EACCES; ext2Unlock(file->vd); return -1; } // Try and find the file and (if found) ensure that it is not a directory file->ni = ext2OpenEntry(file->vd, path); if (file->ni && LINUX_S_ISDIR(file->ni->ni.i_mode)) { ext2CloseEntry(file->vd, file->ni); ext2Unlock(file->vd); r->_errno = EISDIR; return -1; } // Are we creating this file? if ((flags & O_CREAT) && !file->ni) // Create the file file->ni = ext2Create(file->vd, path, S_IFREG, NULL); // exit(0); // Sanity check, the file should be open by now if (!file->ni) { ext2Unlock(file->vd); r->_errno = ENOENT; return -1; } // Make sure we aren't trying to write to a read-only file if (!(file->vd->fs->flags & EXT2_FLAG_RW) && file->write) { ext2CloseEntry(file->vd, file->ni); ext2Unlock(file->vd); r->_errno = EROFS; return -1; } errcode_t err = ext2fs_file_open2(file->vd->fs, file->ni->ino, &file->ni->ni, file->write ? EXT2_FLAG_RW : 0, &file->fd); if(err != 0) { ext2CloseEntry(file->vd, file->ni); ext2Unlock(file->vd); r->_errno = ENOENT; return -1; } // Truncate the file if requested if ((flags & O_TRUNC) && file->write) { if (ext2fs_file_set_size2(file->fd, 0) != 0) { ext2CloseEntry(file->vd, file->ni); ext2Unlock(file->vd); r->_errno = errno; return -1; } file->ni->ni.i_size = file->ni->ni.i_size_high = 0; } // Set the files current position ext2fs_file_llseek(file->fd, file->append ? EXT2_I_SIZE(&file->ni->ni) : 0, SEEK_SET, 0); //ext2_log_trace("file->len %lld\n", EXT2_I_SIZE(&file->ni->ni)); // Update file times ext2UpdateTimes(file->vd, file->ni, EXT2_UPDATE_ATIME); // Insert the file into the double-linked FILO list of open files if (file->vd->firstOpenFile) { file->nextOpenFile = file->vd->firstOpenFile; file->vd->firstOpenFile->prevOpenFile = file; } else { file->nextOpenFile = NULL; } file->prevOpenFile = NULL; file->vd->firstOpenFile = file; file->vd->openFileCount++; // Sync access time ext2Sync(file->vd, file->ni); file->is_ntfs = 0; // Unlock ext2Unlock(file->vd); return (int)(s64)fileStruct; }
static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, file_data_t*dir_list, const unsigned long int inode, const unsigned int depth) { /* Return value * -1: quit * 1: back * other: new inode * */ int quit=0; WINDOW *window=(WINDOW*)dir_data->display; do { int offset=0; int pos_num=0; file_data_t *pos=dir_list; int old_LINES=LINES; unsigned int status=FILE_STATUS_MARKED; aff_copy(window); wmove(window,3,0); aff_part(window, AFF_PART_ORDER|AFF_PART_STATUS, disk, partition); wmove(window,4,0); wprintw(window,"Directory %s\n",dir_data->current_directory); do { int i; int car; const file_data_t *current_file; for(i=0,current_file=dir_list;(current_file!=NULL) && (i<offset);current_file=current_file->next,i++); for(i=offset;(current_file!=NULL) &&((i-offset)<INTER_DIR);i++,current_file=current_file->next) { char str[11]; char datestr[80]; wmove(window, 6+i-offset, 0); wclrtoeol(window); /* before addstr for BSD compatibility */ if(current_file==pos) { wattrset(window, A_REVERSE); waddstr(window, ">"); } else waddstr(window, " "); if((current_file->status&FILE_STATUS_DELETED)!=0 && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(1)); else if((current_file->status&FILE_STATUS_MARKED)!=0 && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(2)); if(current_file->td_mtime!=0) { struct tm *tm_p; tm_p = localtime(¤t_file->td_mtime); snprintf(datestr, sizeof(datestr),"%2d-%s-%4d %02d:%02d", tm_p->tm_mday, monstr[tm_p->tm_mon], 1900 + tm_p->tm_year, tm_p->tm_hour, tm_p->tm_min); /* May have to use %d instead of %e */ } else { strncpy(datestr, " ",sizeof(datestr)); } mode_string(current_file->st_mode, str); wprintw(window, "%s %5u %5u ", str, (unsigned int)current_file->st_uid, (unsigned int)current_file->st_gid); wprintw(window, "%9llu", (long long unsigned int)current_file->st_size); /* screen may overlap due to long filename */ wprintw(window, " %s %s", datestr, current_file->name); if(((current_file->status&FILE_STATUS_DELETED)!=0 || (current_file->status&FILE_STATUS_MARKED)!=0) && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if(current_file==pos) wattroff(window, A_REVERSE); } wmove(window, 6-1, 51); wclrtoeol(window); if(offset>0) wprintw(window, "Previous"); /* Clear the last line, useful if overlapping */ wmove(window,6+i-offset,0); wclrtoeol(window); wmove(window, 6+INTER_DIR, 51); wclrtoeol(window); if(current_file!=NULL) wprintw(window, "Next"); if(dir_list==NULL) { wmove(window,6,0); wprintw(window,"No file found, filesystem may be damaged."); } /* Redraw the bottom of the screen everytime because very long filenames may have corrupt it*/ mvwaddstr(window,LINES-3,0,"Use "); if(depth>0) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window, "Left"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," arrow to go back, "); } if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"Right"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to change directory"); if((dir_data->capabilities&CAPA_LIST_DELETED)!=0) { waddstr(window,", "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"h"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if((dir_data->param&FLAG_LIST_DELETED)==0) waddstr(window," to unhide deleted files"); else waddstr(window," to hide deleted files"); } wmove(window,LINES-2,4); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"q"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to quit"); if(dir_data->copy_file!=NULL) { waddstr(window,", "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,":"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to select the current file, "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"a"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if((status&FILE_STATUS_MARKED)==FILE_STATUS_MARKED) waddstr(window," to select all files "); else waddstr(window," to deselect all files"); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); mvwaddstr(window,LINES-1,4,"C"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to copy the selected files, "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"c"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to copy the current file"); } wrefresh(window); /* Using gnome terminal under FC3, TERM=xterm, the screen is not always correct */ wredrawln(window,0,getmaxy(window)); /* redrawwin def is boggus in pdcur24 */ car=wgetch(window); wmove(window,5,0); wclrtoeol(window); switch(car) { case key_ESC: case 'q': case 'M': quit=1; break; case '-': case KEY_LEFT: case '4': if(depth>0) return 1; break; case 'h': if((dir_data->capabilities&CAPA_LIST_DELETED)!=0) dir_data->param^=FLAG_LIST_DELETED; return inode; } if(dir_list!=NULL) { switch(car) { case KEY_UP: case '8': if(pos->prev!=NULL) { pos=pos->prev; pos_num--; } break; case KEY_DOWN: case '2': if(pos->next!=NULL) { pos=pos->next; pos_num++; } break; case ':': if(!(pos->name[0]=='.' && pos->name[1]=='\0') && !(pos->name[0]=='.' && pos->name[1]=='.' && pos->name[2]=='\0')) pos->status^=FILE_STATUS_MARKED; if(pos->next!=NULL) { pos=pos->next; pos_num++; } break; case 'a': { file_data_t *tmp; for(tmp=dir_list; tmp!=NULL; tmp=tmp->next) { if((tmp->name[0]=='.' && tmp->name[1]=='\0') || (tmp->name[0]=='.' && tmp->name[1]=='.' && tmp->name[2]=='\0')) { tmp->status&=~FILE_STATUS_MARKED; } else { if((tmp->status & FILE_STATUS_MARKED)!=status) tmp->status^=FILE_STATUS_MARKED; } } status^=FILE_STATUS_MARKED; } break; case 'p': case 'P': case '+': case ' ': case KEY_RIGHT: case '\r': case '\n': case '6': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif if((pos!=NULL) && (LINUX_S_ISDIR(pos->st_mode)!=0)) { unsigned long int new_inode=pos->st_ino; if((new_inode!=inode) &&(strcmp(pos->name,".")!=0)) { if(strcmp(pos->name,"..")==0) return 1; if(strlen(dir_data->current_directory)+1+strlen(pos->name)+1<=sizeof(dir_data->current_directory)) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); strcat(dir_data->current_directory,pos->name); return (long int)new_inode; } } } break; case KEY_PPAGE: for(i=0;(i<INTER_DIR-1)&&(pos->prev!=NULL);i++) { pos=pos->prev; pos_num--; } break; case KEY_NPAGE: for(i=0;(i<INTER_DIR-1)&&(pos->next!=NULL);i++) { pos=pos->next; pos_num++; } break; case 'c': if(dir_data->copy_file!=NULL) { const unsigned int current_directory_namelength=strlen(dir_data->current_directory); if(strcmp(pos->name,"..")!=0 && current_directory_namelength+1+strlen(pos->name)<sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); if(strcmp(pos->name,".")!=0) strcat(dir_data->current_directory,pos->name); if(dir_data->local_dir==NULL) { if(LINUX_S_ISDIR(pos->st_mode)!=0) dir_data->local_dir=ask_location("Please select a destination where %s and any files below will be copied.", dir_data->current_directory, NULL); else dir_data->local_dir=ask_location("Please select a destination where %s will be copied.", dir_data->current_directory, NULL); } if(dir_data->local_dir!=NULL) { int res=-1; wmove(window,5,0); wclrtoeol(window); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copying, please wait..."); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); wrefresh(window); if(LINUX_S_ISDIR(pos->st_mode)!=0) { res=copy_dir(disk, partition, dir_data, pos); } else if(LINUX_S_ISREG(pos->st_mode)!=0) { res=dir_data->copy_file(disk, partition, dir_data, pos); } wmove(window,5,0); wclrtoeol(window); if(res < -1) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copy failed!"); } else { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2)); if(res < 0) wprintw(window,"Copy done! (Failed to copy some files)"); else wprintw(window,"Copy done!"); } if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); } dir_data->current_directory[current_directory_namelength]='\0'; } } break; case 'C': if(dir_data->copy_file!=NULL) { if(dir_data->local_dir==NULL) { dir_data->local_dir=ask_location("Please select a destination where the marked files will be copied.", NULL, NULL); } if(dir_data->local_dir!=NULL) { file_data_t *tmp; int copy_bad=0; int copy_ok=0; const unsigned int current_directory_namelength=strlen(dir_data->current_directory); wmove(window,5,0); wclrtoeol(window); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copying, please wait..."); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); wrefresh(window); for(tmp=dir_list; tmp!=NULL; tmp=tmp->next) { if((tmp->status&FILE_STATUS_MARKED)!=0 && current_directory_namelength + 1 + strlen(tmp->name) < sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); if(strcmp(tmp->name,".")!=0) strcat(dir_data->current_directory,tmp->name); if(LINUX_S_ISDIR(tmp->st_mode)!=0) { const int res=copy_dir(disk, partition, dir_data, tmp); if(res >=-1) { tmp->status&=~FILE_STATUS_MARKED; copy_ok=1; } else if(res < 0) copy_bad=1; } else if(LINUX_S_ISREG(tmp->st_mode)!=0) { if(dir_data->copy_file(disk, partition, dir_data, tmp) == 0) { tmp->status&=~FILE_STATUS_MARKED; copy_ok=1; } else copy_bad=1; } } dir_data->current_directory[current_directory_namelength]='\0'; } wmove(window,5,0); wclrtoeol(window); if(copy_bad > 0 && copy_ok==0) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copy failed!"); } else { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2)); if(copy_bad > 0) wprintw(window,"Copy done! (Failed to copy some files)"); else if(copy_ok == 0) wprintw(window,"No file selected"); else wprintw(window,"Copy done!"); } if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); } } break; case 'f': { const char *needle=ask_string_ncurses("Filename to find ? "); if(needle!=NULL && needle[0]!='\0') { file_data_t *pos_org=pos; const int pos_num_org=pos_num; while(strcmp(pos->name, needle)!=0 && pos->next!=NULL) { pos=pos->next; pos_num++; } if(strcmp(pos->name, needle)!=0) { pos=pos_org; pos_num=pos_num_org; } } } break; } if(pos_num<offset) offset=pos_num; if(pos_num>=offset+INTER_DIR) offset=pos_num-INTER_DIR+1; } } while(quit==0 && old_LINES==LINES); } while(quit==0); return -1; }