help with stat() and fopen()

This is a discussion on help with stat() and fopen() within the C Programming forums, part of the General Programming Boards category; Code: /* a very simple copy command for unix */ #include <sys/stat.h> #include <sys/types.h> #include <errno.h> #include <string.h> int main(int ...

  1. #1
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72

    help with stat() and fopen()

    Code:
    /* a very simple copy command for unix */
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <errno.h>
    #include <string.h>
    
    int main(int argc, char *argv[])
    {
             struct stat flinfo;                   /* structure holding file info read by stat() */
    
             if (argc != 3) 
                    display_usage(1);
             
    
             /* we're doing a copy, so we want to see the permissions of file a */
             errno = 0;
             if ( (stat(argv[1],  flinfo)) == -1) {
                  fprintf(stderr, "copy: %s: %s\n", argv[1], strerror(errno));
                  exit(1);
             }
    
             /* open argv[1] for reading */
             fd = open(argv[1], O_RDONLY);
    
            /* now open argv[2] with same permissions as argv[1], so that the resulting
                copied file has same permissions    */
            errno = 0;
            if ( (fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, flinfo.st_mode)) == -1)
                  fprintf(stderr, "copy: %s: %s\n", argv[2], strerro(errno));
                  exit(1);
            }
    
    
            /* then here I'd do the actual copy with read() and write() */
    
    }

    I'm doing the above with low level (OS specific) functions and wish to do them with
    fopen, fgetc, etc. My problem is with using the 'mode' argument with fopen() so that the
    resulting file will be of the same permissions (executable, etc). The above worked fine
    using the above code (plus the rest, not shown) to make a simple 'copy' command. You can
    pass the st_mode of the first file you open read with stat(), to open(). Can I do the same
    with the fopen() function? I tried fopen() and then did a stat(), and then used umask() to
    set the mode of the 2nd file I wanted to create with fopen() for the copy, but it didn't
    seem to work. Can anyone give some suggestions?

    thanks
    Remember that all that code you write turns into this:

    0100100100110010010011100100111001001
    0010100100100001001111100010010010010 ....

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,535
    There is no standard way to set the permissions on a file.
    So you can use fopen() etc to copy the file, but you still need to "stat" to find its real permissions.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    Thanks, but how do I pass the st_mode (permissions) read by stat() to fopen?

    with open I do:
    Code:
        open(filename, O_WRONLY | O_CREAT | O_TRUNC, fl.st_mode);
    That creates a new file with the same permissions as the first file that I stat()'d
    such as for a copy.

    But how do I pass the st_mode element of struct stat fl (first file's info) to fopen()?
    Doesn't fopen() only take fopen(filename, "w") ?

    Thanks
    Remember that all that code you write turns into this:

    0100100100110010010011100100111001001
    0010100100100001001111100010010010010 ....

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,535
    You have to do a chmod() after the file has been created.

    Or if you want to make sure that the file has the right permissions thoughout, create it with the right permissions, then fopen() it later using one of the "update" modes.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    Quote Originally Posted by movl0x1 View Post
    Thanks, but how do I pass the st_mode (permissions) read by stat() to fopen?
    You can't directly. First, open the file with open() and then turn it into a FILE object with fdopen:

    Code:
    FILE *fp;
    int fd;
    
    umask(0); /* See below */
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, fl.st_mode);
    if(fd < 0)
    {
        /* Error */
    }
    else
    {
        fp = fdopen(fd, "wb");
    }
    There is a problem here, though. The st_mode you pass to open() will be combined with the current umask to form the real permissions. For a copy program, you do NOT want this -- you want the permissions to be exactly as passed. So, you need to clear the umask before calling open() -- as highlighted in blue in the code.

    The change to the umask only affects your program, not the shell or any other process.

  6. #6
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    Thanks guys. But what I did was do a stat() on the first file (the one I want to copy) to
    get its permissions (st_mode). Then I did an fopen() on the 2nd file (the one I want to create
    and copy file a to) and used chmod() on the 2nd file I just created and it works every time.

    Code:
          struct stat fl;
    
          /* open first file (1 I want to copy) */
          in = fopen(argv[1], "r");
    
          /* get the first file's info into fl */
          stat(argv[1], &fl);
    
         /* open the file we want to create and copy to */
          out = fopen(argv[2], "w");
    
         /* Now we want to set our new file to the same
             permissions as argv[1]  */
         chmod(argv[2], fl.st_mode);
    The above of course excludes all error checks, etc. which I have
    in the real program.


    So I basically just open the 2nd file with fopen() and copy the mode of the first
    open file with chmod() to the new file.

    thanks
    Last edited by movl0x1; 07-25-2007 at 05:15 AM.
    Remember that all that code you write turns into this:

    0100100100110010010011100100111001001
    0010100100100001001111100010010010010 ....

  7. #7
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,535
    > fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, fl.st_mode);
    Will this allow you to copy a file which is read-only?
    IE, will the file you're trying to create be read-only at the point you create it?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21