Looking for a C system call to copy files

Discussion in 'C Programming' started by Avi, May 29, 2007.

  1. Avi

    Avi Guest

    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:
     
    Avi, May 29, 2007
    #1
    1. Advertising

  2. Avi

    Ian Collins Guest

    Avi wrote:
    > 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.

    --
    Ian Collins.
     
    Ian Collins, May 29, 2007
    #2
    1. Advertising

  3. 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;
    }

    <snip>

    > 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:


    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.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, May 29, 2007
    #3
  4. On Tue, 29 May 2007 00:05:49 +0000, Richard Heathfield wrote:
    >Avi said:
    >> 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.


    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;
    >}
    >
    ><snip>
    >
    >> 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().


    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.


    --
    Roland Pibinger
    "The best software is simple, elegant, and full of drama" - Grady Booch
     
    Roland Pibinger, May 29, 2007
    #4
  5. Roland Pibinger said:

    > On Tue, 29 May 2007 00:05:49 +0000, Richard Heathfield wrote:


    <snip>

    >> rc |= COPYFILE_INCLOSE_ERROR;

    >
    > 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>

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, May 29, 2007
    #5
  6. Avi

    B. Augestad Guest

    Richard Heathfield wrote:
    > 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);
    > }


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


    Bjørn


    [snip]

    --
    Looking for an embeddable web server?
    http://www.metasystems.no/products/highlander/index.html
     
    B. Augestad, May 29, 2007
    #6
  7. B. Augestad said:

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


    ferror(fpout) is tested later in the code.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, May 29, 2007
    #7
  8. Avi

    B. Augestad Guest

    Richard Heathfield wrote:
    > B. Augestad said:
    >
    > <snip>
    >> Why did you chose not to check the return value of putc()?

    >
    > 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
     
    B. Augestad, May 29, 2007
    #8
  9. B. Augestad said:

    > Richard Heathfield wrote:
    >> B. Augestad said:
    >>
    >> <snip>
    >>> Why did you chose not to check the return value of putc()?

    >>
    >> 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?


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

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, May 29, 2007
    #9
  10. On Tue, 29 May 2007 20:47:00 +0200, "B. Augestad" wrote:
    >Richard Heathfield wrote:
    >> B. Augestad said:
    >>
    >> <snip>
    >>> Why did you chose not to check the return value of putc()?

    >>
    >> 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.


    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.


    --
    Roland Pibinger
    "The best software is simple, elegant, and full of drama" - Grady Booch
     
    Roland Pibinger, May 29, 2007
    #10
  11. Avi

    B. Augestad Guest

    Roland Pibinger wrote:
    > On Tue, 29 May 2007 20:47:00 +0200, "B. Augestad" wrote:
    >> Richard Heathfield wrote:
    >>> B. Augestad said:
    >>>
    >>> <snip>
    >>>> Why did you chose not to check the return value of putc()?
    >>> 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.

    >
    > 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

    --
    Looking for an embeddable web server?
    http://www.metasystems.no/products/highlander/index.html
     
    B. Augestad, May 29, 2007
    #11
  12. On Tue, 29 May 2007 21:38:05 +0200, "B. Augestad" wrote:
    >Roland Pibinger wrote:
    >> 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'?


    Error checking is done by ferror().
    >
    >> 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()?


    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().


    --
    Roland Pibinger
    "The best software is simple, elegant, and full of drama" - Grady Booch
     
    Roland Pibinger, May 29, 2007
    #12
  13. Avi

    B. Augestad Guest

    Roland Pibinger wrote:
    > On Tue, 29 May 2007 21:38:05 +0200, "B. Augestad" wrote:
    >> Roland Pibinger wrote:
    >>> 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'?

    >
    > Error checking is done by ferror().
    >>> 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()?

    >
    > 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
     
    B. Augestad, May 29, 2007
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alex
    Replies:
    2
    Views:
    1,233
  2. Russell Warren
    Replies:
    1
    Views:
    787
    Tim Roberts
    Apr 27, 2006
  3. Tim Golden
    Replies:
    0
    Views:
    606
    Tim Golden
    Apr 27, 2006
  4. Replies:
    26
    Views:
    2,119
    Roland Pibinger
    Sep 1, 2006
  5. Avi
    Replies:
    1
    Views:
    556
    Ian Collins
    May 29, 2007
Loading...

Share This Page