diff --git a/doc/Notes.html b/doc/Notes.html index 4af4a09e..de075227 100644 --- a/doc/Notes.html +++ b/doc/Notes.html @@ -2830,7 +2830,18 @@

Cross reference matrix

1.3.0 1.2.2 - + + June 6th, 2024 + 2.7.15 + 11.3 + 06 + 6.7.3 + 1.7.0 + 1.6.0 + 1.9.0 + 1.3.0 + 1.2.2 + diff --git a/man/dar.1 b/man/dar.1 index 5017a979..8081f2ea 100644 --- a/man/dar.1 +++ b/man/dar.1 @@ -1,4 +1,4 @@ -.TH DAR 1 "March 23rd, 2024" +.TH DAR 1 "June 6th, 2024" .UC 8 .SH NAME dar \- creates, tests, lists, extracts, compares, merges, isolates, repairs dar archives diff --git a/misc/dar_static_builder_with_musl_voidlinux.bash b/misc/dar_static_builder_with_musl_voidlinux.bash index 942c3adc..a3823586 100755 --- a/misc/dar_static_builder_with_musl_voidlinux.bash +++ b/misc/dar_static_builder_with_musl_voidlinux.bash @@ -33,8 +33,8 @@ LIBSSH2_VERSION=1.10.0 # define whether to use libssh or libssh2 # note that both libraries do support ssh version 2 protocol, # libssh even supports more recent ciphers than libssh2 -# LIBSSH=1 -LIBSSH=2 +LIBSSH=1 +# LIBSSH=2 # wget options need for gnutls website that does not provide all chain of trust in its certificate diff --git a/src/build/ChangeLog b/src/build/ChangeLog index ba6baba0..bc298ab5 100644 --- a/src/build/ChangeLog +++ b/src/build/ChangeLog @@ -32,10 +32,14 @@ from 2.7.14 to 2.7.15 reported as deprecated by recent libcurl libraries. - fixed compilation problem under MacOS Mojave - fixed bug that lead the warning about a backup operation about to save - the backup itslef, to not show + itself, to not show - removing obsolete call to gcry_control(GCRYCTL_ENABLE_M_GUARD) while - initializing libgcrypt. This lead to libgcrypt initialization to fail + initializing libgcrypt. This led to libgcrypt initialization to fail with libgcrypt 1.11 and more recent versions. +- fixed listing but about "present but unsaved" FSA status +- fixed dead-lock condition in libdar when used with libcurl > 0.74.0 at + the end of closing sftp session (undocumented changed behavior in + libcurl). from 2.7.13 to 2.7.14 - adding safe guard in fichier_libcurl destructor to verify all data have diff --git a/src/check/main.sh b/src/check/main.sh index f92b67f6..42a9ba32 100755 --- a/src/check/main.sh +++ b/src/check/main.sh @@ -266,7 +266,9 @@ listing: testing: -diffing: +diff: +--fsa-scope none +# because of birth date change when comparing with restored data EOF diff --git a/src/check/routine.sh b/src/check/routine.sh index bde8df2f..c8c399a9 100755 --- a/src/check/routine.sh +++ b/src/check/routine.sh @@ -625,9 +625,9 @@ fi # I1 - SFTP repository # if echo $* | grep "I1" > /dev/null ; then -GO "I1-1" 0 $ROUTINE_DEBUG $DAR -N -w -c $DAR_SFTP_REPO/$prefix$full -R $src "-@" $prefix$catf_fly -B $OPT -GO "I1-2" 0 $ROUTINE_DEBUG $DAR -N -l $DAR_SFTP_REPO/$prefix$full -B $OPT -GO "I1-3" 0 $ROUTINE_DEBUG $DAR -N -t $DAR_SFTP_REPO/$prefix$full -B $OPT +GO "I1-1" 0 $ROUTINE_DEBUG $DAR -N -w -c $DAR_SFTP_REPO/$prefix-$full -R $src "-@" $prefix$catf_fly -B $OPT +GO "I1-2" 0 $ROUTINE_DEBUG $DAR -N -l $DAR_SFTP_REPO/$prefix-$full -B $OPT +GO "I1-3" 0 $ROUTINE_DEBUG $DAR -N -t $DAR_SFTP_REPO/$prefix-$full -B $OPT ../sftp_mdelete "$DAR_SFTP_REPO" "$prefix*" fi @@ -635,9 +635,9 @@ fi # I2 - FTP repository # if echo $* | grep "I2" > /dev/null ; then -GO "I2-1" 0 $ROUTINE_DEBUG $DAR -N -w -c $DAR_FTP_REPO/$prefix$full -R $src "-@" $prefix$catf_fly -B $OPT -GO "I2-2" 0 $ROUTINE_DEBUG $DAR -N -l $DAR_FTP_REPO/$prefix$full -B $OPT -GO "I2-3" 0 $ROUTINE_DEBUG $DAR -N -t $DAR_FTP_REPO/$prefix$full -B $OPT +GO "I2-1" 0 $ROUTINE_DEBUG $DAR -N -w -c $DAR_FTP_REPO/$prefix-$full -R $src "-@" $prefix$catf_fly -B $OPT +GO "I2-2" 0 $ROUTINE_DEBUG $DAR -N -l $DAR_FTP_REPO/$prefix-$full -B $OPT +GO "I2-3" 0 $ROUTINE_DEBUG $DAR -N -t $DAR_FTP_REPO/$prefix-$full -B $OPT ../ftp_mdelete "$DAR_FTP_REPO" "$prefix*" fi ### diff --git a/src/libdar/cat_entree.cpp b/src/libdar/cat_entree.cpp index b3641d5a..733bbd2d 100644 --- a/src/libdar/cat_entree.cpp +++ b/src/libdar/cat_entree.cpp @@ -369,14 +369,19 @@ namespace libdar } } ent.set_fsa_status(tmp_inode->fsa_get_saved_status()); - if(tmp_inode->fsa_get_saved_status() == fsa_saved_status::full) + if(tmp_inode->fsa_get_saved_status() == fsa_saved_status::full + || tmp_inode->fsa_get_saved_status() == fsa_saved_status::partial) { - infinint tmp; - - if(tmp_inode->fsa_get_offset(tmp)) - ent.set_archive_offset_for_FSA(tmp); - ent.set_storage_size_for_FSA(tmp_inode->fsa_get_size()); ent.set_fsa_scope(tmp_inode->fsa_get_families()); + + if(tmp_inode->fsa_get_saved_status() == fsa_saved_status::full) + { + infinint tmp; + + if(tmp_inode->fsa_get_offset(tmp)) + ent.set_archive_offset_for_FSA(tmp); + ent.set_storage_size_for_FSA(tmp_inode->fsa_get_size()); + } } } diff --git a/src/libdar/cat_inode.cpp b/src/libdar/cat_inode.cpp index 78ecb0f2..7a1fdde1 100644 --- a/src/libdar/cat_inode.cpp +++ b/src/libdar/cat_inode.cpp @@ -266,13 +266,13 @@ namespace libdar switch(fsa_flag) { case INODE_FLAG_FSA_NONE: - fsa_saved = fsa_saved_status::none; + fsa_saved = fsa_saved_status::none; break; case INODE_FLAG_FSA_PART: - fsa_saved = fsa_saved_status::partial; + fsa_saved = fsa_saved_status::partial; break; case INODE_FLAG_FSA_FULL: - fsa_saved = fsa_saved_status::full; + fsa_saved = fsa_saved_status::full; break; default: throw Erange("cat_inode::cat_inode", gettext("badly structured inode: unknown inode flag for FSA")); @@ -492,6 +492,9 @@ namespace libdar { if(scope.size() > 0) throw Erange("cat_inode::compare", gettext("No Filesystem Specific Attribute to compare with")); + + // this is not perfect, the "other" could have no FSA due to the non empty scope excluding only + // the valid FSAs. A more specific comparison would worth it... } break; case fsa_saved_status::partial: @@ -502,7 +505,13 @@ namespace libdar throw Erange("cat_inode::compare", gettext("inode last change date (ctime) greater, FSA might be different")); } else - throw Erange("cat_inode::compare", gettext("Filesystem Specific Attribute are missing")); + { + if(scope.size() > 0) + throw Erange("cat_inode::compare", gettext("Filesystem Specific Attribute are missing")); + + // this is not perfect, the "other" could have no FSA due to the non empty scope excluding only + // the valid FSAs. A more specific comparison would worth it... + } break; case fsa_saved_status::none: break; // nothing to check diff --git a/src/libdar/fichier_libcurl.cpp b/src/libdar/fichier_libcurl.cpp index 9b4b354d..573d0547 100644 --- a/src/libdar/fichier_libcurl.cpp +++ b/src/libdar/fichier_libcurl.cpp @@ -51,6 +51,7 @@ namespace libdar end_data_mode(false), sub_is_dying(false), sync_write_asked(false), + weof(false), ehandle(handle), metadatamode(false), current_offset(0), @@ -181,7 +182,7 @@ namespace libdar } catch(Egeneric & e) { - e.prepend_message("Error while reading file size on a remote repository"); + e.prepend_message("Error while reading file size on a remote repository: "); throw; } } @@ -526,6 +527,7 @@ namespace libdar void fichier_libcurl::initialize_subthread() { sub_is_dying = false; + weof = false; synchronize.wait(); // release calling thread as we, as child thread, do now exist } @@ -805,10 +807,30 @@ namespace libdar if(me == nullptr) throw SRC_BUG; + bool fetch_block = !me->weof || me->sync_write_asked; + // with libcurl 7.74.0 and below, returning zero + // bytes was properly addressed by libcurl as an EOF + // and no more call to read_data_callback was "performed". + // But with libcurl 7.88.1 read_data_callback() was called + // again at least once after that, which lead fichier_libcurl + // main thread hanging forever for curl_perform to end + // because read_data_callback() was pending to receive + // data from interthread pipe. To avoid that having the ending + // of the subthread involving external software (libcurl) which + // somehow changed without notice nor documentation change, we + // add the weof boolean variable to avoid fetching from interthread + // in that context. + do { just_synced = false; - me->interthread.fetch(ptr, ptr_size); + if(fetch_block) + me->interthread.fetch(ptr, ptr_size); + else // emulate an the fetching of a zero length block + { + ptr_size = 0; + ptr = bufptr; // we will copy 0 bytes from bufptr to bufptr + } // note: if ptr_size is zero // libcurl will assume EOF and stop @@ -817,7 +839,8 @@ namespace libdar if(me->sync_write_asked && ptr_size == 0) { me->sync_write_asked = false; - me->interthread.fetch_recycle(ptr); + if(fetch_block) + me->interthread.fetch_recycle(ptr); me->synchronize.wait(); just_synced = true; } @@ -827,7 +850,8 @@ namespace libdar if(ptr_size <= room) { memcpy(bufptr, ptr, ptr_size); - me->interthread.fetch_recycle(ptr); + if(fetch_block) + me->interthread.fetch_recycle(ptr); ret = ptr_size; } else @@ -835,10 +859,14 @@ namespace libdar memcpy(bufptr, ptr, room); ptr_size -= room; memmove(ptr, ptr + room, ptr_size); - me->interthread.fetch_push_back(ptr, ptr_size); + if(fetch_block) + me->interthread.fetch_push_back(ptr, ptr_size); ret = room; } + if(fetch_block && ptr_size == 0 && !(me->sync_write_asked)) + me->weof = true; + return ret; } diff --git a/src/libdar/fichier_libcurl.hpp b/src/libdar/fichier_libcurl.hpp index 765862a0..3b300422 100644 --- a/src/libdar/fichier_libcurl.hpp +++ b/src/libdar/fichier_libcurl.hpp @@ -155,6 +155,7 @@ namespace libdar bool end_data_mode; ///< true if subthread has been requested to end bool sub_is_dying; ///< is set by subthread when about to end bool sync_write_asked; ///< ask subthread to use 'synchronize' tell all data has been written + bool weof; ///< whether write EOF has been signaled to libcurl std::shared_ptr ehandle; ///< easy handle (wrapped in C++ object) that we modify when necessary bool metadatamode; ///< wether we are acting on metadata rather than file's data infinint current_offset; ///< current offset we are reading / writing at diff --git a/src/libdar/path.cpp b/src/libdar/path.cpp index 473736d0..a78f291f 100644 --- a/src/libdar/path.cpp +++ b/src/libdar/path.cpp @@ -242,8 +242,8 @@ namespace libdar if(me.size() >= you.size()) if(strncmp(me.c_str(), you.c_str(), you.size()) == 0) if(me.size() > you.size()) - return you.size() > 1 && me[you.size()] == '/' - || you.size() == 1 && you[0] == '/'; + return (you.size() > 1 && me[you.size()] == '/') + || (you.size() == 1 && you[0] == '/'); else // thus, me.size() == you.size(), thus I'm a subdir of myself return true; else // path differs in the common length part, cannot be a subdir of "you"