cross-device kopieren mit std::filesystem



  • Hallo,

    #include <iostream>
    #include <fstream>
    #include <filesystem>
    
    namespace fs = std::filesystem;
    
    int main(){
        std::ofstream{"file"}.write("000", 3);
        std::string from = "file", to = "/mnt";
        fs::copy_file(from, to, fs::copy_options::overwrite_existing);
    }
    

    vs.

    #include <iostream>
    #include <fstream>
    #include <boost/filesystem.hpp>
    
    namespace fs = boost::filesystem;
    
    int main(){
        std::ofstream{"file"}.write("000", 3);
        std::string from = "file", to = "/mnt";
        fs::copy_file(from, to, fs::copy_option::overwrite_if_exists);
    }
    

    Ich versuche eine Datei auf ein Cross-Link Device zu kopieren, d.h. auf ein anderes Dateisystem. Mit Boost.Filesystem funktioniert das auch. Mit den Bordmitteln des neuen Standards jedoch nicht. Der Boost-Code wird erfolgreich ausgeführt. Mit <filesystem> wird eine Exception geworfen:

    terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
      what():  filesystem error: cannot copy file [file] [/mnt]
    

    Die Datei wird angelegt, der Inhalt bleibt jedoch leer. Scheint wohl als wäre die Implementation von Boost immernoch besser als der Standard. Abwarten?

    gcc --version => gcc (GCC) 9.1.0
    clang --version => clang version 8.0.1

    Mit Linux unterwegs.



  • Der Boost-Code wird erfolgreich ausgeführt.

    Wird die Datei denn kopiert oder erkennt boost lediglich den Fehler nicht?



  • @manni66 sagte in cross-device kopieren mit std::filesystem:

    Wird die Datei denn kopiert oder erkennt boost lediglich den Fehler nicht?

    Die Datei wird mitsamt den drei Nullen kopiert. Mit dem Standard wird nur die Datei angelegt.



  • vermutlich verlangt die std implementierung dass der zielpfad auch auf eine datei zeigt und nicht auf ein Verzeichnis.
    Daher änder mal den to part auf "/mnt/file"



  • @firefly sagte in cross-device kopieren mit std::filesystem:

    Daher änder mal den to part auf "/mnt/file"

    Erzeugt das gleiche Ergebnis.



  • Was kommt denn für ein Error Code raus wenn Du

    bool copy_file( const path& from, const path& to, copy_options options, error_code& ec );
    

    nimmst?

    @firefly sagte in cross-device kopieren mit std::filesystem:

    Daher änder mal den to part auf "/mnt/file"

    Das auf jeden Fall: [fs.op.copy.file]/4.1.2:

    [Report an error as specified in [fs.err.report] if:] exists(to) is true and is_­regular_­file(to) is false, [...]



  • Erstes Beispiel:

    #include <fstream>
    #include <filesystem>
    #include <iostream>
    
    int main(){
        std::ofstream{"file"}.write("000", 3);
        std::string from = "file", to = "/mnt/file";
        std::error_code ec;
    
        if(std::filesystem::copy_file(from, to, std::filesystem::copy_options::overwrite_existing, ec))
            std::cout << "Success\n";
    
        else
            std::cerr << ec.value() << ':' << ec.message() << '\n';
    }
    

    Ausgabe; Datei wird angelegt, fehlen jedoch drei Nullen, es sei denn, ich führe das Programm mit Root-Rechten aus:

    1:Operation not permitted
    

    Dann mit Boost (ohne Root):

    #include <fstream>
    #include <boost/filesystem.hpp>
    #include <iostream>
    
    int main(){
        std::ofstream{"file"}.write("000", 3);
        std::string from = "file", to = "/mnt/file";
        boost::system::error_code ec;
    
        boost::filesystem::copy_file(from, to, boost::filesystem::copy_option::overwrite_if_exists, ec);
        std::cerr << ec.value() << ':' << ec.message() << '\n';
    }
    

    Ausgabe:

    0:Success
    

    Dann blkid /dev/smth:

    /dev/smth /mnt type fuseblk (rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other,blksize=4096)
    

    Versuche eine ext4-Datei auf ein exfat-Filesystem zu kopieren. Dann hab ich das hier versucht:

    Und { echo '000' > /mnt/f && cat /mnt/f; } && echo $?;:

    000
    0
    

    Dann hab ich noch touch f; test -f f && echo yes ohne Root-Permissions versucht:

    touch: setting times of 'f': Operation not permitted
    yes
    


  • push



  • pop


Log in to reply