TransWikia.com

How to delete a file in C using a file-descriptor?

Stack Overflow Asked on January 14, 2021

In my code, I create a file with a random name using mkstemp() function (Im on Linux). What this function returns is an int being a file descriptor.

int fd;
char temp[] = "tempXXXXXX";

fd = mkstemp(temp);

Later I can access the file using fdopen() through that int file descriptor.

FILE *file_ptr = NULL;

file_ptr = fdopen(fd);

But at the end of my program, I would like to see if the file still exists with the random name it was given when I created it (the program should change that file name if successful). I can set a flag if the rename() function run on that file is successful, but I still don’t know how to delete it when I only have its file descriptor.

if rename files => remove the temp file

How can I do that? Or is there a way to get the files name if I have its file descriptor?

3 Answers

Neither C nor POSIX (since you are using POSIX library functions) defines a way to delete a file via an open file descriptor. And that makes sense, because the kind of deletion you're talking about is actually to remove a directory entry, not the file itself. The same file can be hard linked into the directory tree in multiple places, with multiple names. The OS takes care of removing its data from storage, or at least marking it as available for reuse, after the last hard link to it is removed from the directory tree and no process any longer has it open.

A file descriptor is associated directly with a file, not with any particular path, notwithstanding the fact that under many circumstances, you obtain one via a path. This has several consequences, among them that once a process opens a file, that file cannot be pulled out from under it by manipulating the directory tree. And that is the basis for one of the standard approaches to your problem: unlink (delete) it immediately after opening it, before losing its name. Example:

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

int make_temp_file() {
    char filename[] = "my_temp_file_XXXXXX";
    int fd;

    fd = mkstemp(filename);
    if (fd == -1) {
        // handle failure to open ...
    } else {
        // file successfully opened, now unlink it
        int result = unlink(filename);
        // ... check for and handle error conditions ...
    }

    return fd;
}

Not only does that (nearly) ensure that the temp file does not outlive the need for it, but it also prevents the contents from being accessible to users and processes to which the owning process does not explicitly grant access.

Correct answer by John Bollinger on January 14, 2021

Even though this doesn't exactly answer the question you're asking about mkstemp, consider creating a temporary file that will automatically be deleted, unless you rename it.

Instead of mkstemp you could call open combined with the creation flag O_TMPFILE to create a temporary, unnamed file that is automatically deleted when file is closed.

See open(2):

O_TMPFILE (since Linux 3.11)
    Create an unnamed temporary regular file.  The pathname argu‐
    ment specifies a directory; an unnamed inode will be created
    in that directory's filesystem.  Anything written to the
    resulting file will be lost when the last file descriptor is
    closed, unless the file is given a name.

Instead of a filename, you call open with the path where you prefer to place the temporary file, like:

temp_fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);

If you like to give the temporary file a permanent location/name, you can call linkat on it later:

linkat(temp_fd, NULL, AT_FDCWD, "/path/for/file", AT_EMPTY_PATH);

Note: Filesystem support is required for O_TMPFILE, but mainstream Linux filesystems do support it.

Answered by Elijan9 on January 14, 2021

readlink provide you the name of your file depending of the file descriptor if you use the path /proc/self/fd/ adding you fd.

Then use remove for deleting the file passing the name readlink gave you

ssize_t readlink(const char *path, char *buf, size_t bufsiz); (also load ernno)

int remove(const char *filename); (returns zero is successful, otherwise nonzero)

I hope something like that could helped you ?


⚠ Don't copy/past this you must edit "filename"; _BUFFER, _BUFSIZE ⚠

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

int delete_file(int fd) {
   char *str_fd = itoa(fd, str_fd, 10);
   char *path = strcat("/proc/self/fd/", str_fd);
   
   if (read_link(path, buffer, bufsize) == -1)
        return -1;
        
   int del = remove(filename);
   if (!del)
      printf("The file is Deleted successfully");
   else
      printf("The file is not Deleted");
   return 0;
}

(feel free to edit this, i didn't test the code and i let you handel the buffer and buffer size)

Answered by Halfa on January 14, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP