如何知道文件是否被复制?

时间:2011-05-14 17:17:54

标签: c file

我目前正在尝试检查目录中的文件副本是否已完成。 我想知道目标文件是否仍在复制。

所以我想获得在这个文件上打开的文件描述符的数量。 我使用C语言并没有真正找到解决该问题的方法。

7 个答案:

答案 0 :(得分:2)

如果你有控制权,我会建议在进行复制的程序中使用复制移动习语:

cp file1 otherdir/.file1.tmp
mv otherdir/.file1.tmp otherdir/file1

mv只是更改了一些文件系统条目,并且与副本相比具有原子性和非常快的速度。

答案 1 :(得分:0)

在linux中,尝试使用lsof命令,该命令列出系统中的所有打开文件。

编辑1:我想到的唯一C语言功能是fstat功能。您可以将其与结构的st_mtime(最后修改时间)字段一起使用 - 一旦该值停止更改(例如,10秒的时间段),则可以假定文件复制操作已停止。

编辑2:同样,在linux上,您可以遍历/proc/[pid]/fd以查看哪些文件是打开的。其中的文件是符号链接,但C的readlink()函数可以告诉你它的路径,所以你可以看到它是否仍然是打开的。使用getpid(),您将知道程序的进程ID(如果您正在从程序中执行文件复制),以了解在/ proc中查找的位置。

答案 2 :(得分:0)

如果您能够打开文件进行编写,操作系统很可能已完成复制并已释放其锁定。但是,不同的操作系统可能会有不同的行为。

另一种方法是打开源文件和目标文件以进行读取并比较它们的大小。如果它们的大小相同,则副本很可能已完成。您可以使用fseek()ftell()来确定C:

中文件的大小
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);

答案 3 :(得分:0)

(这个答案是一个很大的假设,它将在Linux上运行。)

lsof的C源代码是一个工具,它告诉哪些程序当前对特定文件有一个打开的文件描述符,是freely available。但是,为了警告你,我无法理解它。有关于读取内核内存的参考,所以对我来说它是伏都教或黑魔法。

也就是说,没有什么能阻止你通过自己的程序运行lsof。从您自己的程序运行第三方程序通常是您尝试避免的原因有多种,例如安全性(如果恶意用户更改lsof恶意程序,它将使用您的程序权限运行,可能灾难性后果)但是检查lsof源代码,我得出的结论是,没有公共API来确定哪个程序打开了哪个文件。如果您不害怕人们在/usr/sbin中更改计划,您可能会考虑这一点。

int isOpen(const char* file)
{
    char* command;
    // BE AWARE THAT THIS WILL NOT WORK IF THE FILE NAME CONTAINS A DOUBLE QUOTE
    // OR IF IT CAN SOMEHOW BE ALTERED THROUGH SHELL EXPANSION
    // you should either try to fix it yourself, or use a function of the `exec`
    // family that won't trigger shell expansion.
    // It would be an EXTREMELY BAD idea to call `lsof` without an absolute path
    // since it could result in another program being run. If this is not where
    // `lsof` resides on your system, change it to the appropriate absolute path.
    asprintf(&command, "/usr/sbin/lsof \"%s\"", file);
    int result = system(command);

    free(command);
    return result;
}

如果您还需要知道哪个程序打开了您的文件(大概是cp?),您可以使用popen以类似的方式读取lsof的输出。 popen描述符的行为类似于fopen描述符,所以您需要做的只是fread它们,看看您是否能找到您的程序名称。在我的机器上,lsof输出如下所示:

$ lsof document.pdf 
COMMAND PID  USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
SomeApp 873 felix  txt    REG   14,3   303260 5165763 document.pdf

答案 4 :(得分:0)

我认为您的基本错误是尝试将C程序与不用于同步的shell工具/外部程序同步。如果您对执行复制的程序/脚本有一定程度的控制权,则应对其进行修改以对目标文件执行某种类型的咨询锁定(最好基于fcntl)。然后你的其他程序可以简单地阻止获取锁。

如果您无法控制执行副本的程序,则唯一的解决方案取决于lsof或Linux inotify API等非便携式黑客攻击。

答案 5 :(得分:0)

正如poundifdef所提到的,fstat()函数可以为您提供当前的修改时间。但是fstat也为你提供了文件的大小。

回到C昏暗的黑暗时代,当我监控被各种程序复制的文件时,我无法控制我总是:

  1. 等到目标文件大小为> =源大小,然后
  2. 等待目标修改时间比当前时间至少早N秒。 N是一个数字5,如果经验表明必要,则设置得更大。是5秒似乎极端,但它是安全的。

如果您不知道目标文件是什么,那么您唯一真正的选择是#2,但是用户需要更大的N以允许更糟糕的网络和本地CPU延迟,并且具有健康的安全系数。

答案 6 :(得分:0)

使用boost libs将解决问题

boost::filesystem::fstream fileStream(filePath, std::ios_base::in | std::ios_base::binary);

if(fileStream.is_open())
    //not getting copied
else
    //Wait, the file is getting copied