Looking for a C system call to copy files

A

Avi

Hi,

Is there a UNIX C system command that will let me copy a file?
I am looking for something similar to "cp" that can be called within a
C program.
I know of the "link" system call but this command will set a the
second file as a link to the first file rather than an independent
copy of the first file.
(Windows has the CopyFile command but I didn't find anything that
would work under UNIX)

I am also looking for C commands to move files. Is the C system call
"rename" equivalent to Window's specific MoveFileEx function?

Thanks,
Avner Moshkovitz
Research Analyst
Email: (e-mail address removed)
 
I

Ian Collins

Avi said:
Hi,

Is there a UNIX C system command that will let me copy a file?
I am looking for something similar to "cp" that can be called within a
C program.
I know of the "link" system call but this command will set a the
second file as a link to the first file rather than an independent
copy of the first file.
(Windows has the CopyFile command but I didn't find anything that
would work under UNIX)

I am also looking for C commands to move files. Is the C system call
"rename" equivalent to Window's specific MoveFileEx function?
comp.unix.programmer would be a better place for these questions. The
only standard C way would be to use the system() function to invoke the
appropriate commands.
 
R

Richard Heathfield

Avi said:
Hi,

Is there a UNIX C system command that will let me copy a file?
I am looking for something similar to "cp" that can be called within a
C program.

#include <stdio.h>

#define COPYFILE_OK 0
#define COPYFILE_READ_ERROR 1
#define COPYFILE_WRITE_ERROR 2
#define COPYFILE_OUTCLOSE_ERROR 4
#define COPYFILE_OUTOPEN_ERROR 8
#define COPYFILE_INCLOSE_ERROR 16
#define COPYFILE_INOPEN_ERROR 32

