adept_remove: -O <dir> writes the result into a nested sub-directory when the input is a path #28

Closed
opened 2026-06-29 16:27:17 +02:00 by benoitperrin · 1 comment
Contributor

Summary

adept_remove -O <dir> <file> is documented as putting the de-DRMed result into <dir>. But when <file> is given as a path (absolute, or relative with sub-directories), the result is written to <dir>/<full input path> instead of <dir>/<basename>, and the intermediate directories are created silently.

This is a natural usage: download with acsmdownloader into one directory, then run adept_remove -O <other dir> on the resulting (absolute-path) file.

Version

master (commit 324c566, also tag v0.8.9), built on Ubuntu 24.04, g++ 13.

Steps to reproduce

mkdir -p /tmp/in /tmp/out
cp some.epub /tmp/in/book.epub
adept_remove -D ~/.config/adept -O /tmp/out /tmp/in/book.epub

Expected

Result written to /tmp/out/book.epub.

Actual

Result written to /tmp/out/tmp/in/book.epub — the whole /tmp/in/ tree is re-created under /tmp/out/. No error or warning about the path.

Root cause

utils/adept_remove.cpp, ADEPTRemove::run() (~line 88):

filename = std::string(inputFile);

if (outputDir)
    filename = std::string(outputDir) + "/" + filename;

inputFile is concatenated as-is (full path) after outputDir, then createPath() creates the nested directories. The input should be reduced to its base name first.

acsmdownloader -O is not affected because it builds the output name from the title metadata, not from the input path.

Note: there is a prior commit b44b988 ("Fix bug in utils with -o and -O options"); this specific case (input passed as a path) still reproduces on current master.

Fix

Reduce inputFile to its base name before prefixing it with outputDir. Tested on Ubuntu 24.04: with the patch, -O /tmp/out /tmp/in/book.epub correctly writes /tmp/out/book.epub.

diff --git a/utils/adept_remove.cpp b/utils/adept_remove.cpp
index 47112ab..b48bb07 100644
--- a/utils/adept_remove.cpp
+++ b/utils/adept_remove.cpp
@@ -88,7 +88,12 @@ public:
                 filename = std::string(inputFile);
 
                 if (outputDir)
-                    filename = std::string(outputDir) + "/" + filename;
+                {
+                    std::string _in(inputFile);
+                    size_t _pos = _in.find_last_of('/');
+                    std::string _base = (_pos == std::string::npos) ? _in : _in.substr(_pos + 1);
+                    filename = std::string(outputDir) + "/" + _base;
+                }
             }
## Summary `adept_remove -O <dir> <file>` is documented as putting the de-DRMed result into `<dir>`. But when `<file>` is given as a path (absolute, or relative with sub-directories), the result is written to `<dir>/<full input path>` instead of `<dir>/<basename>`, and the intermediate directories are created silently. This is a natural usage: download with `acsmdownloader` into one directory, then run `adept_remove -O <other dir>` on the resulting (absolute-path) file. ## Version `master` (commit `324c566`, also tag `v0.8.9`), built on Ubuntu 24.04, g++ 13. ## Steps to reproduce ```sh mkdir -p /tmp/in /tmp/out cp some.epub /tmp/in/book.epub adept_remove -D ~/.config/adept -O /tmp/out /tmp/in/book.epub ``` ## Expected Result written to `/tmp/out/book.epub`. ## Actual Result written to `/tmp/out/tmp/in/book.epub` — the whole `/tmp/in/` tree is re-created under `/tmp/out/`. No error or warning about the path. ## Root cause `utils/adept_remove.cpp`, `ADEPTRemove::run()` (~line 88): ```cpp filename = std::string(inputFile); if (outputDir) filename = std::string(outputDir) + "/" + filename; ``` `inputFile` is concatenated as-is (full path) after `outputDir`, then `createPath()` creates the nested directories. The input should be reduced to its base name first. `acsmdownloader -O` is **not** affected because it builds the output name from the title metadata, not from the input path. Note: there is a prior commit `b44b988` ("Fix bug in utils with -o and -O options"); this specific case (input passed as a path) still reproduces on current `master`. ## Fix Reduce `inputFile` to its base name before prefixing it with `outputDir`. Tested on Ubuntu 24.04: with the patch, `-O /tmp/out /tmp/in/book.epub` correctly writes `/tmp/out/book.epub`. ```diff diff --git a/utils/adept_remove.cpp b/utils/adept_remove.cpp index 47112ab..b48bb07 100644 --- a/utils/adept_remove.cpp +++ b/utils/adept_remove.cpp @@ -88,7 +88,12 @@ public: filename = std::string(inputFile); if (outputDir) - filename = std::string(outputDir) + "/" + filename; + { + std::string _in(inputFile); + size_t _pos = _in.find_last_of('/'); + std::string _base = (_pos == std::string::npos) ? _in : _in.substr(_pos + 1); + filename = std::string(outputDir) + "/" + _base; + } } ```
Owner

Thanks Benoît for your report and your fix.
Tested and approved !

Thanks Benoît for your report and your fix. Tested and approved !
Sign in to join this conversation.
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: soutade/libgourou#28