"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "fsmove/src/io/io_posix.cc" between
fstransform-0.9.3-src.tar.gz and fstransform-0.9.4.tar.gz

About: fstransform is a tool to change a file-system from one format to another, for example from jfs, xfs, or reiser to ext2, ext3, or ext4, in-place and without the need for backup.

io_posix.cc  (fstransform-0.9.3-src):io_posix.cc  (fstransform-0.9.4)
skipping to change at line 80 skipping to change at line 80
#ifdef FT_HAVE_UTIME_H #ifdef FT_HAVE_UTIME_H
# include <utime.h> // " " " # include <utime.h> // " " "
#endif #endif
#include "../assert.hh" // for ff_assert() #include "../assert.hh" // for ff_assert()
#include "../log.hh" // for ff_log() #include "../log.hh" // for ff_log()
#include "../misc.hh" // for ff_min2() #include "../misc.hh" // for ff_min2()
#include "disk_stat.hh" // for fm_disk_stat::THRESHOLD_MIN #include "disk_stat.hh" // for fm_disk_stat::THRESHOLD_MIN
#include "io_posix.hh" // for fm_io_posix #include "io_posix.hh" // for fm_io_posix
#include "io_posix_dir.hh" // for fm_io_posix_dir #include "io_posix_dir.hh" // for ft_io_posix_dir
#include "util_posix.hh" // for ff_posix_exec_silent() #include "util_posix.hh" // for ff_posix_exec_silent()
#ifndef PATH_MAX #ifndef PATH_MAX
# define PATH_MAX 4096 # define PATH_MAX 4096
#endif /* PATH_MAX */ #endif /* PATH_MAX */
FT_IO_NAMESPACE_BEGIN FT_IO_NAMESPACE_BEGIN
/** default constructor */ /** default constructor */
fm_io_posix::fm_io_posix() fm_io_posix::fm_io_posix()
skipping to change at line 146 skipping to change at line 146
return half_free_space > bytes_to_write return half_free_space > bytes_to_write
&& half_free_space - bytes_to_write > bytes_copied_since_last_check; && half_free_space - bytes_to_write > bytes_copied_since_last_check;
} }
/** /**
* add bytes_just_written to bytes_copied_since_last_check. * add bytes_just_written to bytes_copied_since_last_check.
* *
* if bytes_copied_since_last_check >= PERIODIC_CHECK_FREE_SPACE or >= 50% of fr ee space, * if bytes_copied_since_last_check >= PERIODIC_CHECK_FREE_SPACE or >= 50% of fr ee space,
* reset bytes_copied_since_last_check to zero and call check_free_space() * reset bytes_copied_since_last_check to zero and call check_free_space()
*/ */
int fm_io_posix::periodic_check_free_space(ft_size bytes_just_written, ft_uoff b ytes_to_write) int fm_io_posix::periodic_check_free_space(ft_uoff bytes_just_written, ft_uoff b ytes_to_write)
{ {
add_work_done(bytes_just_written); add_work_done(bytes_just_written);
bytes_copied_since_last_check += bytes_just_written; bytes_copied_since_last_check += bytes_just_written;
int err = 0; int err = 0;
if (!enough_free_space(bytes_to_write)) { if (!enough_free_space(bytes_to_write)) {
bytes_copied_since_last_check = 0; bytes_copied_since_last_check = 0;
err = check_free_space(); err = check_free_space();
} }
return err; return err;
} }
/** /**
* call 'disk_stat' twice: one time on source_root() and another on target_root( ). * sync(), then call disk_stat() twice: one time on source_root() and another on target_root().
* return error if statvfs() fails or if free disk space becomes critically low * return error if statvfs() fails or if free disk space becomes critically low
*/ */
int fm_io_posix::check_free_space() int fm_io_posix::check_free_space()
{ {
::sync(); // slow, but needed to get accurate disk stats when loop devices a re involved sync(); // slow, but needed to get accurate disk stats when loop devices are involved
int err = disk_stat(source_root().c_str(), source_stat()); int err = disk_stat(source_root().c_str(), source_stat());
if (err == 0) if (err == 0)
err = disk_stat(target_root().c_str(), target_stat()); err = disk_stat(target_root().c_str(), target_stat());
return err; return err;
} }
/** call ::sync(). slow, but needed to get accurate disk stats when loop devices
are involved */
void fm_io_posix::sync()
{
::sync();
}
/** /**
* fill 'disk_stat' with information about the file-system containing 'path'. * fill 'disk_stat' with information about the file-system containing 'path'.
* return error if statvfs() fails or if free disk space becomes critically low * return error if statvfs() fails or if free disk space becomes critically low
*/ */
int fm_io_posix::disk_stat(const char * path, fm_disk_stat & disk_stat) int fm_io_posix::disk_stat(const char * path, fm_disk_stat & disk_stat)
{ {
struct statvfs buf; struct statvfs buf;
int err = 0; int err = 0;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
skipping to change at line 204 skipping to change at line 210
} }
err = disk_stat.set_free(disk_free); err = disk_stat.set_free(disk_free);
break; break;
} }
return err; return err;
} }
/** /**
* use some file-system specific trickery and try to free some space. * use some file-system specific trickery and try to free some space.
*/ */
void fm_io_posix::try_to_make_free_space(const char * path) void fm_io_posix::try_to_make_free_space(const char * FT_ARG_UNUSED(path))
{ {
#if 0 #if 0
/* /*
* we COULD run 'xfs_fsr <path>' and try to free some space on 'xfs' file-sy stems, * we COULD run 'xfs_fsr <path>' and try to free some space on 'xfs' file-sy stems,
* but at least on linux with an almost-full source device * but at least on linux with an almost-full source device
* xfs_fsr can WORSEN the problem by triggering 'loop write error' kernel er rors, * xfs_fsr can WORSEN the problem by triggering 'loop write error' kernel er rors,
* which mean the source device has not enough space to accommodate the loop file contents. * which mean the source device has not enough space to accommodate the loop file contents.
* typically this CORRUPTS the file system inside target (loop) device! * this typically CORRUPTS the file system inside target (loop) device!
*/ */
const char * cmd = "xfs_fsr"; const char * cmd = "xfs_fsr";
const char * const args[] = { cmd, path, NULL }; const char * const args[] = { cmd, path, NULL };
if (ff_posix_exec_silent(cmd, args) == 0) if (ff_posix_exec_silent(cmd, args) == 0)
ff_log(FC_INFO, 0, "successfully executed '%s %s' to free some disk spac e", args[0], args[1]); ff_log(FC_INFO, 0, "successfully executed '%s %s' to free some disk spac e", args[0], args[1]);
#endif #endif
} }
/** /**
skipping to change at line 272 skipping to change at line 278
/** /**
* move a single file/socket/special-device or a whole directory tree * move a single file/socket/special-device or a whole directory tree
*/ */
int fm_io_posix::move(const ft_string & source_path, const ft_string & target_pa th) int fm_io_posix::move(const ft_string & source_path, const ft_string & target_pa th)
{ {
ft_stat stat; ft_stat stat;
const std::set<ft_string> & exclude_set = this->exclude_set(); const std::set<ft_string> & exclude_set = this->exclude_set();
int err = 0; int err = 0;
ff_log(FC_DEBUG, 0, "move() `%s'\t-> `%s'", source_path.c_str(), tar get_path.c_str()); ff_log(FC_DEBUG, 0, "`%s'\t-> `%s'", source_path.c_str(), target_path.c_str( ));
do { do {
if (exclude_set.count(source_path) != 0) { if (exclude_set.count(source_path) != 0) {
ff_log(FC_INFO, 0, "move() skipped `%s', matches exclude list", sour ce_path.c_str()); ff_log(FC_INFO, 0, "skipped `%s', matches exclude list", source_path .c_str());
break; break;
} }
if ((err = this->stat(source_path, stat)) != 0) if ((err = this->stat(source_path, stat)) != 0)
break; break;
if (fm_io_posix_is_file(stat)) { if (fm_io_posix_is_file(stat)) {
err = this->move_file(source_path, stat, target_path); err = this->move_file(source_path, stat, target_path);
break; break;
} else if (!fm_io_posix_is_dir(stat)) { } else if (!fm_io_posix_is_dir(stat)) {
err = this->move_special(source_path, stat, target_path); err = this->move_special(source_path, stat, target_path);
break; break;
} }
fm_io_posix_dir source_dir; ft_io_posix_dir source_dir;
if ((err = source_dir.open(source_path))) if ((err = source_dir.open(source_path)))
break; break;
/* /*
* we allow target_root() to exist already, but other target directories must NOT exist. * we allow target_root() to exist already, but other target directories must NOT exist.
* option '-f' drops this check, i.e. any target directory can exist alr eady * option '-f' drops this check, i.e. any target directory can exist alr eady
* *
* Exception: we allow a 'lost+found' directory to exist inside target_r oot() * Exception: we allow a 'lost+found' directory to exist inside target_r oot()
*/ */
if ((err = this->create_dir(target_path)) != 0) if ((err = this->create_dir(target_path)) != 0)
break; break;
if ((err = this->periodic_check_free_space()) != 0) if ((err = this->periodic_check_free_space()) != 0)
break; break;
ft_string child_source = source_path, child_target = target_path; ft_string child_source = source_path, child_target = target_path;
child_source += '/'; child_source += '/';
child_target += '/'; child_target += '/';
fm_io_posix_dirent * dirent; ft_io_posix_dirent * dirent;
/* recurse on directory contents */ /* recurse on directory contents */
while ((err = source_dir.next(dirent)) == 0 && dirent != NULL) { while ((err = source_dir.next(dirent)) == 0 && dirent != NULL) {
/* skip "." and ".." */ /* skip "." and ".." */
if (!strcmp(".", dirent->d_name) || !strcmp("..", dirent->d_name)) if (!strcmp(".", dirent->d_name) || !strcmp("..", dirent->d_name))
continue; continue;
child_source.resize(1 + source_path.size()); // faster than child_so urce = source_path + '/' child_source.resize(1 + source_path.size()); // faster than child_so urce = source_path + '/'
child_source += dirent->d_name; child_source += dirent->d_name;
skipping to change at line 376 skipping to change at line 382
/* check inode_cache for hard links and recreate them */ /* check inode_cache for hard links and recreate them */
err = this->hard_link(stat, target_path); err = this->hard_link(stat, target_path);
if (err == 0) { if (err == 0) {
/** hard link succeeded, no need to create the special-device */ /** hard link succeeded, no need to create the special-device */
err = this->periodic_check_free_space(); err = this->periodic_check_free_space();
break; break;
} else if (err == EAGAIN) { } else if (err == EAGAIN) {
/* no luck with inode_cache, proceed as usual */ /* no luck with inode_cache, proceed as usual */
err = 0; err = 0;
} else { } else {
/** hard link failed */ /** hard link() failed */
return err; return err;
} }
/* found a special device */ /* found a special device */
if (S_ISCHR(stat.st_mode) || S_ISBLK(stat.st_mode) || S_ISSOCK(stat.st_m ode)) { if (S_ISCHR(stat.st_mode) || S_ISBLK(stat.st_mode) || S_ISSOCK(stat.st_m ode)) {
if (mknod(target, (stat.st_mode | 0600) & ~0077, stat.st_rdev) != 0) { if (mknod(target, (stat.st_mode | 0600) & ~0077, stat.st_rdev) != 0) {
if (!S_ISSOCK(stat.st_mode)) { if (!S_ISSOCK(stat.st_mode)) {
err = ff_log(FC_ERROR, errno, "failed to create target speci al device `%s'", target); err = ff_log(FC_ERROR, errno, "failed to create target speci al device `%s'", target);
break; break;
} }
skipping to change at line 408 skipping to change at line 414
err = ff_log(FC_ERROR, errno, "failed to read source symbolic li nk `%s'", source); err = ff_log(FC_ERROR, errno, "failed to read source symbolic li nk `%s'", source);
break; break;
} }
link_to[link_len] = '\0'; link_to[link_len] = '\0';
if (symlink(link_to, target) != 0) { if (symlink(link_to, target) != 0) {
err = ff_log(FC_ERROR, errno, "failed to create target symbolic link `%s'\t-> `%s'", target, link_to); err = ff_log(FC_ERROR, errno, "failed to create target symbolic link `%s'\t-> `%s'", target, link_to);
break; break;
} }
} else { } else {
ff_log(FC_ERROR, 0, "special device %s has unknown type 0%"FT_OLL", cannot create it", ff_log(FC_ERROR, 0, "special device %s has unknown type 0%" FT_OLL " , cannot create it",
source, (ft_ull)(stat.st_mode & ~07777)); source, (ft_ull)(stat.st_mode & ~07777));
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
break; break;
} }
if ((err = this->copy_stat(target, stat)) != 0) if ((err = this->copy_stat(target, stat)) != 0)
break; break;
if ((err = this->periodic_check_free_space()) != 0) if ((err = this->periodic_check_free_space()) != 0)
break; break;
} while (0); } while (0);
if (err == 0 && remove(source) != 0) if (err == 0)
err = ff_log(FC_ERROR, errno, "failed to remove source special device `% err = remove_special(source);
s'", source);
return err;
}
/**
* remove the special file 'source_path'
*/
int fm_io_posix::remove_special(const char * source_path)
{
int err = 0;
if (::remove(source_path) != 0)
err = ff_log(FC_ERROR, errno, "failed to remove source special device `%
s'", source_path);
return err;
}
/**
* remove the regular file 'source_path'
*/
int fm_io_posix::remove_file(const char * source_path)
{
int err = 0;
if (::remove(source_path) != 0)
err = ff_log(FC_ERROR, errno, "failed to remove source file `%s'", sourc
e_path);
return err; return err;
} }
/** /**
* move the regular file 'source_path' to 'target_path'. * move the regular file 'source_path' to 'target_path'.
*/ */
int fm_io_posix::move_file(const ft_string & source_path, const ft_stat & stat, const ft_string & target_path) int fm_io_posix::move_file(const ft_string & source_path, const ft_stat & stat, const ft_string & target_path)
{ {
const char * source = source_path.c_str(), * target = target_path.c_str(); const char * source = source_path.c_str(), * target = target_path.c_str();
int err = 0; int err = 0;
skipping to change at line 446 skipping to change at line 474
if (simulate_run()) if (simulate_run())
return err; return err;
/* check inode_cache for hard links and recreate them */ /* check inode_cache for hard links and recreate them */
err = this->hard_link(stat, target_path); err = this->hard_link(stat, target_path);
if (err == 0) { if (err == 0) {
/** hard link succeeded, no need to copy the file contents */ /** hard link succeeded, no need to copy the file contents */
err = this->periodic_check_free_space(); err = this->periodic_check_free_space();
goto move_file_remove_source; goto move_file_remove_source;
} else if (err == EAGAIN) { } else if (err != EAGAIN) {
/* no luck with inode_cache, proceed as usual */
err = 0;
} else {
/** hard link failed */ /** hard link failed */
return err; return err;
} }
{ /* no luck with inode_cache, proceed as usual */
int in_fd = ::open(source, O_RDWR); err = copy_file_contents(source_path, stat, target_path);
if (in_fd < 0)
err = ff_log(FC_ERROR, errno, "failed to open source file `%s'", sou move_file_remove_source:
rce); if (err == 0)
err = remove_file(source);
return err;
}
/**
* copy the contents of regular file 'source_path' to 'target_path'.
*/
int fm_io_posix::copy_file_contents(const ft_string & source_path, const ft_stat
& stat, const ft_string & target_path)
{
const char * source = source_path.c_str(), * target = target_path.c_str();
int err = 0;
int in_fd = ::open(source, O_RDWR);
if (in_fd < 0)
err = ff_log(FC_ERROR, errno, "failed to open source file `%s'", source)
;
#ifndef O_EXCL #ifndef O_EXCL
# define O_EXCL 0 # define O_EXCL 0
#endif #endif
int out_fd = ::open(target, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0600); int out_fd = ::open(target, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0600);
if (out_fd < 0) if (out_fd < 0)
err = ff_log(FC_ERROR, errno, "failed to create target file `%s'", t err = ff_log(FC_ERROR, errno, "failed to create target file `%s'", targe
arget); t);
if (err == 0) { if (err == 0) {
err = this->periodic_check_free_space(); err = this->periodic_check_free_space();
if (err == 0) if (err == 0)
err = this->copy_stream(in_fd, out_fd, stat, source, target); err = this->copy_stream(in_fd, out_fd, stat, source, target);
}
if (in_fd >= 0)
(void) ::close(in_fd);
if (out_fd >= 0)
(void) ::close(out_fd);
} }
if (in_fd >= 0)
(void) ::close(in_fd);
if (out_fd >= 0)
(void) ::close(out_fd);
if (err == 0) if (err == 0)
err = this->copy_stat(target, stat); err = this->copy_stat(target, stat);
move_file_remove_source:
if (err == 0) {
if (::remove(source) != 0)
err = ff_log(FC_ERROR, errno, "failed to remove source file `%s'", s
ource);
}
return err; return err;
} }
/** /**
* try to rename a file, directory or special-device from 'source_path' to 'targ et_path'. * try to rename a file, directory or special-device from 'source_path' to 'targ et_path'.
*/ */
int fm_io_posix::move_rename(const char * source, const char * target) int fm_io_posix::move_rename(const char * source, const char * target)
{ {
int err = 0; int err = 0;
do { do {
skipping to change at line 513 skipping to change at line 548
ff_log(FC_TRACE, 0, "move_rename() `%s'\t-> `%s': success", source, tar get); ff_log(FC_TRACE, 0, "move_rename() `%s'\t-> `%s': success", source, tar get);
} while (0); } while (0);
return err; return err;
} }
/** /**
* check inode_cache for hard links and recreate them. * check inode_cache for hard links and recreate them.
* must be called if and only if stat.st_nlink > 1 * must be called if and only if stat.st_nlink > 1
* *
* returns EAGAIN if inode was not in inode_cache * returns EAGAIN if inode *was* not in inode_cache
*/ */
int fm_io_posix::hard_link(const ft_stat & stat, const ft_string & target_path) int fm_io_posix::hard_link(const ft_stat & stat, const ft_string & target_path)
{ {
const ft_string * cached_link, * to_erase = NULL; ft_string cached_link = target_path;
int err;
if (stat.st_nlink > 1) if (stat.st_nlink > 1) {
/* /*
* source path has 2 or more links. * source path has 2 or more links.
* check if it is cached already, or add it to detect further links to t he same file/device * check if it is cached already, or add it to detect further links to t he same file/device
*/ */
cached_link = inode_cache_find_or_add(stat.st_ino, target_path); err = inode_cache_find_or_add(stat.st_ino, cached_link);
else } else {
/* /*
* source path has only 1 link. it can be either: * source path has only 1 link. it can be either:
* a) the last link of a file/device which previously had multiple links * a) the last link of a file/device which previously had multiple links
, but we removed them during fm_io_posix::move() ,
* but we all other links during fm_io_posix::move()
* b) a file/device which always had one link * b) a file/device which always had one link
* *
* so we check for its presence in inode_cache, but we do not add it to inode_cache * so we check for its presence in inode_cache, but we do not add it to inode_cache
* in any case, if a cached inode is found, we will erase it below with inode_cache_erase() * in any case, if a cached inode is found, we erase it
* because it is guaranteed that no more links to this inode will ever b e found. * because it is guaranteed that no more links to this inode will ever b e found.
*/ */
cached_link = to_erase = inode_cache_find(stat.st_ino, target_path); err = inode_cache_find_and_delete(stat.st_ino, cached_link);
}
int err = 0;
do {
if (cached_link == NULL) {
// fake error to tell caller that inode was not in inode_cache
err = EAGAIN;
break;
}
const char * link_to = cached_link->c_str(), * link_from = target_path.c if (err == 0) {
_str(); // fake error to tell caller that inode was not in cache
if (::link(link_to, link_from) != 0) { err = EAGAIN;
}
else if (err == 1) {
// inode found in cache
const char * link_to = cached_link.c_str(), * link_from = target_path.c_
str();
if (::link(link_to, link_from) != 0)
err = ff_log(FC_ERROR, errno, "failed to create target hard link `%s '\t-> `%s'", link_from, link_to); err = ff_log(FC_ERROR, errno, "failed to create target hard link `%s '\t-> `%s'", link_from, link_to);
break; else
} err = 0;
}
} while (0);
if (to_erase != NULL)
inode_cache_erase(stat.st_ino);
return err; return err;
} }
enum { enum {
FT_LOG_BUFSIZE = 16, //< log2(FT_BUFSIZE) FT_LOG_BUFSIZE = 16, //< log2(FT_BUFSIZE)
// FT_BUFSIZE must be a power of 2 (currently 64k), // FT_BUFSIZE must be a power of 2 (currently 64k),
// and must be somewhat smaller than fm_disk_stat::THRESHOLD_MIN (currently 96k) // and must be somewhat smaller than fm_disk_stat::THRESHOLD_MIN (currently 96k)
FT_BUFSIZE = (ft_size)1 << FT_LOG_BUFSIZE, FT_BUFSIZE = (ft_size)1 << FT_LOG_BUFSIZE,
skipping to change at line 604 skipping to change at line 635
target, pretty_size, pretty_label); target, pretty_size, pretty_label);
if (::lseek(in_fd, 0, SEEK_END) != file_size) if (::lseek(in_fd, 0, SEEK_END) != file_size)
return ff_log(FC_ERROR, errno, "error seeking to end of file `%s'", sour ce); return ff_log(FC_ERROR, errno, "error seeking to end of file `%s'", sour ce);
ft_off offset_high = file_size, offset_low; ft_off offset_high = file_size, offset_low;
if ((err = fd_truncate(out_fd, offset_high, target)) != 0) if ((err = fd_truncate(out_fd, offset_high, target)) != 0)
return err; return err;
::sync(); // slow, but on Linux not doing it is worse // slow, but on Linux not doing it is worse:
// you can get inaccurate disk usage statistics
// and (if loop device becomes full) silent I/O errors!
sync();
char buf[FT_BUFSIZE]; char buf[FT_BUFSIZE];
ft_size expected, got; ft_size expected, got;
ft_size hole_len, nonhole_len, tosend_offset, tosend_left; ft_size hole_len, nonhole_len, tosend_offset, tosend_left;
while (offset_high > 0) { while (offset_high > 0) {
/** truncate in_fd, discarding any data that we already copied */ /** truncate in_fd, discarding any data that we already copied */
if ((err = fd_truncate(in_fd, offset_high, source)) != 0) if ((err = fd_truncate(in_fd, offset_high, source)) != 0)
break; break;
offset_low = (offset_high - 1) & ~(ft_off)FT_BUFSIZE_m1; offset_low = (offset_high - 1) & ~(ft_off)FT_BUFSIZE_m1;
ff_assert(offset_high - offset_low <= FT_BUFSIZE); ff_assert(offset_high - offset_low <= FT_BUFSIZE);
got = expected = (ft_size)(offset_high - offset_low); got = expected = (ft_size)(offset_high - offset_low);
if ((err = fd_seek2(in_fd, out_fd, offset_low, source, target)) != 0) if ((err = fd_seek2(in_fd, out_fd, offset_low, source, target)) != 0)
break; break;
if ((err = this->full_read(in_fd, buf, got, source)) != 0 || got != expe cted) { if ((err = this->full_read(in_fd, buf, got, source)) != 0 || got != expe cted) {
if (err == 0) { if (err == 0) {
ff_log(FC_ERROR, 0, "error reading from `%s': expected %"FT_ULL" bytes, got %"FT_ULL" bytes", ff_log(FC_ERROR, 0, "error reading from `%s': expected %" FT_ULL " bytes, got %" FT_ULL " bytes",
source, (ft_ull)expected, (ft_ull)got); source, (ft_ull)expected, (ft_ull)got);
err = -EIO; err = -EIO;
} }
break; break;
} }
tosend_offset = 0; tosend_offset = 0;
for (tosend_left = got; tosend_left != 0; ) { for (tosend_left = got; tosend_left != 0; ) {
/* detect hole */ /* detect hole */
if ((hole_len = hole_length(buf + tosend_offset, tosend_left)) != 0) { if ((hole_len = hole_length(buf + tosend_offset, tosend_left)) != 0) {
/* re-create hole in target file */ /* re-create hole in target file */
if (::lseek(out_fd, (ft_off)hole_len, SEEK_CUR) == (ft_off)-1) { if (::lseek(out_fd, (ft_off)hole_len, SEEK_CUR) == (ft_off)-1) {
err = ff_log(FC_ERROR, errno, "error seeking %"FT_ULL" bytes forward in file `%s'", (ft_ull)hole_len, target); err = ff_log(FC_ERROR, errno, "error seeking %" FT_ULL " byt es forward in file `%s'", (ft_ull)hole_len, target);
break; break;
} }
tosend_offset += hole_len; tosend_offset += hole_len;
tosend_left -= hole_len; tosend_left -= hole_len;
} }
if ((nonhole_len = nonhole_length(buf + tosend_offset, tosend_left)) != 0) { if ((nonhole_len = nonhole_length(buf + tosend_offset, tosend_left)) != 0) {
// copy the non-hole data // copy the non-hole data
if ((err = this->full_write(out_fd, buf + tosend_offset, nonhole _len, target)) != 0) if ((err = this->full_write(out_fd, buf + tosend_offset, nonhole _len, target)) != 0)
break; break;
skipping to change at line 663 skipping to change at line 697
break; break;
offset_high = offset_low; offset_high = offset_low;
} }
if (err != 0 && offset_high != 0 && offset_high != file_size) { if (err != 0 && offset_high != 0 && offset_high != file_size) {
ff_log(FC_ERROR, 0, "DANGER! due to previous error, copying `%s' -> `%s' was aborted", source, target); ff_log(FC_ERROR, 0, "DANGER! due to previous error, copying `%s' -> `%s' was aborted", source, target);
ff_log(FC_ERROR, 0, " and BOTH copies of this file are now incomp lete."); ff_log(FC_ERROR, 0, " and BOTH copies of this file are now incomp lete.");
ff_log(FC_ERROR, 0, " To recover this file, execute the following command"); ff_log(FC_ERROR, 0, " To recover this file, execute the following command");
ff_log(FC_ERROR, 0, " AFTER freeing enough space in the source de vice:"); ff_log(FC_ERROR, 0, " AFTER freeing enough space in the source de vice:");
offset_high >>= FT_LOG_BUFSIZE; offset_high >>= FT_LOG_BUFSIZE;
ff_log(FC_ERROR, 0, " /bin/dd bs=%"FT_ULL" skip=%"FT_ULL" seek= %"FT_ULL" conv=notrunc if=\"%s\" of=\"%s\"", ff_log(FC_ERROR, 0, " /bin/dd bs=%" FT_ULL " skip=%" FT_ULL " s eek=%" FT_ULL " conv=notrunc if=\"%s\" of=\"%s\"",
(ft_ull)FT_BUFSIZE, (ft_ull)offset_high, (ft_ull)offset_high, ta rget, source); (ft_ull)FT_BUFSIZE, (ft_ull)offset_high, (ft_ull)offset_high, ta rget, source);
} }
return err; return err;
} }
/** /**
* forward copy file/stream contents from in_fd to out_fd. * forward copy file/stream contents from in_fd to out_fd.
*/ */
int fm_io_posix::copy_stream_forward(int in_fd, int out_fd, const char * source, const char * target) int fm_io_posix::copy_stream_forward(int in_fd, int out_fd, const char * source, const char * target)
{ {
skipping to change at line 744 skipping to change at line 778
return err; return err;
} }
/** /**
* truncate file pointed by descriptor to specified length * truncate file pointed by descriptor to specified length
*/ */
int fm_io_posix::fd_truncate(int fd, ft_off length, const char * path) int fm_io_posix::fd_truncate(int fd, ft_off length, const char * path)
{ {
int err = 0; int err = 0;
if (::ftruncate(fd, length) == -1) if (::ftruncate(fd, length) == -1)
err = ff_log(FC_ERROR, errno, "error truncating file `%s' to %"FT_ULL" b ytes", path, (ft_ull)length); err = ff_log(FC_ERROR, errno, "error truncating file `%s' to %" FT_ULL " bytes", path, (ft_ull)length);
return err; return err;
} }
/** /**
* seek to specified position of *both* fd1 and fd2 * seek to specified position of *both* fd1 and fd2
*/ */
int fm_io_posix::fd_seek2(int fd1, int fd2, ft_off offset, const char * path1, c onst char * path2) int fm_io_posix::fd_seek2(int fd1, int fd2, ft_off offset, const char * path1, c onst char * path2)
{ {
int err = fd_seek(fd1, offset, path1); int err = fd_seek(fd1, offset, path1);
if (err == 0) if (err == 0)
skipping to change at line 766 skipping to change at line 800
return err; return err;
} }
/** /**
* seek to specified position of file descriptor * seek to specified position of file descriptor
*/ */
int fm_io_posix::fd_seek(int fd, ft_off offset, const char * path) int fm_io_posix::fd_seek(int fd, ft_off offset, const char * path)
{ {
int err = 0; int err = 0;
if (::lseek(fd, offset, SEEK_SET) != offset) if (::lseek(fd, offset, SEEK_SET) != offset)
err = ff_log(FC_ERROR, errno, "error seeking to position %"FT_ULL" of fi le `%s'", (ft_ull)offset, path); err = ff_log(FC_ERROR, errno, "error seeking to position %" FT_ULL " of file `%s'", (ft_ull)offset, path);
return err; return err;
} }
/** /**
* scan memory for blocksize-length and blocksize-aligned sections full of zeroe s * scan memory for blocksize-length and blocksize-aligned sections full of zeroe s
* return length of zeroed area at the beginning of scanned memory. * return length of zeroed area at the beginning of scanned memory.
* returned length is rounded down to block_size * returned length is rounded down to block_size
*/ */
size_t fm_io_posix::hole_length(const char * mem, ft_size mem_len) size_t fm_io_posix::hole_length(const char * mem, ft_size mem_len)
{ {
skipping to change at line 919 skipping to change at line 953
/* copy owner and group. this resets any SUID bits */ /* copy owner and group. this resets any SUID bits */
#if defined(FT_HAVE_LCHOWN) #if defined(FT_HAVE_LCHOWN)
if (lchown(target, stat.st_uid, stat.st_gid) != 0) if (lchown(target, stat.st_uid, stat.st_gid) != 0)
#else #else
if (!is_symlink && chown(target, stat.st_uid, stat.st_gid) != 0) if (!is_symlink && chown(target, stat.st_uid, stat.st_gid) != 0)
#endif #endif
{ {
err = ff_log(is_error ? FC_ERROR : FC_WARN, errno, err = ff_log(is_error ? FC_ERROR : FC_WARN, errno,
"%s set owner=%"FT_ULL" and group=%"FT_ULL" on %s `%s'", "%s set owner=%" FT_ULL " and group=%" FT_ULL " on %s `%s'",
fail_label, (ft_ull)stat.st_uid, (ft_ull)stat.st_gid, label, target); fail_label, (ft_ull)stat.st_uid, (ft_ull)stat.st_gid, label, target);
if (is_error) if (is_error)
break; break;
err = 0; err = 0;
} }
/* /*
* copy permission bits * copy permission bits
* 1. chmod() on a symbolic link has no sense, don't to it * 1. chmod() on a symbolic link has no sense, don't to it
* 2. chmod() must be performed AFTER lchown(), because lchown() resets any SUID bits * 2. chmod() must be performed AFTER lchown(), because lchown() resets any SUID bits
*/ */
if (!is_symlink && chmod(target, stat.st_mode) != 0) { if (!is_symlink && chmod(target, stat.st_mode) != 0) {
err = ff_log(is_error ? FC_ERROR : FC_WARN, errno, err = ff_log(is_error ? FC_ERROR : FC_WARN, errno,
"%s change mode to 0%"FT_OLL" on %s `%s'", "%s change mode to 0%" FT_OLL " on %s `%s'",
fail_label, (ft_ull)stat.st_mode, label, target); fail_label, (ft_ull)stat.st_mode, label, target);
if (is_error) if (is_error)
break; break;
err = 0; err = 0;
} }
} while (0); } while (0);
return err; return err;
} }
skipping to change at line 1002 skipping to change at line 1036
*/ */
int fm_io_posix::remove_dir(const ft_string & path) int fm_io_posix::remove_dir(const ft_string & path)
{ {
const char * dir = path.c_str(); const char * dir = path.c_str();
int err = 0; int err = 0;
ff_log(FC_TRACE, 0, "remove_dir() `%s'", dir); ff_log(FC_TRACE, 0, "remove_dir() `%s'", dir);
do { do {
if (simulate_run() || is_source_lost_found(path)) if (simulate_run() || is_source_lost_found(path))
break; break;
if (remove(dir) != 0) { if (::remove(dir) != 0) {
/* ignore error if we are removing source root: it is allowed to be in use */ /* ignore error if we are removing source root: it is allowed to be in use */
if (path != source_root()) { if (path != source_root()) {
/* if force_run(), failure to remove a source directory is just a warning */ /* if force_run(), failure to remove a source directory is just a warning */
bool is_warn = force_run(); bool is_warn = force_run();
err = ff_log(is_warn ? FC_WARN : FC_ERROR, errno, "%sfailed to r emove source directory `%s'", is_warn ? "warning: " : "", dir); err = ff_log(is_warn ? FC_WARN : FC_ERROR, errno, "%sfailed to r emove source directory `%s'", is_warn ? "warning: " : "", dir);
if (!is_warn) if (!is_warn)
break; break;
err = 0; err = 0;
} }
break; break;
 End of changes. 39 change blocks. 
80 lines changed or deleted 116 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)