我目前正在尝试检查目录中的文件副本是否已完成。 我想知道目标文件是否仍在复制。
所以我想获得在这个文件上打开的文件描述符的数量。 我使用C语言并没有真正找到解决该问题的方法。
答案 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昏暗的黑暗时代,当我监控被各种程序复制的文件时,我无法控制我总是:
如果您不知道目标文件是什么,那么您唯一真正的选择是#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