How to get the mode a file was opened in C (LINUX) - c

I want to implement a function that gets as parameter a FILE*, that is already open in write mode (a, a+, w, w+ etc), and reads the contents of that file. The problem here is that the file is already locked (because of the fopen) and I need to close it before starting reading.
However, after I have read the file I need to reopen it just like it was before my function was called.
Thus, I need both the file name and the mode the fopen was called with, initially.
I was able to get the file name. However the mode seems to be tricky.
Since now I was able to get the mode code using the code below.
int fd = fileno(file_pointer);
int mode = fcntl(fd, F_GETFL);
Unfortunately, there is inconsistency among systems (same open mode -> different mode codes). Is the method shown above an actual way to get the mode a file was open in? Do you have any other ideas?

Related

How to make child process use append mode? [duplicate]

i am trying to open a file in append mode using open() api call , however following code is not working ! Its not writing anything to file! here is my code :
O_APPEND is not a mode by itself; it's a flag. Since the value of O_RDONLY is 0, it's like you're trying to open the file read-only but for append, which is nonsense. Use O_WRONLY|O_APPEND or O_RDWR|O_APPEND.

How does mode affect the permisson on newly created files in Linux?

I'm new to Linux, still struggling to understand how permisson control work in Linux. The open function prototype is sth like :
int open(char *filename, int flags, mode_t mode);
Let's I have the following code:
fd = open("foo.txt", O_CREAT|O_RDWR, S_IRUSR)
and let's say the file "foo.txt" didn't exist before, so the above statment will create a file called "foo.txt", and current process who executes this open statment can read and write this file. But after this process terminates, If another process starts and tries to open this file. Below is my question:
Q1-Since the file was created with S_IRUSR(owner can read this file) in the first open call, does it mean that even I as owner of the file, if I start a new process to open this file again, I can only read this file and I cannot write this file, is my understanding correct?
If my understanding is correct, is it sensible/practicable that owners create sth that they cannot have full access to it later?
Q2-If my above understanding is correct, then in the second call to open by a new process. I can only call like:
fd = open("foo.txt", O_RDONLY) // uses flags like O_WRONLY or O_RDWR will throw an error?
since the first open specified the mode as S_IRUSR, which maps to O_RDONLY in the subsequent calls, is my understanding correct?
Correct, if you create the file with permissions S_IRUSR (often written in octal as 0400), then you will not be able to open the file for writing. Attempting to do so will fail and set errno to EACCES.
This is quite practical as it gives you a way to protect files you do not want to accidentally overwrite, as long as the permissions stay as they are. However, as the owner, you have the power to change the permissions later, using the chmod() system call. So it's not as though you have permanently lost the ability to write that file; you can give yourself back that ability whenever you want.

Any reason to reopen as "write-append" after "read-only"?

I have a save file containing a stream of program events. The program may read the file and execute the events to restore a previous state (say between program invocations). After that any new events are appended to this file.
I could open the file once as read-write (fopen rw), not exposing the usage pattern.
But I wonder if there are any benefits of opening it as read-only at first (fopen r) and later re-opening it as append (freopen a). Would there be any appearent difference?
In your case there may not be any specific benefits, but primary use of freopen is to change the file associated with standard text stream (stdin, stdout, stderr). It may effect the readability of your code if you use if on normal files. In your case you first open in read-only mode, but if you are opening the stream as output there are few things about freopen that we need to keep in mind.
On Linux, freopen may also fail and set errno to EBUSY when the kernel structure for the old file descriptor was not initialized completely before freopen was called
freopen should not be used on output streams because it ignores errors while closing the old file descriptor.
Read about freopen and possible error conditions with fclose in GNU manual: https://www.gnu.org/software/libc/manual/html_node/Opening-Streams.html#Opening-Streams
No there are no specific benefits of opening the file as Read Only and then reopening in Append mode. If you require changes in files during program execution than better if you open it in as per mode.

Text mode adapter for binary (or text) mode file

I have a method (parse) that processes data from an input file, which may have been opened in binary mode. However in some subclasses it would be easier to process the data if the file were opened in text mode. So my question is if theres an easy way to wrap any file to get something that acts as a text mode file.
Note that the solution in "Convert binary input stream to text mode" does not really make it as it only produces an iterator (and not a file-like object). Also note that opening the file in text mode in the first place is not an option.
If it simplifies the solution one can assume that the input file is indeed opened in binary mode.
It appears as the buffer argument in io.TextIOWrapper is actually an io.BufferedReader object (ie file opened in binary mode). This is however not obvious from reading the documentation.
This seem to work if the file is known to be opened in binary mode (instance of io.RawIOBase or io.BufferedIOBase):
srctxt = io.TextIOWrapper(src)
It doesn't work however if src is already opened in text mode, but it could be tested by checking if it is is an io.TextIOBase:
if isinstance(src, io.TextIOBase):
srctxt = src
else:
srctxt = io.TextIOWrapper(src)

How to check if a file still exists using a file descriptor

I have a file descriptor that is set to a positive value with the result of a open() function so this fd is indicating a file. When i delete the actual file fd is still a positive integer. I want to know that if i delete a file for some reason, how can i know that this file descriptor is not valid anymore. In short, how can i know that the file that fd is indicating, still there or not. I am trying to do this in C on FreeBSD.
Unix systems let you delete open files (or rather, delete all references to the file from the filesystem). But the file descriptor is still valid. Any read and write calls will be successful, as they would with the filename still there.
In other words, you cannot fully delete a file until the file descriptor is closed. Once closed, the file will then be removed automatically.
With a valid file descriptor, you can check if the filename still exists, e.g.
printf("%d\n", buf.st_nlink); // 0 means no filenames
Where buf is a struct stat initialised with fstat.
Before writing to the file you could check if it is still there using access()
if (access("/yourfile",W_OK)!=-1) {
//Write on the file
}
You can also do fstat on the descriptor:
struct stat statbuf;
fstat(fd,&statbuf);
if (statbuf.st_nlink > 0) {
//File still exists
}
But it will slow your software down a lot, and also some program could link the file somewhere else and unlink the original name, so that the file would still be existing but under a different name/location, and this method would not detect that.
A much better alternative would be to use inotify on GNU/Linux, or kqueue on bsd, but I've never used the 2nd one.
You can use these API to watch changes in directories and get notifications from the kernel and get an event when your file is being deleted by some other process, and do something about it.
Keep in mind that this events are not in real time, so you could still use the file for a couple of milliseconds before getting the event.

Resources