Discussion:
how copy file on linux?
(too old to reply)
Thiago Adams
2024-06-26 20:44:48 UTC
Permalink
How to copy a file on linux keeping the original file information?
timestamp etc?

Or in other words the equivalent of CopyFileA from windows.
Janis Papanagnou
2024-06-26 21:48:15 UTC
Permalink
Post by Thiago Adams
How to copy a file on linux keeping the original file information?
timestamp etc?
This is an OS question and I'm not sure you want the shell command
or the library function.

On a Linux shell I do

cp -p # to preserve attributes
cp -a # incl. -p, to do a lot like copying recursive a directory
Post by Thiago Adams
Or in other words the equivalent of CopyFileA from windows.
And what exactly does it do? (Windows has - for example, since you
mentioned time stamps above - other time information than Unix
systems. So it may not be what you expect.)

Janis
Keith Thompson
2024-06-26 22:35:00 UTC
Permalink
Post by Thiago Adams
How to copy a file on linux keeping the original file information?
timestamp etc?
Or in other words the equivalent of CopyFileA from windows.
comp.unix.programmer is likely to give you better answers. I don't
think POSIX defines any functions that copy files.

If I uunderstand correctly, you want to do the equivalent of "cp -p",
but from C rather than from a shell. You might consider using system(),
but that has some drawbacks, and there are probably better ways.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+***@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
Lew Pitcher
2024-06-26 23:24:47 UTC
Permalink
(Followup set to comp.unix.programmer)
Post by Keith Thompson
Post by Thiago Adams
How to copy a file on linux keeping the original file information?
timestamp etc?
Or in other words the equivalent of CopyFileA from windows.
comp.unix.programmer is likely to give you better answers. I don't
think POSIX defines any functions that copy files.
No, AFAIK, POSIX doesn't define an "all-in-one" file copy function.
However, Linux (the OS Thiago asks about) defines a number of them.
Post by Keith Thompson
If I uunderstand correctly, you want to do the equivalent of "cp -p",
Which /can/ be accomplished with POSIX calls
- the standard I/O functions (fopen()/open(), fread()/read(),
fwrite()/write(), fclose()/close() ) to copy the file data
- stat() to obtain the "original file information", and
- utime() to set the copy timestamps,
- chmod() to set the copy file permissions
- chown() to set the file ownership

But, perhaps Thiago would be satisfied with just a hardlinked file.
Post by Keith Thompson
but from C rather than from a shell. You might consider using system(),
but that has some drawbacks, and there are probably better ways.
HTH
--
Lew Pitcher
"In Skills We Trust"
Lawrence D'Oliveiro
2024-06-26 23:43:04 UTC
Permalink
Post by Thiago Adams
How to copy a file on linux keeping the original file information?
timestamp etc?
Last-modified is usually the only timestamp people care about.
Scott Lurndal
2024-06-27 00:36:17 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Thiago Adams
How to copy a file on linux keeping the original file information?
timestamp etc?
Last-modified is usually the only timestamp people care about.
Do you think before you post?

That's not true.
Bonita Montero
2024-06-28 08:19:33 UTC
Permalink
Post by Scott Lurndal
Post by Lawrence D'Oliveiro
Post by Thiago Adams
How to copy a file on linux keeping the original file information?
timestamp etc?
Last-modified is usually the only timestamp people care about.
Do you think before you post?
That's not true.
No, he forgot he posted that thousand times because he didn't
copy the creation time of is objection. ;-)
Bonita Montero
2024-06-28 18:15:20 UTC
Permalink
I tried to implement that in C++. Unfortunately an error branch of the
code is taken. What Do I have to change ?

bool CopyFileA( char const *from, char const *to, bool overwrite )
{
struct stat attrFrom, attrTo;
if( stat( from, &attrFrom ) )
return false;
if( !overwrite && !stat( to, &attrTo ) && errno != ENOENT )
return false;
union ndi { char c; };
vector<char> buf( attrFrom.st_size >= 0x100000 ? 0x100000 :
attrFrom.st_size );
int fromFile = open( from, O_RDONLY | O_NOATIME );
if( !fromFile )
return false;
invoke_on_destruct closeFrom( [&] { close( fromFile ); } );
int toFile = open( to, O_CREAT );
if( !toFile )
return false;
invoke_on_destruct closeTo( [&] { close( toFile ); } );
invoke_on_destruct delTo( [&] { unlink( to ); } );
for( int64_t remaining = attrFrom.st_size; remaining > 0; remaining -=
0x100000 )
{
size_t n = (size_t)(remaining >= 0x100000 ? 0x100000 : remaining);
buf.resize( n );
if( read( fromFile, buf.data(), n ) )
{
// this branch is taken
cout << strerror( errno ) << endl;
return false;
}
if( write( toFile, buf.data(), n ) )
return false;
}
closeTo();
utimbuf utb;
utb.actime = attrFrom.st_atime;
utb.modtime = attrFrom.st_mtime;
if( utime( to, &utb ) )
return false;
if( chmod( to, attrFrom.st_mode ) )
return false;
if( chown( to, attrFrom.st_uid, attrFrom.st_gid ) && errno != EACCES )
return false;
delTo.disable();
return to;
}

