如何使用文件描述符在C中删除文件?

问题描述

在我的代码中,我使用mkstemp()函数(在Linux上为Im)创建了一个具有随机名称文件。此函数返回的是intfile descriptor

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

fd = mkstemp(temp);

稍后,我可以通过fdopen()文件描述符使用int访问文件

FILE *file_ptr = NULL;

file_ptr = fdopen(fd);

但是在程序结束时,我想查看文件是否仍然存在,并具有创建时给定的随机名称(如果成功,程序应更改该文件名)。如果在该文件上运行的rename()函数成功,我可以设置一个标志,但是当我只有文件描述符时,我仍然不知道如何删除它。

if rename files => remove the temp file

我该怎么做?或者,如果我有file descriptor,是否可以获取文件名?

解决方法

即使这不能完全回答您所问的关于mkstemp的问题,也可以考虑创建一个将自动删除的临时文件,除非您重命名它。

您可以调用mkstemp而不是open并与创建标记O_TMPFILE一起创建一个临时的未命名文件,该文件在关闭文件后会自动删除。

请参见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.

您可以使用您喜欢放置临时文件的路径而不是文件名来调用open,例如:

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

如果您想给临时文件一个永久的位置/名称,可以稍后再调用linkat

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

注意O_TMPFILE需要文件系统支持,但是主流Linux文件系统都支持。

,

C或POSIX(因为您正在使用POSIX库函数)都没有定义通过打开的文件描述符删除文件的方法。这是有道理的,因为您所谈论的删除实际上是删除目录条目,而不是文件本身。可以使用多个名称在多个位置将同一文件硬链接到目录树中。在从目录树中删除最后一个硬链接并且不再打开任何进程之后,操作系统会负责从存储中删除其数据,或者至少将其标记为可重用。

文件描述符直接与文件关联,而不与任何特定路径关联,尽管在许多情况下,您都是通过路径获得的。这会带来多种后果,其中包括一旦进程打开文件,就无法通过操纵目录树将文件从文件中拉出。这就是解决问题的一种标准方法的基础:在打开它后立即取消链接(删除),然后再失去其名称。示例:

#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;
}

这样做(几乎)不仅可以确保临时文件不会超过对临时文件的需求,而且还可以防止内容和拥有进程未明确授予访问权限的进程访问用户和进程。

,

readlink根据文件描述符为您提供文件名,如果您使用路径/proc/self/fd/添加fd。

然后使用remove删除名称为readlink给您的文件

ssize_t readlink(const char *path,char *buf,size_t bufsiz);(还加载ernno

int remove(const char *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;
}

(随时进行编辑,我没有测试代码,让您处理缓冲区和缓冲区大小)