I created this file
char *output = "big";
creat(output, O_RDWR);
When I'm trying to read the file
cat big
I'm getting permission denied. Whats wrong with my code? How to create a file with read and write permission mode?
with ls -l, the permission of big looked like this
----------
what does this mean?
You have misinterpeted the mode argument. From the man page:
mode specifies the permissions to use in case a new file is cre‐
ated. This argument must be supplied when O_CREAT is specified
in flags; if O_CREAT is not specified, then mode is ignored.
The effective permissions are modified by the process's umask in
the usual way: The permissions of the created file are
(mode & ~umask). Note that this mode only applies 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.
and also
creat() is equivalent to open() with flags equal to
O_CREAT|O_WRONLY|O_TRUNC.
So, a more appropriate call might look like:
int fd = creat(output, 0644); /*-rw-r--r-- */
If you want to open it O_RDWR though, then just use open():
int fd = open(output, O_CREAT|O_RDWR|O_TRUNC, 0644);
This is obviously a permission issue, start trying to see if creat doesn't returns -1, if so, print the errno value, with perror(""), so that you could resolve the problem.
Imho, i'd rather use open() to do this, because as mentionned in the creat man page,
"Note that open() can open device special files, but creat() cannot create them; ..", and
"creat() is equivalent to open() with flags equals to O_CREAT | O_WRONLY | O_TRUNC", and this doesn't talks about the permissions..
it would be the exact same result if you did this:
char* output = "big";
int fd;
fd = open(output, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
// do whaterver you want to do in your file
close(fd);
For more information, "man 2 open"
Related
I want to know which purpose has the following line of code in Linux syscall int open(const char *pathname, int flags):
if (flags & ~(O_RDONLY | O_WRONLY | O_CREAT | O_RDWR | O_TRUNC | O_APPEND))
{
return -1;
}
This line checks that your file have only these properties available :
O_RDONLY : read-only file
O_WRONLY : write-only file
O_CREAT : create the file if it does not exist
O_RDWR : read-write file
O_TRUNC : If the file already exists and is a regular file and the access
mode allows writing (i.e., is O_RDWR or O_WRONLY) it will be
truncated to length 0.
O_APPEND : the file is opened in append mode
Without knowing the actual values of that O_RDONLY, O_WRONLY, and O_RDWR are assigned, it's not really possible to determine what that code actually does.
The code
if (flags & ~(O_RDONLY | O_WRONLY | O_CREAT | O_RDWR | O_TRUNC | O_APPEND))
{
return -1;
}
is non-portable and strictly speaking invalid outside of the actual system implementation that has access to and control of the actual values of the flags. Per POSIX, the flags O_RDONLY, O_WRONLY, and O_RDWR are NOT bit flags:
Values for oflag are constructed by a bitwise-inclusive OR of flags from the following list, defined in . Applications shall specify exactly one of the first five values (file access modes) below in the value of oflag:
O_EXEC
Open for execute only (non-directory files). The result is unspecified if this flag is applied to a directory.
O_RDONLY
Open for reading only.
O_RDWR
Open for reading and writing. The result is undefined if this flag is applied to a FIFO.
O_SEARCH
Open directory for search only. The result is unspecified if this flag is applied to a non-directory file.
O_WRONLY
Open for writing only.
Since those flags are not bit-based but actual value-based, their presence or absence can not be detected via bitwise operations without knowledge of their actual values on the system in use.
This code uses more than one of those flags, violating the POSIX specification:
O_RDONLY | O_WRONLY | O_CREAT | O_RDWR | O_TRUNC | O_APPEND
It can in theory produce a nonsensical bit value that can not be used in a valid bitwise comparison to anything.
The RATIONALE section of the open() POSIX documentation even addresses the non-bit flag-based nature of the open() flags:
RATIONALE
In historical implementations the value of O_RDONLY is zero. Because of that, it is not possible to detect the presence of O_RDONLY and another option. Future implementations should encode O_RDONLY and O_WRONLY as bit flags so that:
O_RDONLY | O_WRONLY == O_RDWR
That comment only makes sense if O_RDONLY, O_WRONLY and O_RDWR are not bit-based flags.
I am writing a program which requires me to create a file using standard fopen fprintf fclose calls.
I want to set the execute bits.
I can do this with chmod but this seems overkill. For the life of me (possibly due to advanced age) I can't seem to find (or remember) an API to do this.
fchmod(2) would be in keeping with your other calls... Given a file descriptor in fd:
struct stat buf;
fstat(fd, &buf);
fchmod(fd, buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
will add all three execute bits to the file's current mode (error handling left as an exercise for the reader).
You'd use fileno(3) to get the file descriptor from your FILE * structures. Alternatively you could use chmod(2) and pass it the file name.
chmod(2) is an API call,
and is the canonical way of changing the mode of a file (referenced by name)
from a program; it is not overkill.
You could use fchmod (see fchmod(3)), or umask if you want to apply the same for every file created (extracts below taken from http://www.gnu.org/software/libc/manual/html_node/Setting-Permissions.html and the umask(2) man page):
The functions in this section are declared in sys/stat.h.
Function: mode_t umask (mode_t mask)
The umask function sets the file creation mask of the current process to mask, and returns the previous value of the file creation mask.
Here is an example showing how to read the mask with umask without changing it permanently:
mode_t
read_umask (void)
{
mode_t mask = umask (0);
umask (mask);
return mask;
}
However, on GNU/Hurd systems it is better to use getumask if you just want to read the mask value, because it is reentrant.
Name
umask - set file mode creation mask
mode_t umask(mode_t mask);
Description
umask() sets the calling process's file mode creation mask (umask) to mask & 0777 (i.e., only the file permission bits of mask are used), and returns the previous value of the mask.
The umask is used by open(2), mkdir(2), and other system calls that create files to modify the permissions placed on newly created files or directories. Specifically, permissions in the umask are turned off from the mode argument to open(2) and mkdir(2).
The constants that should be used to specify mask are described under stat(2).
The typical default value for the process umask is S_IWGRP | S_IWOTH (octal 022). In the usual case where the mode argument to open(2) is specified as:
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
(octal 0666) when creating a new file, the permissions on the resulting file will be:
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
(because 0666 & ~022 = 0644; i.e., rw-r--r--).
Return Value
This system call always succeeds and the previous value of the mask is returned
I'm trying to create a C code which will create a file for which I can read or write from/to. This file can already exist, or need to be created from scratch. If it already exists within the directory, I want it to created from scratch, in other words delete all the contents.
FD = open("p.txt", O_RDWR | O_CREAT | O_TRUNC);
I've tried using that for the time being. I encounter a problem though. If the file doesn't exist, it creates it and returns a positive file descriptor.
If the file however already exists, a -1 FD is returned. So I must be missing a flag?
I assumed O_TRUNC would be enough to clear the contents of a file?
FD = open("p.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
When a Unix call returns -1, check the value of the errno variable. It contains the reason for the error. Don't speculate as to what might be the problem until you've seen the error code. You can call strerror or perror to get a message describing the numerical value stored in errno.
Also, as others have noted, when you pass O_CREAT to open, you must pass a third argument which determines the file's permission if it's created. (If you don't )
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main() {
int fd = open("p.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd == -1) {
perror("opening p.txt");
exit(1);
}
/* … */
}
I have problem I want to open a file with .out extension or if it not exist then it should create it with permissions to read and write and by opening file I want to erase his content
variable = open( "file.out", O_RDWR | O_CREAT, S_IRWXO, O_TRUNC )
I used this command but it always fails I think I have bad flags as far I know:
O_RDWR is to open file with write and read permission
O_CREAT it creates file if not exist
S_IRWXO is used by O_CREAT to make the file readable and writable
O_TRUNC erase all data from file
open doesn't take 4 arguments - only 2 or 3. All of the O_ flags should be OR'ed together in the second argument. Also, S_IRWXO will give permissions only to others, not to the owner or group owner. You meant S_IRWXU | S_IRWXG | S_IRWXO probably. But I'd rather just see an octal number; the macros aren't more readable.
variable = open( "file.out", O_RDWR | O_CREAT | O_TRUNC, 0777 )
If you want read/write/execute permission for the current user/owner use: S_IRWXU:
S_IRWXO
Read, write, and search or execute permission for users other than the
file owner. S_IRWXO is the bitwise inclusive-OR of S_IROTH, S_IWOTH,
and S_IXOTH.
S_IRWXU
Read, write, and search, or execute, for the file owner; S_IRWXG is the
bitwise inclusive-OR of S_IRUSR, S_IWUSR, and S_IXUSR.
Doing open( "file.out", O_RDWR | O_CREAT, S_IRWXU, O_TRUNC ); and ls -l gives:
-rwx------. 1 perreal perreal 0 Apr 29 15:52 file.out
I try to open a file like this in linux. It will over-write an existing one if exits. That is what I want.
fout = open(out_file_name, O_WRONLY | O_CREAT, 644);
However, if the existing is 1024 bytes, when I open in above way and write 800 new bytes.
I still see the 224 bytes at the end of previous content.
How can I make it just have the 800 bytes that I have been written?
You want to use the O_TRUNC flag to open(), by OR-ing it with the existing flags you have above:
int fout = open(out_file_name, O_WRONLY | O_CREAT | O_TRUNC, 644);
This will truncate the file. Below is the information in the man page for open(2).
O_TRUNC
If the file already exists and is a regular file and the open
mode allows writing (i.e., is O_RDWR or O_WRONLY) it will be
truncated to length 0. If the file is a FIFO or terminal device
file, the O_TRUNC flag is ignored. Otherwise the effect of
O_TRUNC is unspecified.