If everything works fine at last I'll make a C-rewrite.
Scott Lurndal
2024-06-28 19:22:55 UTC
Permalink
Post by Bonita Montero
I tried to implement that in C++. Unfortunately an error branch of the
code is taken. What Do I have to change ?
You need to figure out which error branch is taken and
look at errno and the surrounding logic at that point
to see why the call failed.
Malcolm McLean
2024-06-28 23:04:00 UTC
Permalink
Post by Bonita Montero
int fromFile = open( from, O_RDONLY | O_NOATIME );
    if( !fromFile )
        return false;
   invoke_on_destruct closeFrom( [&] { close( fromFile ); } );
//    int toFile = open( to, O_CREAT );
//    if( !toFile )
//        return false;
    invoke_on_destruct closeTo( [&] { close( toFile ); } );
//     invoke_on_destruct delTo( [&] { unlink( to ); } );
    for( int64_t remaining = attrFrom.st_size; remaining > 0; remaining
-= 0x100000 )
    {
        size_t n = (size_t)(remaining >= 0x100000 ? 0x100000 : remaining);
        buf.resize( n );
        if( read( fromFile, buf.data(), n ) )
        {
            // this branch is taken
            cout << strerror( errno ) << endl;
            return false;
        }
So it claims the file opens, then won't read it?

Check the call. Is 0 the success return?

Then I must admit I'm stumped. "to" doesn't alias "from" I suppose?

I'd also wonder if somehow the C++ compiler has invoked the on destruct
code, and closed the file.
--
Check out my hobby project.
http://malcolmmclean.github.io/babyxrc
Lew Pitcher
2024-06-28 23:25:20 UTC
Permalink
Post by Malcolm McLean
Post by Bonita Montero
int fromFile = open( from, O_RDONLY | O_NOATIME );
    if( !fromFile )
        return false;
open() returns -1 on failure, and some non-negative number
on success. That non-negative number /can be/ 0 and still
be a valid success value.

The above test /will not/ detect an open() failure, as !(-1) == 0
However, the above /will/ falsely call a valid open() that returns
fd 0 (slim chance unless you've previously closed stdin).
Post by Malcolm McLean
Post by Bonita Montero
   invoke_on_destruct closeFrom( [&] { close( fromFile ); } );
//    int toFile = open( to, O_CREAT );
//    if( !toFile )
//        return false;
    invoke_on_destruct closeTo( [&] { close( toFile ); } );
//     invoke_on_destruct delTo( [&] { unlink( to ); } );
    for( int64_t remaining = attrFrom.st_size; remaining > 0; remaining
-= 0x100000 )
    {
        size_t n = (size_t)(remaining >= 0x100000 ? 0x100000 : remaining);
        buf.resize( n );
        if( read( fromFile, buf.data(), n ) )
        {
            // this branch is taken
            cout << strerror( errno ) << endl;
            return false;
        }
So it claims the file opens, then won't read it?
Check the call. Is 0 the success return?
Then I must admit I'm stumped. "to" doesn't alias "from" I suppose?
I'd also wonder if somehow the C++ compiler has invoked the on destruct
code, and closed the file.
--
Lew Pitcher
"In Skills We Trust"
Lew Pitcher
2024-06-28 23:27:49 UTC
Permalink
Oops. missed part of my edit. See unquoted line below
Post by Lew Pitcher
Post by Malcolm McLean
Post by Bonita Montero
int fromFile = open( from, O_RDONLY | O_NOATIME );
    if( !fromFile )
        return false;
open() returns -1 on failure, and some non-negative number
on success. That non-negative number /can be/ 0 and still
be a valid success value.
The above test /will not/ detect an open() failure, as !(-1) == 0
However, the above /will/ falsely call
a FAILURE (and return a "false" from the function)
Post by Lew Pitcher
a valid open() that returns
fd 0 (slim chance unless you've previously closed stdin).
Post by Malcolm McLean
Post by Bonita Montero
   invoke_on_destruct closeFrom( [&] { close( fromFile ); } );
//    int toFile = open( to, O_CREAT );
//    if( !toFile )
//        return false;
    invoke_on_destruct closeTo( [&] { close( toFile ); } );
//     invoke_on_destruct delTo( [&] { unlink( to ); } );
    for( int64_t remaining = attrFrom.st_size; remaining > 0; remaining
-= 0x100000 )
    {
        size_t n = (size_t)(remaining >= 0x100000 ? 0x100000 : remaining);
        buf.resize( n );
        if( read( fromFile, buf.data(), n ) )
        {
            // this branch is taken
            cout << strerror( errno ) << endl;
            return false;
        }
So it claims the file opens, then won't read it?
Check the call. Is 0 the success return?
Then I must admit I'm stumped. "to" doesn't alias "from" I suppose?
I'd also wonder if somehow the C++ compiler has invoked the on destruct
code, and closed the file.
--
Lew Pitcher
"In Skills We Trust"
Loading...