How to remove a file in C program? - c

How do I close a file and remove it?
I have the following code:
FILE *filePtr = fopen("fileName", "w");
...
Now I want to close filePtr and remove the file "fileName".
Should I:
fclose(filePtr);
remove("fileName");
Or:
remove("fileName");
fclose(filePtr);
Does it matter which I do first?
Thanks!!

That is OS-dependent. On *nix, deleting an open file leaves it open and the data on disk, but removes the filename from the filesystem, and actually deletes the file on close; some other operating systems may not let you delete an open file at all. Therefore the former is recommended for maximum portability.

It makes more sense to fclose and then unlink.

As man unlink(2) says (for Unix systems) :
The unlink() function removes the link
named by path from its directory and
decrements the link count of the file
which was referenced by the link. If
that decrement reduces the link count
of the file to zero, and no process
has the file open, then all resources
associated with the file are
reclaimed. If one or more process
have the file open when the last link
is removed, the link is removed, but
the removal of the file is delayed
until all references to it have been
closed.
So the order doesn't matter at all.

You do not need to fopen a file to remove it. But, in linux, if you remove an fopened file, it will be deleted only after closing it. You can still read/write to it.

Related

Can an already opened FILE handle reflect changes to the underlying file without re-opening it?

Assuming a plain text file, foo.txt, and two processes:
Process A, a shell script, overwrites the file in regular intervals
$ echo "example" > foo.txt
Process B, a C program, reads from the file in regular intervals
fopen("foo.txt", "r"); getline(buf, len, fp); fclose(fp);
In the C program, keeping the FILE* fp open after the initial fopen(), doing a rewind() and reading again does not seem to reflect the changes that have happened to the file in the meantime. Is the only way to see the updated contents by doing an fclose() and fopen() cycle, or is there a way to re-use the already opened FILE handle, yet reading the most recently written data?
For context, I'm simply trying to find the most efficient way of doing this.
On Unix/Linux, when you create a file with a name which already existed, the old file is not deleted or altered in any way. A new file is created and the directory is updated to point at the new file instead of the old one.
The old file will continue to exist as long as some directory entry points at it (Unix file systems allow the same file to be pointed to by multiple directories) or some program has an open file handle to the file, which is more relevant to your question.
As long as you don't close fp, it continues to refer to the original file, even if that file is no longer referenced by the filesystem. When you close fp, the file will get garbage collected automatically, and the next time you open foo.txt, you'll get a file descriptor for whatever file happens to have that name at that point in time.
In short, with the shell script you indicate, your C program must close and reopen the file in order to see the new contents.
Theoretically, it would be possible for the shell script to overwrite the same file without deleting it, but (a) that's tricky to get right; (b) it's prone to race conditions; and (c) closing and reopening the file is not that time-consuming. But if you did that, you would see the changes. [Note 1]
In particular, it's common (and easy) to append to an existing file, and if you have a shell script which does that, you can keep the file descriptor open and see the changes. However, in that case you would normally have already read to the end of the file before the new data was appended, and the standard C library treats the feof() indicator as sticky; once it gets set, you will continue to get an EOF indication from new reads. If you suspect that some process will be writing more data to the file, you should reset the EOF indication with fseek(fp, 0, SEEK_CUR); before retrying the read.
Notes
As #amadan points out in a comment, there are race conditions with echo text > foo.txt as well, although the window is a bit shorter. But you can definitely avoid race conditions by using the idiom echo text > temporary_file; mv -f temporary_file foo.txt, because the rename operation is atomic. Of course, that would definitely require you to close and reopen the file. But it's a good idea, particularly if the contents being written are long or critical, or if new files are created frequently.

A file opened for read and write can be unlinked

