Bug 108178 - Filesystem::copy_file can't copy from /proc on Linux machines
Summary: Filesystem::copy_file can't copy from /proc on Linux machines
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 11.3.0
: P3 normal
Target Milestone: 11.5
Assignee: Jonathan Wakely
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-12-19 15:11 UTC by Faivel Dragatsky
Modified: 2023-10-04 11:34 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-12-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Faivel Dragatsky 2022-12-19 15:11:38 UTC
Hello,
When trying to copy a file from /proc folder on Linux, copy_file won't copy the file but will generate a success status.

The problem is that copy_file passes 0 file size to sendfile() on Linux machines as you can see here: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/src/filesystem/ops-common.h#L499 
, making sendfile() to do nothing. Since most of the files if not all files in /proc don't have a valid file size, the copying will be successful but no files are copied.


Thanks,
Faivel
Comment 1 Richard Biener 2022-12-19 15:39:59 UTC
But that's a bug of the procfs filesystem, not of the standard library.
Comment 2 Jonathan Wakely 2022-12-19 15:47:30 UTC
Yes, but we should probably add a workaround anyway.

Maybe we should not use sendfile for zero-sized files, and use fstream instead. That will copy until EOF, without caring about the file size obtained from stat(2). For real files that actually do have zero size that might be slightly slower than attempting to use sendfile, but hopefully not too bad. I'll try to benchmark it.
Comment 3 Jonathan Wakely 2022-12-19 15:53:01 UTC
On the other hand, it's not a bug in /proc, because the size of some of those files might vary dynamically, and the size isn't known until you try to read it. So even if we got a size from stat, we might read a different number of bytes once we open it, and so sendfile wouldn't copy the whole thing anyway. And on the gripping hand, reading from /proc could be considered undefined behaviour because files that are changing while performing std::filesystem operations cause races and so the behaviour is not defined by the standard.

But we can make it work in practice.
Comment 4 Richard Biener 2022-12-20 12:39:21 UTC
In hindsight the files in /proc should probably have been named pipes, not regular files.
Comment 5 Jonathan Wakely 2023-03-21 12:02:47 UTC
I have a patch for GCC 14 stage 1.
Comment 6 Jonathan Wakely 2023-03-22 12:21:21 UTC
Patch: https://gcc.gnu.org/pipermail/gcc-patches/2023-March/614415.html
Comment 7 GCC Commits 2023-06-06 11:38:00 UTC
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:07a0e108247f23fcb919c61595adae143f1ea02a

commit r14-1570-g07a0e108247f23fcb919c61595adae143f1ea02a
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Mar 21 12:29:08 2023 +0000

    libstdc++: Make std::filesystem::copy_file work for procfs [PR108178]
    
    The size reported by stat is always zero for some special files such as
    those under /proc, which means the current copy_file implementation
    thinks there is nothing to copy. Instead of trusting the stat value, try
    to read a character from a streambuf and check for EOF.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/108178
            * src/filesystem/ops-common.h (do_copy_file): Check for empty
            files by trying to read a character.
            * testsuite/27_io/filesystem/operations/copy_file_108178.cc:
            New test.
Comment 8 GCC Commits 2023-06-06 14:10:58 UTC
The releases/gcc-13 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:c0a57904308ad0f10833f38cb207c750e5658b6b

commit r13-7420-gc0a57904308ad0f10833f38cb207c750e5658b6b
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Mar 21 12:29:08 2023 +0000

    libstdc++: Make std::filesystem::copy_file work for procfs [PR108178]
    
    The size reported by stat is always zero for some special files such as
    those under /proc, which means the current copy_file implementation
    thinks there is nothing to copy. Instead of trusting the stat value, try
    to read a character from a streambuf and check for EOF.
    
    For the backport, we also need to avoid trying to use sendfile when stat
    reports a zero size, so that we use streambufs to copy the file.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/108178
            * src/filesystem/ops-common.h (do_copy_file): Check for empty
            files by trying to read a character.
            * testsuite/27_io/filesystem/operations/copy_file_108178.cc:
            New test.
    
    (cherry picked from commit 07a0e108247f23fcb919c61595adae143f1ea02a)
Comment 9 GCC Commits 2023-10-03 16:11:08 UTC
The releases/gcc-12 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:f85947338197b12b77aa5eb0eb2d1b4ea7dbdd54

commit r12-9908-gf85947338197b12b77aa5eb0eb2d1b4ea7dbdd54
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Mar 21 12:29:08 2023 +0000

    libstdc++: Make std::filesystem::copy_file work for procfs [PR108178]
    
    The size reported by stat is always zero for some special files such as
    those under /proc, which means the current copy_file implementation
    thinks there is nothing to copy. Instead of trusting the stat value, try
    to read a character from a streambuf and check for EOF.
    
    For the backport, we also need to avoid trying to use sendfile when stat
    reports a zero size, so that we use streambufs to copy the file.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/108178
            * src/filesystem/ops-common.h (do_copy_file): Check for empty
            files by trying to read a character.
            * testsuite/27_io/filesystem/operations/copy_file_108178.cc:
            New test.
    
    (cherry picked from commit 07a0e108247f23fcb919c61595adae143f1ea02a)
Comment 10 GCC Commits 2023-10-04 11:29:33 UTC
The releases/gcc-11 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:d69407149194e2a7ee20537c76acb1976c8659be

commit r11-11048-gd69407149194e2a7ee20537c76acb1976c8659be
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Mar 21 12:29:08 2023 +0000

    libstdc++: Make std::filesystem::copy_file work for procfs [PR108178]
    
    The size reported by stat is always zero for some special files such as
    those under /proc, which means the current copy_file implementation
    thinks there is nothing to copy. Instead of trusting the stat value, try
    to read a character from a streambuf and check for EOF.
    
    For the backport, we also need to avoid trying to use sendfile when stat
    reports a zero size, so that we use streambufs to copy the file.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/108178
            * src/filesystem/ops-common.h (do_copy_file): Check for empty
            files by trying to read a character.
            * testsuite/27_io/filesystem/operations/copy_file_108178.cc:
            New test.
    
    (cherry picked from commit 07a0e108247f23fcb919c61595adae143f1ea02a)
Comment 11 Jonathan Wakely 2023-10-04 11:34:02 UTC
Fixed for 11.5, 12.4 and 13.2