static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, ext2_ino_t inode, int link_count, char *buf, ext2_ino_t *res_inode) { char *pathname; char *buffer = 0; errcode_t retval; struct ext2_inode ei; blk64_t blk; #ifdef NAMEI_DEBUG printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", root, dir, inode, link_count); #endif retval = ext2fs_read_inode (fs, inode, &ei); if (retval) return retval; if (!LINUX_S_ISLNK (ei.i_mode)) { *res_inode = inode; return 0; } if (link_count++ >= EXT2FS_MAX_NESTED_LINKS) return EXT2_ET_SYMLINK_LOOP; if (ext2fs_inode_data_blocks(fs,&ei)) { retval = ext2fs_bmap2(fs, inode, &ei, NULL, 0, 0, NULL, &blk); if (retval) return retval; retval = ext2fs_get_mem(fs->blocksize, &buffer); if (retval) return retval; retval = io_channel_read_blk64(fs->io, blk, 1, buffer); if (retval) { ext2fs_free_mem(&buffer); return retval; } pathname = buffer; } else pathname = (char *)&(ei.i_block[0]); retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, link_count, buf, res_inode); if (buffer) ext2fs_free_mem(&buffer); return retval; }
static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, ext2_ino_t inode, int link_count, char *buf, ext2_ino_t *res_inode) { char *pathname; char *buffer = 0; errcode_t retval; struct ext2_inode ei; #ifdef NAMEI_DEBUG printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", root, dir, inode, link_count); #endif retval = ext2fs_read_inode (fs, inode, &ei); if (retval) return retval; if (!LINUX_S_ISLNK (ei.i_mode)) { *res_inode = inode; return 0; } if (link_count++ > 5) { return EXT2_ET_SYMLINK_LOOP; } /* FIXME-64: Actually, this is FIXME EXTENTS */ if (ext2fs_inode_data_blocks(fs,&ei)) { retval = ext2fs_get_mem(fs->blocksize, &buffer); if (retval) return retval; retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer); if (retval) { ext2fs_free_mem(&buffer); return retval; } pathname = buffer; } else pathname = (char *)&(ei.i_block[0]); retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, link_count, buf, res_inode); if (buffer) ext2fs_free_mem(&buffer); return retval; }
void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, struct ext2_inode_large *f, int hostorder, int bufsize) { unsigned i, has_data_blocks, extra_isize, attr_magic; int has_extents = 0; int islnk = 0; __u32 *eaf, *eat; if (hostorder && LINUX_S_ISLNK(f->i_mode)) islnk = 1; t->i_mode = ext2fs_swab16(f->i_mode); if (!hostorder && LINUX_S_ISLNK(t->i_mode)) islnk = 1; t->i_uid = ext2fs_swab16(f->i_uid); t->i_size = ext2fs_swab32(f->i_size); t->i_atime = ext2fs_swab32(f->i_atime); t->i_ctime = ext2fs_swab32(f->i_ctime); t->i_mtime = ext2fs_swab32(f->i_mtime); t->i_dtime = ext2fs_swab32(f->i_dtime); t->i_gid = ext2fs_swab16(f->i_gid); t->i_links_count = ext2fs_swab16(f->i_links_count); t->i_file_acl = ext2fs_swab32(f->i_file_acl); if (hostorder) has_data_blocks = ext2fs_inode_data_blocks(fs, (struct ext2_inode *) f); t->i_blocks = ext2fs_swab32(f->i_blocks); if (!hostorder) has_data_blocks = ext2fs_inode_data_blocks(fs, (struct ext2_inode *) t); if (hostorder && (f->i_flags & EXT4_EXTENTS_FL)) has_extents = 1; t->i_flags = ext2fs_swab32(f->i_flags); if (!hostorder && (t->i_flags & EXT4_EXTENTS_FL)) has_extents = 1; t->i_dir_acl = ext2fs_swab32(f->i_dir_acl); if (!has_extents && (!islnk || has_data_blocks)) { for (i = 0; i < EXT2_N_BLOCKS; i++) t->i_block[i] = ext2fs_swab32(f->i_block[i]); } else if (t != f) { for (i = 0; i < EXT2_N_BLOCKS; i++) t->i_block[i] = f->i_block[i]; } t->i_generation = ext2fs_swab32(f->i_generation); t->i_faddr = ext2fs_swab32(f->i_faddr); switch (fs->super->s_creator_os) { case EXT2_OS_LINUX: t->osd1.linux1.l_i_version = ext2fs_swab32(f->osd1.linux1.l_i_version); t->osd2.linux2.l_i_blocks_hi = ext2fs_swab16(f->osd2.linux2.l_i_blocks_hi); t->osd2.linux2.l_i_file_acl_high = ext2fs_swab16(f->osd2.linux2.l_i_file_acl_high); t->osd2.linux2.l_i_uid_high = ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); t->osd2.linux2.l_i_gid_high = ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); t->osd2.linux2.l_i_reserved2 = ext2fs_swab32(f->osd2.linux2.l_i_reserved2); break; case EXT2_OS_HURD: t->osd1.hurd1.h_i_translator = ext2fs_swab32 (f->osd1.hurd1.h_i_translator); t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; t->osd2.hurd2.h_i_mode_high = ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); t->osd2.hurd2.h_i_uid_high = ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); t->osd2.hurd2.h_i_gid_high = ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); t->osd2.hurd2.h_i_author = ext2fs_swab32 (f->osd2.hurd2.h_i_author); break; default: break; } if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) return; if (hostorder) extra_isize = f->i_extra_isize; t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); if (!hostorder) extra_isize = t->i_extra_isize; if (extra_isize > EXT2_INODE_SIZE(fs->super) - sizeof(struct ext2_inode)) { return; } i = sizeof(struct ext2_inode) + extra_isize + sizeof(__u32); if (bufsize < (int) i) return; eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + extra_isize); attr_magic = *eaf; if (!hostorder) attr_magic = ext2fs_swab32(attr_magic); if (attr_magic != EXT2_EXT_ATTR_MAGIC) return; eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + extra_isize); *eat = ext2fs_swab32(*eaf); ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), bufsize - sizeof(struct ext2_inode) - extra_isize - sizeof(__u32), 0); }
// recover Datafile int recover_file( char* des_dir,char* pathname, char* filename, struct ext2_inode *inode, ext2_ino_t inode_nr, int flag){ int rec_error = 255; char err_string[9]; int retval =-1; int hardlink = 0; char i = 0; char *buf=NULL; struct privat priv; struct stat filestat; char *helpname = NULL; char *recovername = NULL; char *linkname = NULL; char *p1; unsigned long long i_size; struct utimbuf touchtime; mode_t i_mode; int major, minor, type; #ifdef DEBUG printf("RECOVER : INODE=%ld FILENAME=%s/%s\n",inode_nr, pathname,filename); dump_inode(stdout, "",inode_nr, (struct ext2_inode *)inode, 0); #endif if (!(inode->i_mode & LINUX_S_IFMT)) //no type flag - no recover return 1; p1 = pathname; while (*p1 == '/') p1++; helpname = malloc(strlen(des_dir) + 15); recovername = malloc(strlen(des_dir) + strlen(pathname) + strlen(filename) +10); if (helpname && recovername){ strcpy(helpname,des_dir); strcat(helpname,"/"); strcpy(recovername,helpname); strcat(recovername,p1); if (strlen(p1)) strcat(recovername,"/"); strcat(recovername,filename); while (!(stat(recovername, &filestat)) && (i<5)){ strcat(recovername,"#"); i++; } p1 = strchr(helpname,0); sprintf(p1,"#%u#",inode_nr); unlink (helpname); priv.flag = flag; //FIXME: hardlink if (inode->i_links_count > 1){ p1 = check_link_stack(inode_nr, inode->i_generation); if (p1) { //hardlink found if (! stat(p1, &filestat)){ retval = check_dir(recovername); if (retval) fprintf(stderr,"Unknown error at target directory by file: %s\ntrying to continue normal\n", recovername); else { if (! link(p1,recovername)){ if (match_link_stack(inode_nr, inode->i_generation)) rec_error -= CREATE_ERROR ; goto out; } else{ rec_error -= CREATE_ERROR ; } } } } else{ //flag as hardlink hardlink = 1; } } switch (inode->i_mode & LINUX_S_IFMT){ //regular File; case LINUX_S_IFREG : priv.fd = open(helpname, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRWXU); if (! priv.fd ){ fprintf(stderr,"Error: open File %s for writing\n",helpname); retval = errno; goto errout; } buf=malloc(current_fs->blocksize); if (buf) { priv.buf = buf; priv.error = 0; // iterate Data Blocks and if not allocated, write to file retval = local_block_iterate3 ( current_fs, *inode, BLOCK_FLAG_DATA_ONLY, NULL, write_block, &priv ); #ifdef DEBUG printf("\n"); #endif if (retval || priv.error){ // error or blocks allocated , we delete the tempfile and goto out close(priv.fd); unlink(helpname); retval = -1; goto errout; } else{ i_size = (unsigned long long)(inode->i_size | ((unsigned long long)inode->i_size_high << 32)); retval = ftruncate(priv.fd,i_size); if (retval){ rec_error -= SEEK_ERROR ; } } } else { fprintf(stderr,"ERROR: can no allocate memory\n"); retval = -1; close(priv.fd); goto errout; } close(priv.fd); break; //symbolic link case LINUX_S_IFLNK : if (ext2fs_inode_data_blocks(current_fs,inode)){ buf = malloc(current_fs->blocksize + 1); if (buf) { memset(buf,0,current_fs->blocksize + 1); priv.buf = buf; priv.error = 0; retval = local_block_iterate3 ( current_fs, *inode, BLOCK_FLAG_DATA_ONLY, NULL, read_syslink_block, &priv ); if (retval || priv.error) goto errout; } else { fprintf(stderr,"ERROR: can no allocate memory\n"); retval = -1; goto errout; } } else { int i; if((! inode->i_size) || (inode->i_size >= 60)) goto errout; buf = malloc(inode->i_size + 1); linkname = (char*) &(inode->i_block[0]); for (i = 0; i < inode->i_size ; i++){ *(buf+i) = (char) *linkname; linkname++; } *(buf+i) = 0; } linkname = buf; retval = symlink(linkname, helpname); if (retval){ rec_error -= (CREATE_ERROR + SEEK_ERROR); } break; //block or char device case LINUX_S_IFBLK : case LINUX_S_IFCHR : type = (LINUX_S_ISBLK(inode->i_mode)) ? S_IFBLK : S_IFCHR ; if (inode->i_block[0]) { major = (inode->i_block[0] >> 8) & 255; minor = inode->i_block[0] & 255; } else {
void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, struct ext2_inode_large *f, int hostorder, int bufsize) { unsigned i; int islnk = 0; __u32 *eaf, *eat; if (hostorder && LINUX_S_ISLNK(f->i_mode)) islnk = 1; t->i_mode = ext2fs_swab16(f->i_mode); if (!hostorder && LINUX_S_ISLNK(t->i_mode)) islnk = 1; t->i_uid = ext2fs_swab16(f->i_uid); t->i_size = ext2fs_swab32(f->i_size); t->i_atime = ext2fs_swab32(f->i_atime); t->i_ctime = ext2fs_swab32(f->i_ctime); t->i_mtime = ext2fs_swab32(f->i_mtime); t->i_dtime = ext2fs_swab32(f->i_dtime); t->i_gid = ext2fs_swab16(f->i_gid); t->i_links_count = ext2fs_swab16(f->i_links_count); t->i_blocks = ext2fs_swab32(f->i_blocks); t->i_flags = ext2fs_swab32(f->i_flags); t->i_file_acl = ext2fs_swab32(f->i_file_acl); t->i_dir_acl = ext2fs_swab32(f->i_dir_acl); if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) { for (i = 0; i < EXT2_N_BLOCKS; i++) t->i_block[i] = ext2fs_swab32(f->i_block[i]); } else if (t != f) { for (i = 0; i < EXT2_N_BLOCKS; i++) t->i_block[i] = f->i_block[i]; } t->i_generation = ext2fs_swab32(f->i_generation); t->i_faddr = ext2fs_swab32(f->i_faddr); switch (fs->super->s_creator_os) { case EXT2_OS_LINUX: t->osd1.linux1.l_i_reserved1 = ext2fs_swab32(f->osd1.linux1.l_i_reserved1); t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag; t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize; t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1); t->osd2.linux2.l_i_uid_high = ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); t->osd2.linux2.l_i_gid_high = ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); t->osd2.linux2.l_i_reserved2 = ext2fs_swab32(f->osd2.linux2.l_i_reserved2); break; case EXT2_OS_HURD: t->osd1.hurd1.h_i_translator = ext2fs_swab32 (f->osd1.hurd1.h_i_translator); t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; t->osd2.hurd2.h_i_mode_high = ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); t->osd2.hurd2.h_i_uid_high = ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); t->osd2.hurd2.h_i_gid_high = ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); t->osd2.hurd2.h_i_author = ext2fs_swab32 (f->osd2.hurd2.h_i_author); break; case EXT2_OS_MASIX: t->osd1.masix1.m_i_reserved1 = ext2fs_swab32(f->osd1.masix1.m_i_reserved1); t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag; t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize; t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1); t->osd2.masix2.m_i_reserved2[0] = ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]); t->osd2.masix2.m_i_reserved2[1] = ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]); break; } if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) return; /* no i_extra_isize field */ t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) - sizeof(struct ext2_inode)) { /* this is error case: i_extra_size is too large */ return; } i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32); if (bufsize < (int) i) return; /* no space for EA magic */ eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + f->i_extra_isize); if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC) return; /* it seems no magic here */ eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + f->i_extra_isize); *eat = ext2fs_swab32(*eaf); /* convert EA(s) */ ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), bufsize - sizeof(struct ext2_inode) - t->i_extra_isize - sizeof(__u32), 0); }
int op_readlink (const char *path, char *buf, size_t size) { int rt; size_t s; errcode_t rc; ext2_ino_t ino; char *b = NULL; char *pathname; struct ext2_inode inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_readinode(e2fs, path, &ino, &inode); if (rt) { debugf("do_readinode(%s, &ino, &inode); failed", path); goto err; } if (!LINUX_S_ISLNK(inode.i_mode)) { debugf("%s is not a link", path); rt = -EINVAL; goto err; } if (ext2fs_inode_data_blocks(e2fs, &inode)) { rc = ext2fs_get_mem(EXT2_BLOCK_SIZE(e2fs->super), &b); if (rc) { debugf("ext2fs_get_mem(EXT2_BLOCK_SIZE(e2fs->super), &b); failed"); rt = -ENOMEM; goto err; } rc = io_channel_read_blk(e2fs->io, inode.i_block[0], 1, b); if (rc) { ext2fs_free_mem(&b); debugf("io_channel_read_blk(e2fs->io, inode.i_block[0], 1, b); failed"); rt = -EIO; goto err; } pathname = b; } else { pathname = (char *) &(inode.i_block[0]); } debugf("pathname: %s", pathname); s = (size < strlen(pathname) + 1) ? size : strlen(pathname) + 1; snprintf(buf, s, "%s", pathname); if (b) { ext2fs_free_mem(&b); } debugf("leave"); FUSE_EXT2_UNLOCK; return 0; err: FUSE_EXT2_UNLOCK; return rt; }