int copyoneunixfiletoanother(const char *fntarget, const char *fnsource)
{
int rc = COPYFILE_OK;
FILE *fpin = fopen(fnsource, "rb");
if(fpin != NULL)
{
FILE *fpout = fopen(fntarget, "wb");
if(fpout != NULL)
{
int ch = 0;
while((ch = getc(fpin)) != EOF)
{
putc(ch, fpout);
}
if(ferror(fpin))
{
rc |= COPYFILE_READ_ERROR;
}
if(ferror(fpout))
{
rc |= COPYFILE_WRITE_ERROR;
}
if(fclose(fpout) != 0)
{
rc |= COPYFILE_OUTCLOSE_ERROR;
}
}
else
{
rc |= COPYFILE_OUTOPEN_ERROR;
}
if(fclose(fpin) != 0)
{
rc |= COPYFILE_INCLOSE_ERROR;
}
else
{
rc |= COPYFILE_INOPEN_ERROR;
}
return rc;
}

I am also looking for C commands to move files. Is the C system call
"rename" equivalent to Window's specific MoveFileEx function?

The standard C library function, rename(), changes the name of a file.
If your implementation considers a file's path to be part of its name,
then it will presumably allow you to move files using rename().
Thanks,
Avner Moshkovitz
Research Analyst
Email: (e-mail address removed)

Consider extending your researches to encompass "The C Programming
Language", 2nd edition, by Brian W Kernighan and Dennis M Ritchie,
which covers the above topics on pp 16-17, 162, and 242.
 
R

Roland Pibinger

Avi said:

IIRC, cp can be called from within a C program.
#include <stdio.h>

#define COPYFILE_OK 0
#define COPYFILE_READ_ERROR 1
#define COPYFILE_WRITE_ERROR 2
#define COPYFILE_OUTCLOSE_ERROR 4
#define COPYFILE_OUTOPEN_ERROR 8
#define COPYFILE_INCLOSE_ERROR 16
#define COPYFILE_INOPEN_ERROR 32

int copyoneunixfiletoanother(const char *fntarget, const char *fnsource)
{
int rc = COPYFILE_OK;
FILE *fpin = fopen(fnsource, "rb");
if(fpin != NULL)
{
FILE *fpout = fopen(fntarget, "wb");
if(fpout != NULL)
{
int ch = 0;
while((ch = getc(fpin)) != EOF)
{
putc(ch, fpout);
}
if(ferror(fpin))
{
rc |= COPYFILE_READ_ERROR;
}
if(ferror(fpout))
{
rc |= COPYFILE_WRITE_ERROR;
}
if(fclose(fpout) != 0)
{
rc |= COPYFILE_OUTCLOSE_ERROR;
}
}
else
{
rc |= COPYFILE_OUTOPEN_ERROR;
}
if(fclose(fpin) != 0)
{
rc |= COPYFILE_INCLOSE_ERROR;

Here obviously the closing brace is missing. Moreover, the return
value of fclose() should never be considered when the file was opened
only for reading.
}
else
{
rc |= COPYFILE_INOPEN_ERROR;
}
return rc;
}



The standard C library function, rename(), changes the name of a file.
If your implementation considers a file's path to be part of its name,
then it will presumably allow you to move files using rename().

rename() presumably works when source and destination are on the same
file system. A move_file function should first try to use rename() and
in case of failure copy the file.
 
R

Richard Heathfield

Roland Pibinger said:
On Tue, 29 May 2007 00:05:49 +0000, Richard Heathfield wrote:


Here obviously the closing brace is missing.
Whoops.

Moreover, the return
value of fclose() should never be considered when the file was opened
only for reading.

I can see why you might choose to omit the check, but I think "never" is
overstating your case.

<snip>
 
B

B. Augestad

Richard said:
Avi said:


#include <stdio.h>

#define COPYFILE_OK 0
#define COPYFILE_READ_ERROR 1
#define COPYFILE_WRITE_ERROR 2
#define COPYFILE_OUTCLOSE_ERROR 4
#define COPYFILE_OUTOPEN_ERROR 8
#define COPYFILE_INCLOSE_ERROR 16
#define COPYFILE_INOPEN_ERROR 32

int copyoneunixfiletoanother(const char *fntarget, const char *fnsource)
{
int rc = COPYFILE_OK;
FILE *fpin = fopen(fnsource, "rb");
if(fpin != NULL)
{
FILE *fpout = fopen(fntarget, "wb");
if(fpout != NULL)
{
int ch = 0;
while((ch = getc(fpin)) != EOF)
{
putc(ch, fpout);
}

Why did you chose not to check the return value of putc()?


Bjørn


[snip]
 
B

B. Augestad

Richard said:
B. Augestad said:



ferror(fpout) is tested later in the code.

I saw that, but what if the call to putc() fails on the first byte out
of a couple of gigabytes? The code will keep calling putc() millions of
times. Either that or one risks partial copies.

Bjørn
 
R

Richard Heathfield

B. Augestad said:
I saw that, but what if the call to putc() fails on the first byte out
of a couple of gigabytes?

Fair point. Feel free to adjust the code accordingly if you wish.
 
R

Roland Pibinger

I saw that, but what if the call to putc() fails on the first byte out
of a couple of gigabytes? The code will keep calling putc() millions of
times. Either that or one risks partial copies.

The implementation must be fast for the usual successful case, not the
rare error case. The code assumes that putc() and getc() are macros
(i.e. they are nor called). Partial copies are avoided by using a
temporal file(name) as destination which is renamed after successful
completion of the copy operation.
 
B

B. Augestad

Roland said:
The implementation must be fast for the usual successful case, not the
rare error case. The code assumes that putc() and getc() are macros
(i.e. they are nor called).

Are you advocating that we drop error checking because it slows down the
'usual successful case'?

Partial copies are avoided by using a
temporal file(name) as destination which is renamed after successful
completion of the copy operation.

How does that help? If the code is used to copy 1GB and putc() fails for
byte 100..1000 but succeeds for byte 0..9 and 101..1GB, how do you
detect that unless you either test the return value of putc()?

Bjørn
 
R

Roland Pibinger

Are you advocating that we drop error checking because it slows down the
'usual successful case'?

Error checking is done by ferror().
How does that help? If the code is used to copy 1GB and putc() fails for
byte 100..1000 but succeeds for byte 0..9 and 101..1GB, how do you
detect that unless you either test the return value of putc()?

It doesn't work that way. After an error the stream remains in the
error state unless clearerr() is called. But admittedly it's not very
elegant to continue 'calling' putc() after an error. I'd probably
prefer fread() and fwrite() to getc() and putc().
 
B

B. Augestad

Roland said:
Error checking is done by ferror().

It doesn't work that way. After an error the stream remains in the
error state unless clearerr() is called.

Good thinking, thanks. I never tought of it that way, but you're right.
But admittedly it's not very
elegant to continue 'calling' putc() after an error. I'd probably
prefer fread() and fwrite() to getc() and putc().

Or maybe even some platform specific solution never to be mentioned in
c.l.c? ;-)

Bjørn
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top