user173717
user173717

Reputation: 83

Write to file without write permission in C?

I want to create a file and the file has no write permission like this.

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

main()
{
    int fd;
    fd=open("xxx",O_CREAT|O_WRONLY|O_APPEND,S_IRUSR);
    if(fd==-1)
        return 0;
    else
        if(write(fd,"created",7)==-1)
            return 0;
    if(close(fd)==-1)
        return 0;
    printf("OK");
}   

I ran executable file and notice that the file xxx could be written to. Of cource, when I ran executable after first time, it worked like I expect when it could't be written to.

But how can I make the file xxx even can't be written to in first time (when it is created).

Upvotes: 2

Views: 2572

Answers (2)

Michi
Michi

Reputation: 5297

You should remove:

O_WRONLY

And it should look like this:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(void){
    int fd;
    fd=open("test.sh",O_CREAT|O_APPEND,S_IRUSR);

    if(fd==-1)
        return 0;
    else
        if(write(fd,"created",7)==-1)
            return 0;
    if(close(fd)==-1)
        return 0;
    printf("OK");

    return 0;
}

And if you try to write that file, you will get:

[ Error writing test.sh: Permission denied ]

Anyway, on my Linux machine if I wanna check that file, I will do it like this:

#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>

void fileCheck(const char *fileName){

    if(!access(fileName, F_OK )){
        printf("The File %s\t Found\n",fileName);
    }else{
        printf("The File %s\t not Found\n",fileName);
        exit(1);
    }

    if(!access(fileName, R_OK )){
        printf("The File %s\t can be read\n",fileName);
    }else{
        printf("The File %s\t cannot be read\n",fileName);
    }

    if(!access( fileName, W_OK )){
        printf("The File %s\t it can be Edited\n",fileName);
    }else{
        printf("The File %s\t it cannot be Edited\n",fileName);
    }

    if(!access( fileName, X_OK )){
        printf("The File %s\t is an Executable\n",fileName);
    }else{
        printf("The File %s\t is not an Executable\n",fileName);
    }
}

int main (void){
   char *fileName = "test.sh";

    fileCheck(fileName);

   return 0;
}

And the output says:

The File test.sh   Found
The File test.sh     can be read
The File test.sh     it cannot be Edited
The File test.sh     is not an Executable

Upvotes: 3

Spark.Bao
Spark.Bao

Reputation: 5743

I can understand author's intent. He want to test the usage of S_IRUSR. I will explain why it doesn't work at first time.

At first let us resolve your question. you can just remove O_WRONLY and O_APPEND flag, and add O_RDONLY flag or not. Codes are following:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

int main() {
    int fd;
    fd = open("xxx", O_CREAT|O_RDONLY, S_IRUSR);
    // or
    // fd = open("xxx", O_CREAT, S_IRUSR);
    if (fd == -1) {
        printf("open failed\n");
        return 0;
    } else {
        if (write(fd, "created", 7) == -1) {
            printf("write failed\n");
            return 0;
        }
    }
    if (close(fd) == -1) {
        printf("close failed\n");
        return 0;
    }
    printf("OK\n");
} 

then execute the program whenever, it will always says "write failed", and "xxx" is empty.

$ ls
test.c
$ make test
cc test.c -o test
$ ls
test test.c
$ ./test
write failed
$ ls
test test.c xxx
$ cat xxx
$ ./test
write failed

you said:

Of cource, when I ran executable after first time, it worked like I expect when it could't be written to.

in fact, if use your code, ran after first time, it is not couldn't be written to, it is not be open.

$ ls
test test.c
$ ./test
OK
$ ls
test test.c xxx
$ cat xxx
created
$ ./test
open failed

Then let us face the more important question, why S_ISUSR doens't work at first time. let us run 'man 2 open', it says:

Note that this mode applies only to future accesses of the newly created file; the open() call that creates a read-only file may well return a read/write file descriptor.

It means S_ISUSR only works after first time. Even S_ISUSR is read only, but in fact still return read/write permission, the final permission depends on the flags, if the flag is O_WRONLY, it can only write when create, if the flag is O_RDONLY, it can only read when create.

let's do a test:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

int main() {
    int fd;
    char buf[10];
    fd = open("xxx", O_CREAT|O_WRONLY, S_IRUSR);
    if (fd == -1) {
        printf("open failed\n");
        return 0;
    } else {
        if (write(fd, "created", 7) == -1) {
            printf("write failed\n");
            return 0;
        }
    }
    if (read(fd, buf, 7) == -1) {
        printf("read failed\n");
        return 0;
    } else {
        printf(buf);
    }
    if (close(fd) == -1) {
        printf("close failed\n");
        return 0;
    }
    printf("OK\n");
} 

and result is expected, at first time, when file create, if has write permission and has no read permission, after first time, it open failed:

$ ls
test.c
$ make test
cc test.c -o test
$ ./test
read failed
$ ./test
open failed
$ cat xxx
created

And I can understand why they design the mode parameter only work after first time. You think, if S_IRUSR works when file create, then the file is always empty and read only, it has no sense.

Upvotes: 1

Related Questions