C system calls, delete the file - c

Right now, when I use write system call over and over again, it just appends to a file lets call file.txt if I were to call sys call write in C, on file.txt, it would just constantly. There is a circumstance where given that same file, I want to erase everything from it, and add just one line. How would I go by doing this? I don't want to create a new file, I want to working in that same file.
Thanks!

Just call truncate or ftruncate to cut the file to zero bytes. Then write the line you want. You don't need to close or re-open the file, you can use your existing handle.

The behaviour depends on what mode the file was opened: sounds like you're currently open in append mode; you need to open as a regular write in order to get the behaviour you desire.

Pass O_TRUNC to open() or pass "w", "wb", "w+", "wb+" or "w+b" to fopen().

When you call fopen(), you need to pass it the appropriate mode: read, write, append, etc. Here's a good review of fopen().

Related

Reading from a file opened using append mode

It might be a very dumb question but I am modifying someone else's code and it seems I need to read from a file that was opened in append mode. I tried to fseek to the beginning of the file but nothing is being read.
I know I can change the mode to rw but I wanted to know why fseek is not working. In the man page it does say write ignores fseek but nothing about read though.
There is just one pointer which initially is at the start of the file but when a write operation is attempted it is moved to the end of the file. You can reposition it using fseek or rewind anywhere in the file for reading, but writing operations will move it back to the end of file.
When you open in append mode, the file pointer is returned to the end of file before every write. You can reposition the pointer with fseek for reading, but as soon as you call a function that writes to the file, the pointer goes back to the end of file.
The answer at Does fseek() move the file pointer to the beginning of the file if it was opened in "a+b" mode? references the appropriate section of the C standard.
Use the "w+" mode if you would like to write to arbitrary places in file. An existing file will be overwritten.
If you would like to append to an existing file initially, but then fseek to arbitrary place, use "r+" followed by
fseek(f, 0, SEEK_END)
Hope it helps..

Untarring file fails when fd is not previously closed

Consider the following scenario: I am opening a tar file (say abc.tar.gz), writing the data, and before closing the file descriptor, I am trying to extract the same file.
I am unable to do so. But if I extract the file after having closing the fd, it works fine.
I wonder what could be the reason.
All files has a position where data is read or written. After writing to the file, the position is at the end. Trying to read will attempt to read from that position. You have to change the position to the beginning of the file with a function like lseek.
Also, you did open the file in both read and write mode?
Edit
After reading your comments, I see you do not actually read the file from inside your program, but from an external program. Then it might be as simple as you not flushing the file to disk, which happens automatically when closing a file. You might want to check the fsync function for that, or possible the sync function.

How to remove a file in C program?

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.

Overwriting an Open File in Windows

In what situations does Windows allow you to overwrite an open file? Is that ever allowed? This includes renaming a different file to the same name as an open file.
If you look at the documentation for CreateFile(), there is this dwShareMode parameter. This can determine what another process can do with that file while it's open.
Specifying FILE_SHARE_READ lets another process open the file for reading. There's FILE_SHARE_WRITE, which means that another process can write to it. There's also FILE_SHARE_DELETE, which allows delete and (IIRC) also rename.
If someone opened the file without FILE_SHARE_WRITE and you open the file for write access, you'll get ERROR_SHARING_VIOLATION. Otherwise you should be able to write to it.
Unfortunately if one process comes along and doesn't set sharing flags to allow something you need, you're pretty much out of luck. Although you might be able to use MoveFileEx() with the option MOVEFILE_DELAY_UNTIL_REBOOT. But I'm not sure if that works; I don't know much about that call except that it exists. :-)

How do you get the filename of a tempfile to use in Linux?

Let's say I'm creating a program in C that needs to use a tempfile. Creating an ad hoc tempfile in /tmp is probably not a good idea. Is there a function or OS call to supply me with a tempfile name so that I can begin to write and read from it?
You can use the mkstemp(3) function for this purpose. Another alternative is the tmpfile(3) function.
Which one of them you choose depends on whether you want the file to be opened as a C library file stream (which tmpfile does), or a direct file descriptor (mkstemp). The tmpfile function also deletes the file automatically when you program finishes.
The advantage of using these functions is that they avoid race conditions between determining the unique filename and creating the file -- so that two programs won't try to create the same file at the same time, for example.
See the man pages for both functions for more details.
The question is how to generate a temporary file name. Neither mkstemp nor tmpfile provide the caller with a name, they return a file descriptor or file handle, respectively.
#garethm:
I believe that the function you're looking for is called tmpnam.
You should definitely not use tmpnam. It suffers from the race condition problem I mentioned in my answer: Between determining the name and opening it, another program may create the file or a symlink to it, which is a huge security hole.
The tmpnam man page specifically says not to use it, but to use mkstemp or tmpfile instead.
Absolutely: man mkstemp.
The man page has example usage.
Not sure about anything in a C lib, but you can do this at the shell with mktemp.
You should use the mkstemp() as this is the recommended function, but it returns a file descriptor, so once you have the descriptor get it's name:
int fd;
fd = mkstemp("hdrXXXXXX);
/* Read out the link to our file descriptor. */
sprintf(path, "/proc/self/fd/%d", fd);
memset(result, 0, sizeof(result));
readlink(path, result, sizeof(result)-1);
/* Print the result. */
printf("%s\n", result);
usually there's no need to actually make a named file; instead use the file descriptor path,
FILE *tmp=tmpfile();
char path[PATH_MAX+1]={0};
sprintf(path, "/dev/fd/%d", fileno(tmp));
printf("%s\n", path);

Resources