Search code examples
cprintffwrite

Return value of fprintf


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

When I a delete the file "file.txt" during the time the program is running, I expect the fprintf to return a value lesser than 0 to print the error message. But all the times fprintf returns the the size of "hello" string which is 5.

Note: Since there is a sleep call for 10 seconds, I deleted the file before the program terminates.

Clarify me on how to produce the error message if fprintf/fwrite writes to a file which is no longer exists (pointed by the file-descriptor).


Solution

  • There is an another way to check if the directory is deleted or not without reading from the disk.

    inotify system call does the job of monitoring a directory and if the directory is deleted, a callback is sent to the main program that created the instance of inotify.

    A simple example - This copied from the man page of 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);
     }