#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(void)
{
FILE *fh = fopen ("file.txt", "w");
if (fh != NULL) {
int i = 0;
while(i < 5){
if (fprintf (fh, "%s", "hello") < 0)
{
fprintf (stderr, "err=%d: %s\n", errno, strerror (errno));
}
if(ferror(fh))
{
printf("wrong\n");
}
sleep(10);
}
}
return(0);
}
当我删除文件&#34; file.txt&#34;在程序运行期间,我希望fprintf返回小于0的值以打印错误消息。但是fprintf总是返回&#34;你好&#34;的大小。字符串是5。
注意:由于有10秒的睡眠调用,我在程序终止之前删除了该文件。
如果fprintf / fwrite写入不再存在的文件(由文件描述符指向),请说明如何生成错误消息。
答案 0 :(得分:5)
在类UNIX系统上,&#34;删除&#34;文件不会物理删除磁盘上的文件。它只是将链接数减少1.文件实际上不会被删除,直到它的最后一个链接消失。这就是调用rm
命令调用的系统调用unlink
的原因。 man 2 unlink
了解更多信息。
如果您创建指向文件的硬链接,则可以看到其中一个结果:
echo "hello" > file0
ln file0 file1
rm file0
rm file0
命令表示该名称不再显示该文件,但通过其他名称file1
仍然可以看到该文件。如果你然后rm file1
,实际文件将最终消失。
阻止文件被删除的另一种方法是让进程打开它。您的程序创建一个文件,并创建一个名为"file.txt"
的目录条目。在程序外键入rm file.txt
时,将删除目录条目,而不是文件。您的程序仍然可以写入该文件。它甚至可以回到文件的开头并再次阅读。
如果您的程序调用{{1}},或者它终止(隐式关闭所有打开的文件),那么对磁盘文件的最后一次引用将会消失,并且磁盘上的实际文件将被删除。
非UNIX系统(如Windows)可能表现不同。
答案 1 :(得分:0)
还有一种方法可以检查目录是否被删除而不从磁盘读取。
inotify系统调用执行监视目录的工作,如果删除了目录,则会向创建了inotify实例的主程序发送回调。
一个简单的例子 - 这是从inotify的手册页复制的。 link
+/* demo_inotify.c
+
+ Demonstrate the use of the inotify API.
+
+ Usage: demo_inotify pathname...
+
+ The program monitors each of the files specified on the command line for all
+ possible file events.
+
+ This program is Linux-specific. The inotify API is available in Linux 2.6.13
+ and later.
+*/
#include <sys/inotify.h>
#include <limits.h>
#include "tlpi_hdr.h"
static void /* Display information from inotify_event structure */
displayInotifyEvent(struct inotify_event *i)
{
printf(" wd =%2d; ", i->wd);
if (i->cookie > 0)
printf("cookie =%4d; ", i->cookie);
printf("mask = ");
if (i->mask & IN_ACCESS) printf("IN_ACCESS ");
if (i->mask & IN_ATTRIB) printf("IN_ATTRIB ");
if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");
if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE ");
if (i->mask & IN_CREATE) printf("IN_CREATE ");
if (i->mask & IN_DELETE) printf("IN_DELETE ");
if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF ");
if (i->mask & IN_IGNORED) printf("IN_IGNORED ");
if (i->mask & IN_ISDIR) printf("IN_ISDIR ");
if (i->mask & IN_MODIFY) printf("IN_MODIFY ");
if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF ");
if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM ");
if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO ");
if (i->mask & IN_OPEN) printf("IN_OPEN ");
if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW ");
if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT ");
printf("\n");
if (i->len > 0)
printf(" name = %s\n", i->name);
}
#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))
int
main(int argc, char *argv[])
{
int inotifyFd, wd, j;
char buf[BUF_LEN] __attribute__ ((aligned(8)));
ssize_t numRead;
char *p;
struct inotify_event *event;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s pathname...\n", argv[0]);
inotifyFd = inotify_init(); /* Create inotify instance */
if (inotifyFd == -1)
errExit("inotify_init");
+ /* For each command-line argument, add a watch for all events */
+
for (j = 1; j < argc; j++) {
wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);
if (wd == -1)
errExit("inotify_add_watch");
printf("Watching %s using wd %d\n", argv[j], wd);
}
for (;;) { /* Read events forever */
numRead = read(inotifyFd, buf, BUF_LEN);
if (numRead == 0)
fatal("read() from inotify fd returned 0!");
if (numRead == -1)
errExit("read");
printf("Read %ld bytes from inotify fd\n", (long) numRead);
/* Process all of the events in buffer returned by read() */
for (p = buf; p < buf + numRead; ) {
event = (struct inotify_event *) p;
displayInotifyEvent(event);
p += sizeof(struct inotify_event) + event->len;
}
}
exit(EXIT_SUCCESS);
}