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

Handle metadata iterators renaming tempfile over symlink #740

Merged
merged 2 commits into from
Aug 30, 2024
Merged
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: 38 additions & 1 deletion src/libFLAC/metadata_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,8 +1525,10 @@ static FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *t

/* move the tempfile on top of the original */
(void)fclose(f);
if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status))
if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status)) {
chain->status = get_equivalent_status_(status);
return false;
}

return true;

Expand Down Expand Up @@ -3475,6 +3477,41 @@ FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tem
}
#endif

#ifndef _WIN32
/* Need to check whether filename refers to a symlink or not */
{
struct stat filestat;
if(lstat(filename, &filestat) != 0) {
cleanup_tempfile_(tempfile, tempfilename);
*status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
return false;
}
if(S_ISLNK(filestat.st_mode)) {
/* file is symlink, find out name of symlinked file */
char linked_name[1024];
ssize_t len = readlink(filename, linked_name, sizeof(linked_name) - 1);
if (len == sizeof(linked_name) - 1) {
/* name too long */
cleanup_tempfile_(tempfile, tempfilename);
*status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
return false;
}
linked_name[len] = '\0';

if(0 != flac_rename(*tempfilename, linked_name)) {
cleanup_tempfile_(tempfile, tempfilename);
*status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR;
return false;
}
return true;
}
/* else, continue with normale code */
}

#endif



/*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just flac_rename(): */
if(0 != flac_rename(*tempfilename, filename)) {
cleanup_tempfile_(tempfile, tempfilename);
Expand Down
12 changes: 10 additions & 2 deletions src/metaflac/operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,12 @@ FLAC__bool do_major_operation_on_file(const char *filename, const CommandLineOpt
if(options->use_padding)
FLAC__metadata_chain_sort_padding(chain);
ok = FLAC__metadata_chain_write(chain, options->use_padding, options->preserve_modtime);
if(!ok)
if(!ok) {
FLAC__Metadata_ChainStatus status = FLAC__metadata_chain_status(chain);
print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename);
if(status == FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR)
flac_fprintf(stderr, "NOTE: rename errors often occur when working with symlinks pointing to a different filesystem\n");
}
}

FLAC__metadata_chain_delete(chain);
Expand Down Expand Up @@ -466,8 +470,12 @@ FLAC__bool do_shorthand_operations_on_file(const char *filename, const CommandLi
if(use_padding)
FLAC__metadata_chain_sort_padding(chain);
ok = FLAC__metadata_chain_write(chain, use_padding, options->preserve_modtime);
if(!ok)
if(!ok) {
FLAC__Metadata_ChainStatus status = FLAC__metadata_chain_status(chain);
print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename);
if(status == FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR)
flac_fprintf(stderr, "NOTE: rename errors often occur when working with symlinks pointing to a different filesystem\n");
}
}

cleanup :
Expand Down
Loading