Message ID | 1393661175-459-6-git-send-email-liezhi.yang@windriver.com |
---|---|
State | Accepted, archived |
Headers | show |
I noticed a few things while merging -next into my dev tree... On Sat, Mar 01, 2014 at 03:06:09AM -0500, Robert Yang wrote: > The do_write_internal() is used for copying file from native fs to > target, most of the code are from debugfs/debugfs.c, the > debugfs/debugfs.c will be modified to use this function. > > Signed-off-by: Robert Yang <liezhi.yang@windriver.com> > Reviewed-by: Darren Hart <dvhart@linux.intel.com> > --- > misc/create_inode.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 183 insertions(+) > > diff --git a/misc/create_inode.c b/misc/create_inode.c > index f845103..98f4a93 100644 > --- a/misc/create_inode.c > +++ b/misc/create_inode.c > @@ -8,6 +8,16 @@ > # endif > #endif > > +/* 64KiB is the minimium blksize to best minimize system call overhead. */ > +#ifndef IO_BUFSIZE > +#define IO_BUFSIZE 64*1024 > +#endif > + > +/* Block size for `st_blocks' */ > +#ifndef S_BLKSIZE > +#define S_BLKSIZE 512 > +#endif > + > /* Make a special file which is block, character and fifo */ > errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) > { > @@ -127,9 +137,182 @@ errcode_t do_mkdir_internal(ext2_ino_t cwd, const char *name, struct stat *st) > { > } > > +static errcode_t copy_file(int fd, ext2_ino_t newfile, int bufsize, int make_holes) > +{ > + ext2_file_t e2_file; > + errcode_t retval; > + int got; > + unsigned int written; > + char *buf; > + char *ptr; > + char *zero_buf; > + int cmp; > + > + retval = ext2fs_file_open(current_fs, newfile, > + EXT2_FILE_WRITE, &e2_file); > + if (retval) > + return retval; > + > + retval = ext2fs_get_mem(bufsize, &buf); > + if (retval) { > + com_err("copy_file", retval, "can't allocate buffer\n"); > + return retval; > + } > + > + /* This is used for checking whether the whole block is zero */ > + retval = ext2fs_get_memzero(bufsize, &zero_buf); > + if (retval) { > + com_err("copy_file", retval, "can't allocate buffer\n"); > + ext2fs_free_mem(&buf); > + return retval; > + } > + > + while (1) { > + got = read(fd, buf, bufsize); > + if (got == 0) > + break; > + if (got < 0) { > + retval = errno; > + goto fail; > + } > + ptr = buf; > + > + /* Sparse copy */ > + if (make_holes) { > + /* Check whether all is zero */ > + cmp = memcmp(ptr, zero_buf, got); > + if (cmp == 0) { > + /* The whole block is zero, make a hole */ > + retval = ext2fs_file_lseek(e2_file, got, EXT2_SEEK_CUR, NULL); > + if (retval) > + goto fail; > + got = 0; > + } > + } > + > + /* Normal copy */ > + while (got > 0) { > + retval = ext2fs_file_write(e2_file, ptr, > + got, &written); > + if (retval) > + goto fail; > + > + got -= written; > + ptr += written; > + } > + } > + ext2fs_free_mem(&buf); > + ext2fs_free_mem(&zero_buf); > + retval = ext2fs_file_close(e2_file); > + return retval; > + > +fail: > + ext2fs_free_mem(&buf); > + ext2fs_free_mem(&zero_buf); > + (void) ext2fs_file_close(e2_file); > + return retval; > +} > + > /* Copy the native file to the fs */ > errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest) > { > + int fd; > + struct stat statbuf; > + ext2_ino_t newfile; > + errcode_t retval; > + struct ext2_inode inode; > + int bufsize = IO_BUFSIZE; > + int make_holes = 0; > + > + fd = open(src, O_RDONLY); > + if (fd < 0) { > + com_err(src, errno, 0); > + return errno; > + } > + if (fstat(fd, &statbuf) < 0) { > + com_err(src, errno, 0); > + close(fd); > + return errno; > + } > + > + retval = ext2fs_namei(current_fs, root, cwd, dest, &newfile); > + if (retval == 0) { > + com_err(__func__, 0, "The file '%s' already exists\n", dest); > + close(fd); > + return errno; > + } > + > + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); > + if (retval) { > + com_err(__func__, retval, 0); > + close(fd); > + return errno; Why return errno here, instead of retval? > + } > +#ifdef DEBUGFS > + printf("Allocated inode: %u\n", newfile); > +#endif > + retval = ext2fs_link(current_fs, cwd, dest, newfile, > + EXT2_FT_REG_FILE); > + if (retval == EXT2_ET_DIR_NO_SPACE) { > + retval = ext2fs_expand_dir(current_fs, cwd); > + if (retval) { > + com_err(__func__, retval, "while expanding directory"); > + close(fd); > + return errno; Or here... > + } > + retval = ext2fs_link(current_fs, cwd, dest, newfile, > + EXT2_FT_REG_FILE); > + } > + if (retval) { > + com_err(dest, retval, 0); > + close(fd); > + return errno; Or here... --D > + } > + if (ext2fs_test_inode_bitmap2(current_fs->inode_map, newfile)) > + com_err(__func__, 0, "Warning: inode already set"); > + ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); > + memset(&inode, 0, sizeof(inode)); > + inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; > + inode.i_atime = inode.i_ctime = inode.i_mtime = > + current_fs->now ? current_fs->now : time(0); > + inode.i_links_count = 1; > + inode.i_size = statbuf.st_size; > + if (current_fs->super->s_feature_incompat & > + EXT3_FEATURE_INCOMPAT_EXTENTS) { > + int i; > + struct ext3_extent_header *eh; > + > + eh = (struct ext3_extent_header *) &inode.i_block[0]; > + eh->eh_depth = 0; > + eh->eh_entries = 0; > + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); > + i = (sizeof(inode.i_block) - sizeof(*eh)) / > + sizeof(struct ext3_extent); > + eh->eh_max = ext2fs_cpu_to_le16(i); > + inode.i_flags |= EXT4_EXTENTS_FL; > + } > + > + if ((retval = ext2fs_write_new_inode(current_fs, newfile, &inode))) { > + com_err(__func__, retval, "while creating inode %u", newfile); > + close(fd); > + return errno; > + } > + if (LINUX_S_ISREG(inode.i_mode)) { > + if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) { > + make_holes = 1; > + /* > + * Use I/O blocksize as buffer size when > + * copying sparse files. > + */ > + bufsize = statbuf.st_blksize; > + } > + retval = copy_file(fd, newfile, bufsize, make_holes); > + if (retval) > + com_err("copy_file", retval, 0); > + } > + close(fd); > + > + return 0; > } > > /* Copy files from source_dir to fs */ > -- > 1.7.10.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Mar 06, 2014 at 11:06:22AM -0800, Darrick J. Wong wrote: > I noticed a few things while merging -next into my dev tree... Darrick, good catch! > > + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); > > + if (retval) { > > + com_err(__func__, retval, 0); > > + close(fd); > > + return errno; > > Why return errno here, instead of retval? Yep, we should do s/errno/retval/ at the places that you noted. Robert, since these are in next already, could you submit a patch to fixt this up? Thanks!! - Ted P.S. Fortunately, this isn't crypto code ala gnutls. :-) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Mar 06, 2014 at 02:47:15PM -0500, Theodore Ts'o wrote: > On Thu, Mar 06, 2014 at 11:06:22AM -0800, Darrick J. Wong wrote: > > I noticed a few things while merging -next into my dev tree... > > Darrick, good catch! > > > > + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); > > > + if (retval) { > > > + com_err(__func__, retval, 0); > > > + close(fd); > > > + return errno; > > > > Why return errno here, instead of retval? > > Yep, we should do s/errno/retval/ at the places that you noted. > > Robert, since these are in next already, could you submit a patch to > fixt this up? I'm already queuing up a bunch of (more) fixes... there's more weird things I didn't notice. Such as, why is current_fs now defined in current_inode.h? That really ought to have stayed in debugfs.c, and current_inode.h should have 'extern ext2_filsys current_fs;', no? Also there's a no-return-value 'return;' if the inline data write fails later down in that function, and I think it's time to pull in cppcheck on a make C=1 build. ...I'll also respin the patchset I sent out a few days ago. --D > > Thanks!! > > - Ted > > P.S. Fortunately, this isn't crypto code ala gnutls. :-) > > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Mar 06, 2014 at 12:14:39PM -0800, Darrick J. Wong wrote: > > I'm already queuing up a bunch of (more) fixes... there's more weird things I > didn't notice. Such as, why is current_fs now defined in current_inode.h? > That really ought to have stayed in debugfs.c, and current_inode.h should have > 'extern ext2_filsys current_fs;', no? Yes, that would be better --- although in the long term we should probably try to get rid of the global variable and pass in an "fs" parameter into functions in misc/create_inode.c. Since these aren't in a shared library, I wasn't worried that much about the details of the abstraction interface, but I'm sure there are some ways that we can improve things. BTW, one of my plans for 1.43 is to rename libquota.a to libe2int.a, and to move things like profile.c, and other files shared between misc and e2fsck, etc., into an "internal support" library. I suspect create_inoode.c would be a candidate for moving into this internal support library. Cheers, > ...I'll also respin the patchset I sent out a few days ago. Sorry for having you respin the patchset yet again --- although hopefully it should be easier this time around. I'm trying to be fair in catching up with th e2fsprogs backlog, and Robert and Zheng's patches have been outstanding for a long time. Don't worry, yours are next on the list. :-) Cheers, - Ted -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 03/07/2014 06:57 AM, Theodore Ts'o wrote: > On Thu, Mar 06, 2014 at 12:14:39PM -0800, Darrick J. Wong wrote: >> >> I'm already queuing up a bunch of (more) fixes... there's more weird things I >> didn't notice. Such as, why is current_fs now defined in current_inode.h? >> That really ought to have stayed in debugfs.c, and current_inode.h should have >> 'extern ext2_filsys current_fs;', no? > > Yes, that would be better --- although in the long term we should > probably try to get rid of the global variable and pass in an "fs" > parameter into functions in misc/create_inode.c. > > Since these aren't in a shared library, I wasn't worried that much > about the details of the abstraction interface, but I'm sure there are > some ways that we can improve things. > > BTW, one of my plans for 1.43 is to rename libquota.a to libe2int.a, > and to move things like profile.c, and other files shared between misc > and e2fsck, etc., into an "internal support" library. I suspect > create_inoode.c would be a candidate for moving into this internal > support library. > Hi Ted and Darrick, Thank you very much for the great help, I think that I don't have to submit a fix patch again since Darrick has helped me to fix the problem, please feel free to let me know if there is anything I can do. // Robert > Cheers, > >> ...I'll also respin the patchset I sent out a few days ago. > > Sorry for having you respin the patchset yet again --- although > hopefully it should be easier this time around. I'm trying to be fair > in catching up with th e2fsprogs backlog, and Robert and Zheng's > patches have been outstanding for a long time. Don't worry, yours are > next on the list. :-) > > Cheers, > > - Ted > > -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Mar 06, 2014 at 05:57:14PM -0500, Theodore Ts'o wrote: > On Thu, Mar 06, 2014 at 12:14:39PM -0800, Darrick J. Wong wrote: > > > > I'm already queuing up a bunch of (more) fixes... there's more weird things I > > didn't notice. Such as, why is current_fs now defined in current_inode.h? > > That really ought to have stayed in debugfs.c, and current_inode.h should have > > 'extern ext2_filsys current_fs;', no? > > Yes, that would be better --- although in the long term we should > probably try to get rid of the global variable and pass in an "fs" > parameter into functions in misc/create_inode.c. Agreed (and fixed). > Since these aren't in a shared library, I wasn't worried that much > about the details of the abstraction interface, but I'm sure there are > some ways that we can improve things. > > BTW, one of my plans for 1.43 is to rename libquota.a to libe2int.a, > and to move things like profile.c, and other files shared between misc > and e2fsck, etc., into an "internal support" library. I suspect > create_inoode.c would be a candidate for moving into this internal > support library. Higher level functionality? I'd been musing that such a thing might be beneficial to userland tools. > > Cheers, > > > ...I'll also respin the patchset I sent out a few days ago. > > Sorry for having you respin the patchset yet again --- although > hopefully it should be easier this time around. I'm trying to be fair > in catching up with th e2fsprogs backlog, and Robert and Zheng's > patches have been outstanding for a long time. Don't worry, yours are > next on the list. :-) It's fine, (st)git merging isn't usually that painful. I was more worried about the impact of spamming linux-ext4 with giant patchsets, but respinning is better than nothing happening at all. :) That said, combing through all the "new arrivals" when I run the static checkers ... was intense this time. Though, it is a little time consuming to run checkpatch, then sparse/cppcheck, then make check, then the metadata checksum test, and then xfstests. But, skipping tests isn't acceptable either, given the things I've fubar'd in the past from /not/ doing that. :) --D > > Cheers, > > - Ted > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Mar 07, 2014 at 09:24:12AM +0800, Robert Yang wrote: > > > On 03/07/2014 06:57 AM, Theodore Ts'o wrote: > >On Thu, Mar 06, 2014 at 12:14:39PM -0800, Darrick J. Wong wrote: > >> > >>I'm already queuing up a bunch of (more) fixes... there's more weird things I > >>didn't notice. Such as, why is current_fs now defined in current_inode.h? > >>That really ought to have stayed in debugfs.c, and current_inode.h should have > >>'extern ext2_filsys current_fs;', no? > > > >Yes, that would be better --- although in the long term we should > >probably try to get rid of the global variable and pass in an "fs" > >parameter into functions in misc/create_inode.c. > > > >Since these aren't in a shared library, I wasn't worried that much > >about the details of the abstraction interface, but I'm sure there are > >some ways that we can improve things. > > > >BTW, one of my plans for 1.43 is to rename libquota.a to libe2int.a, > >and to move things like profile.c, and other files shared between misc > >and e2fsck, etc., into an "internal support" library. I suspect > >create_inoode.c would be a candidate for moving into this internal > >support library. > > > > Hi Ted and Darrick, > > Thank you very much for the great help, I think that I don't have to > submit a fix patch again since Darrick has helped me to fix the > problem, please feel free to let me know if there is anything I > can do. I'll have 6 patches for you to review soon. I also fixed a number of style and whitespace errors. :) I had another thought about populate_fs -- it should be in charge of setting up and tearing down the hdlinks_s hardlink map, not the caller, and it shouldn't really be a global variable. I noticed that populate_fs recursively calls itself, so I moved the functionality to a static function and wrote a wrapper that takes care of hdlinks and calls the static function. By the way, one of the things I /didn't/ fix was the root inode parameter that you pass to ext2fs_namei. I couldn't tell if supporting debugfs' chroot command is part of your requirements set (though it doesn't seem likely to me), but I also think that a better interface would be to have callers of the create_inode functions pass in the destination dir inode instead of a pathname, similar to the do_mknod_internal interface. debugfs is the only tool that knows about the notion of a 'chroot'; the rest would seem to do all namei operations starting at EXT2_ROOT_INO. Also I recommend running sparse/cppcheck on any source files that a patch of yours touches. --D > > // Robert > > >Cheers, > > > >>...I'll also respin the patchset I sent out a few days ago. > > > >Sorry for having you respin the patchset yet again --- although > >hopefully it should be easier this time around. I'm trying to be fair > >in catching up with th e2fsprogs backlog, and Robert and Zheng's > >patches have been outstanding for a long time. Don't worry, yours are > >next on the list. :-) > > > >Cheers, > > > > - Ted > > > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 03/07/2014 10:56 AM, Darrick J. Wong wrote: > On Fri, Mar 07, 2014 at 09:24:12AM +0800, Robert Yang wrote: >> >> >> On 03/07/2014 06:57 AM, Theodore Ts'o wrote: >>> On Thu, Mar 06, 2014 at 12:14:39PM -0800, Darrick J. Wong wrote: >>>> >>>> I'm already queuing up a bunch of (more) fixes... there's more weird things I >>>> didn't notice. Such as, why is current_fs now defined in current_inode.h? >>>> That really ought to have stayed in debugfs.c, and current_inode.h should have >>>> 'extern ext2_filsys current_fs;', no? >>> >>> Yes, that would be better --- although in the long term we should >>> probably try to get rid of the global variable and pass in an "fs" >>> parameter into functions in misc/create_inode.c. >>> >>> Since these aren't in a shared library, I wasn't worried that much >>> about the details of the abstraction interface, but I'm sure there are >>> some ways that we can improve things. >>> >>> BTW, one of my plans for 1.43 is to rename libquota.a to libe2int.a, >>> and to move things like profile.c, and other files shared between misc >>> and e2fsck, etc., into an "internal support" library. I suspect >>> create_inoode.c would be a candidate for moving into this internal >>> support library. >>> >> >> Hi Ted and Darrick, >> >> Thank you very much for the great help, I think that I don't have to >> submit a fix patch again since Darrick has helped me to fix the >> problem, please feel free to let me know if there is anything I >> can do. > > I'll have 6 patches for you to review soon. I also fixed a number of style and > whitespace errors. :) > Thank you very much:-) > I had another thought about populate_fs -- it should be in charge of setting up > and tearing down the hdlinks_s hardlink map, not the caller, and it shouldn't > really be a global variable. I noticed that populate_fs recursively calls > itself, so I moved the functionality to a static function and wrote a wrapper > that takes care of hdlinks and calls the static function. > > By the way, one of the things I /didn't/ fix was the root inode parameter that > you pass to ext2fs_namei. I couldn't tell if supporting debugfs' chroot > command is part of your requirements set (though it doesn't seem likely to me), > but I also think that a better interface would be to have callers of the > create_inode functions pass in the destination dir inode instead of a pathname, > similar to the do_mknod_internal interface. debugfs is the only tool that > knows about the notion of a 'chroot'; the rest would seem to do all namei > operations starting at EXT2_ROOT_INO. > Thank you very much, I will try later. > Also I recommend running sparse/cppcheck on any source files that a patch of > yours touches. > Thanks, got it. // Robert > --D >> >> // Robert >> >>> Cheers, >>> >>>> ...I'll also respin the patchset I sent out a few days ago. >>> >>> Sorry for having you respin the patchset yet again --- although >>> hopefully it should be easier this time around. I'm trying to be fair >>> in catching up with th e2fsprogs backlog, and Robert and Zheng's >>> patches have been outstanding for a long time. Don't worry, yours are >>> next on the list. :-) >>> >>> Cheers, >>> >>> - Ted >>> >>> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/misc/create_inode.c b/misc/create_inode.c index f845103..98f4a93 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -8,6 +8,16 @@ # endif #endif +/* 64KiB is the minimium blksize to best minimize system call overhead. */ +#ifndef IO_BUFSIZE +#define IO_BUFSIZE 64*1024 +#endif + +/* Block size for `st_blocks' */ +#ifndef S_BLKSIZE +#define S_BLKSIZE 512 +#endif + /* Make a special file which is block, character and fifo */ errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) { @@ -127,9 +137,182 @@ errcode_t do_mkdir_internal(ext2_ino_t cwd, const char *name, struct stat *st) { } +static errcode_t copy_file(int fd, ext2_ino_t newfile, int bufsize, int make_holes) +{ + ext2_file_t e2_file; + errcode_t retval; + int got; + unsigned int written; + char *buf; + char *ptr; + char *zero_buf; + int cmp; + + retval = ext2fs_file_open(current_fs, newfile, + EXT2_FILE_WRITE, &e2_file); + if (retval) + return retval; + + retval = ext2fs_get_mem(bufsize, &buf); + if (retval) { + com_err("copy_file", retval, "can't allocate buffer\n"); + return retval; + } + + /* This is used for checking whether the whole block is zero */ + retval = ext2fs_get_memzero(bufsize, &zero_buf); + if (retval) { + com_err("copy_file", retval, "can't allocate buffer\n"); + ext2fs_free_mem(&buf); + return retval; + } + + while (1) { + got = read(fd, buf, bufsize); + if (got == 0) + break; + if (got < 0) { + retval = errno; + goto fail; + } + ptr = buf; + + /* Sparse copy */ + if (make_holes) { + /* Check whether all is zero */ + cmp = memcmp(ptr, zero_buf, got); + if (cmp == 0) { + /* The whole block is zero, make a hole */ + retval = ext2fs_file_lseek(e2_file, got, EXT2_SEEK_CUR, NULL); + if (retval) + goto fail; + got = 0; + } + } + + /* Normal copy */ + while (got > 0) { + retval = ext2fs_file_write(e2_file, ptr, + got, &written); + if (retval) + goto fail; + + got -= written; + ptr += written; + } + } + ext2fs_free_mem(&buf); + ext2fs_free_mem(&zero_buf); + retval = ext2fs_file_close(e2_file); + return retval; + +fail: + ext2fs_free_mem(&buf); + ext2fs_free_mem(&zero_buf); + (void) ext2fs_file_close(e2_file); + return retval; +} + /* Copy the native file to the fs */ errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest) { + int fd; + struct stat statbuf; + ext2_ino_t newfile; + errcode_t retval; + struct ext2_inode inode; + int bufsize = IO_BUFSIZE; + int make_holes = 0; + + fd = open(src, O_RDONLY); + if (fd < 0) { + com_err(src, errno, 0); + return errno; + } + if (fstat(fd, &statbuf) < 0) { + com_err(src, errno, 0); + close(fd); + return errno; + } + + retval = ext2fs_namei(current_fs, root, cwd, dest, &newfile); + if (retval == 0) { + com_err(__func__, 0, "The file '%s' already exists\n", dest); + close(fd); + return errno; + } + + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); + if (retval) { + com_err(__func__, retval, 0); + close(fd); + return errno; + } +#ifdef DEBUGFS + printf("Allocated inode: %u\n", newfile); +#endif + retval = ext2fs_link(current_fs, cwd, dest, newfile, + EXT2_FT_REG_FILE); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, cwd); + if (retval) { + com_err(__func__, retval, "while expanding directory"); + close(fd); + return errno; + } + retval = ext2fs_link(current_fs, cwd, dest, newfile, + EXT2_FT_REG_FILE); + } + if (retval) { + com_err(dest, retval, 0); + close(fd); + return errno; + } + if (ext2fs_test_inode_bitmap2(current_fs->inode_map, newfile)) + com_err(__func__, 0, "Warning: inode already set"); + ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; + inode.i_atime = inode.i_ctime = inode.i_mtime = + current_fs->now ? current_fs->now : time(0); + inode.i_links_count = 1; + inode.i_size = statbuf.st_size; + if (current_fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_EXTENTS) { + int i; + struct ext3_extent_header *eh; + + eh = (struct ext3_extent_header *) &inode.i_block[0]; + eh->eh_depth = 0; + eh->eh_entries = 0; + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); + i = (sizeof(inode.i_block) - sizeof(*eh)) / + sizeof(struct ext3_extent); + eh->eh_max = ext2fs_cpu_to_le16(i); + inode.i_flags |= EXT4_EXTENTS_FL; + } + + if ((retval = ext2fs_write_new_inode(current_fs, newfile, &inode))) { + com_err(__func__, retval, "while creating inode %u", newfile); + close(fd); + return errno; + } + if (LINUX_S_ISREG(inode.i_mode)) { + if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) { + make_holes = 1; + /* + * Use I/O blocksize as buffer size when + * copying sparse files. + */ + bufsize = statbuf.st_blksize; + } + retval = copy_file(fd, newfile, bufsize, make_holes); + if (retval) + com_err("copy_file", retval, 0); + } + close(fd); + + return 0; } /* Copy files from source_dir to fs */