In my program (on Mac OS X), I opened the file using following code.
int fd;
fd = open(filename, O_RDWR);
Program to delete the file is as follows:
unlink(filename);
In my case, I have same file which is opened and deleted. I observed the following:
After opening the file, I can delete it using this program and even by using rm command.
After deleting the file, read and write operations are working on the file without any problem.
I would like to know the reason behind this. How to prevent rm command or unlink(2) system call from deleting the file which is being opened?
You can't stop unlink(2) from unlinking a file which it has permission to unlink (i.e. it has write access to the directory).
unlink is not called unlink because nobody could think of a better name. It's called that because that is what it does; it unlinks the file from the directory. (A directory is just a collection of links; i.e. it associates names with the location of the corresponding data.) It does not delete the file; the file is garbage collected by the filesystem when there are no longer any links to it.
Open file descriptors are not the only way to keep links to files. Another, quite common, way is to use the link(1) command without the -s option. This creates "hard" links. If a file has several hard links, then removing one of the links (with unlink(2)) does just that -- it removes one of the links.
The rm command has a possibly more confusing name, but it, too, only removes the name, not the file. The file exists as long as someone has a link to it, including a running process.
First, rm command is calling unlink(2)
Then, unlinking an opened file is a normal thing to do on Linux or others Unixes (e.g. MacOSX). It is the canonical way to get temporary files (like tmpfile(3) probably does).
You should understand what inodes are, and realize that a file is not its name or file path, but essentially an inode. A file can have zero, one, or several file paths or names (one can add more with the link(2) syscall, provided all the names sit in the same filesystem). Directory entries associate names to inodes.
So there is no (POSIX-ly portable) way to prohibit I/O on open-ed files without any names.
For some opened file, the kernel has reference counters to its inode, and keep that inode till all processes having open(2)-ed it did close(2) it or have terminated.
See also inode(7) and credentials(7).
It's a normal Situation in UNIX SYSTEM. when you rm or unlink an opened file. UNIX system just mark a flag , and won't really delete the file desception. until the file is closed. and it will be really deleted in the file system.
It's protection to help the daemon work fine.
A link is a name associated to some file (a file is basically unamed). Note that a file could have different names (try ln).
unlink() removes one of this association to a file. If you remove the last link to a file, this just makes you unable to access the file by a name. But, this doesn't mean that the file is unusable, as a file could have been opened and his currently read/written by some application.
A file is removed if and only if :
- there is no link on it
- it is not currently opened by any application

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.

C Programming fopen() while opening a file

I've been wondering about this one. Most books I've read shows that when you open a file and you found that the file is not existing, you should put an error that there's no such file then exit the system...
FILE *stream = NULL;
stream = fopen("student.txt", "rt");
if (stream==NULL) {
printf(“Cannot open input file\n”);
exit(1);
else {printf("\nReading the student list directory. Wait a moment please...");
But I thought that instead of doing that.. why not automatically create a new one when you found that the file you are opening is not existing. Even if you will not be writing on the file upon using the program (but will use it next time). I'm not sure if this is efficient or not. I'm just new here and have no programming experience whatsoever so I'm asking your opinion what are the advantages and disadvantages of creating a file upon trying to open it instead of exiting the system as usually being exampled on the books.
FILE *stream = NULL;
stream = fopen("student.txt", "rt");
if (stream == NULL) stream = fopen("student.txt", "wt");
else {
printf("\nReading the student list directory. Wait a moment please...");
Your opinion will be highly appreciated. Thank you.
Because from your example, it seems like it's an input file, if it doesn't exist, no point creating it.
For example if the program is supposed to open a file, then count how many vowels in it, then I don't see much sense of creating the file if it doesn't exist.
my $0.02 worth.
Argument mode:
``r'' Open text file for reading.
``r+'' Open for reading and writing.
``w'' Truncate file to zero length or create text file for writing.
``w+'' Open for reading and writing. The file is created if it does not
exist, otherwise it is truncated.
``a'' Open for writing. The file is created if it does not exist.
``a+'' Open for reading and writing. The file is created if it does not
exist.
Your question is a simple case. Read above description, when you call fopen(), you should decide which mode shall be used. Please consider why a file is not created for "r" and "r+", and why a file is truncated for "w" and "w+", etc. All of these are reasonable designs.
If your program expects a file to exist and it doesn't, then creating one yourself doesn't make much sense, since it's going to be empty.
If OTOH, your program is OK with a file not existing and knows how to populate one from scratch, then it's perfectly fine to do so.
Either is fine as long as it makes sense for your program. Don't worry about efficiency here -- it's negligible. Worry about correctness first.
You may not have permission to create/write to a file in the directory that the user chooses. You will have to handle that error condition.

Detecting file deletion after fopen

im working in a code that detects changes in a file (a log file) then its process the changes with the help of fseek and ftell. but if the file get deleted and changed (with logrotate) the program stops but not dies, because it not detect more changes (even if the file is recreated). fseek dont show errors and eiter ftell.
how i can detect that file deletion? maybe a way to reopen the file with other FILE *var and comparing file descriptor. but how i can do that. ?
When a file gets deleted, it is not necessarily erased from your disk. In your case the program still has a handle to the old file. The old file handle will not get you any information about its deletion or replacement with another file.
An easy way to detect file deletion and recreation is using stat(2) and fstat(2). They give you a struct stat which contains the inode for the file. When a file is recreated (and still open) the files (old open and recreated) are different and thus the inodes are different. The inode field is st_ino. Yes, you need to poll this unless you wish to use Linux-features like inotify.
You can periodically close the file and open it again, that way you will open the newly created one. Files actually get deleted when there is no handle to the file (open file descriptor is a handle), you are still holding the old file.
On windows, you could set callbacks on the modifications of the FS. Here are details: http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx

Resources