Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync output to disk before removing source #151

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions src/xz/file_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ static bool warn_fchown;
((e) == EAGAIN || (e) == EWOULDBLOCK)
#endif

#ifndef O_DIRECTORY
# define O_DIRECTORY O_NOCTTY
#endif

typedef enum {
IO_WAIT_MORE, // Reading or writing is possible.
Expand Down Expand Up @@ -707,6 +710,7 @@ io_open_src(const char *src_name)
.dest_name = NULL,
.src_fd = -1,
.dest_fd = -1,
.dest_dir_fd = -1,
.src_eof = false,
.src_has_seen_input = false,
.flush_needed = false,
Expand Down Expand Up @@ -856,6 +860,15 @@ io_open_dest_real(file_pair *pair)
free(pair->dest_name);
return true;
}
#ifndef TUKLIB_DOSLIKE
if (!opt_keep_original) {
char *dest_dir_name;

dest_dir_name = suffix_get_directory_name(pair->dest_name);
pair->dest_dir_fd = open(dest_dir_name, O_DIRECTORY);
free(dest_dir_name);
}
#endif
}

if (fstat(pair->dest_fd, &pair->dest_st)) {
Expand Down Expand Up @@ -887,7 +900,10 @@ io_open_dest_real(file_pair *pair)
// dest_fd needs to be reset to -1 to keep io_close() working.
(void)close(pair->dest_fd);
pair->dest_fd = -1;

if (pair->dest_dir_fd >= 0) {
(void)close(pair->dest_dir_fd);
pair->dest_dir_fd = -1;
}
free(pair->dest_name);
return true;
}
Expand Down Expand Up @@ -1003,6 +1019,8 @@ io_close_dest(file_pair *pair, bool success)
if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO)
return false;

if (pair->dest_dir_fd >= 0)
close(pair->dest_dir_fd);
if (close(pair->dest_fd)) {
message_error(_("%s: Closing the file failed: %s"),
pair->dest_name, strerror(errno));
Expand Down Expand Up @@ -1055,8 +1073,25 @@ io_close(file_pair *pair, bool success)

// Copy the file attributes. We need to skip this if destination
// file isn't open or it is standard output.
if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO)
if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO) {
io_copy_attrs(pair);
#ifndef TUKLIB_DOSLIKE
if (!opt_keep_original) {
if (fdatasync(pair->dest_fd)) {
success = false;
message_error(_("Failed to sync %s: %s"), pair->dest_name,
strerror(errno));
}
if (pair->dest_dir_fd >= 0)
if (fsync(pair->dest_dir_fd)) {
success = false;
message_error(_("Failed to sync directory of %s: %s"),
pair->dest_name,
strerror(errno));
}
}
#endif
}

// Close the destination first. If it fails, we must not remove
// the source file!
Expand Down
3 changes: 3 additions & 0 deletions src/xz/file_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ typedef struct {
/// File descriptor of the target file
int dest_fd;

/// File descriptor of the target file's directory
int dest_dir_fd;

/// True once end of the source file has been detected.
bool src_eof;

Expand Down
42 changes: 42 additions & 0 deletions src/xz/suffix.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ has_dir_sep(const char *str)
#endif
}

/// \brief Return the last directory separator or NULL if none is found.
static char *
get_last_dir_sep(const char *str)
{
#ifdef TUKLIB_DOSLIKE
char *r;

r = strrchr(str, '/');
if (r)
return r;
r = strrchr(str, '\\')
if (r)
return r;
return NULL;
#else
return strrchr(str, '/');
#endif
}


#ifdef __DJGPP__
/// \brief Test for special suffix used for 8.3 short filenames (SFN)
Expand Down Expand Up @@ -110,6 +129,29 @@ test_suffix(const char *suffix, const char *src_name, size_t src_len)
}


/// \brief Returns the directory name of the file
///
/// \return Name of the directory of the file.
char *
suffix_get_directory_name(const char *f_name)
{
char *name;
char *dir_sep;

name = xstrdup(f_name);
dir_sep = get_last_dir_sep(name);
if (dir_sep) {
dir_sep++;
*dir_sep = '\0';
} else {
name[0] = '.';
name[1] = '\0';
}

return name;
}


/// \brief Removes the filename suffix of the compressed file
///
/// \return Name of the uncompressed file, or NULL if file has unknown
Expand Down
4 changes: 4 additions & 0 deletions src/xz/suffix.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
/// NULL is returned.
extern char *suffix_get_dest_name(const char *src_name);

/// \brief Returns the directory name of the file
///
/// Returns the name of directory where this file is locacted.
extern char *suffix_get_directory_name(const char *f_name);

/// \brief Set a custom filename suffix
///
Expand Down
Loading