fread() error handling on Linux

This is a discussion on fread() error handling on Linux within the C Programming forums, part of the General Programming Boards category; I originally posted this thread in comp.unix.programmer. However, there hasn't been much traffic. I'm suspecting the regulars got some kind ...

  1. #1
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195

    fread() error handling on Linux

    I originally posted this thread in comp.unix.programmer. However, there hasn't been much traffic. I'm suspecting the regulars got some kind of life.

    Anyhow the question stems from the following lines of code:

    Code:
    #include <stdio.h>
    #include <utmp.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define LOG "/var/run/utmp" 
    
    static int process_type(struct utmp *user) {
    
        setutent();
        if(user->ut_type == UT_UNKNOWN)
            printf("%12s:\t Unknown Process Type\n",user->ut_user);
        if(user->ut_type == RUN_LVL)
            printf("%12s:\t Run Level \n",user->ut_user);
        if(user->ut_type == BOOT_TIME)
            printf("%12s:\t Boot Time  \n",user->ut_user);
        if(user->ut_type == NEW_TIME)
            printf("%12s:\t New Time \n",user->ut_user);
        if(user->ut_type == OLD_TIME)
        printf("%12s:\t Old Time \n",user->ut_user);
        if(user->ut_type == INIT_PROCESS)
            printf("%12s:\t Init \n",user->ut_user);
        if(user->ut_type == LOGIN_PROCESS)
            printf("%12s:\t Automatic Login \n",user->ut_user);
        if(user->ut_type == USER_PROCESS)
            printf("%12s:\t User account \n",user->ut_user);
        if(user->ut_type == DEAD_PROCESS)
            printf("%12s:\t Dead Process \n",user->ut_user);
        if(user->ut_type == ACCOUNTING)
            printf("%12s:\t Accounting \n",user->ut_user);
    
        endutent();
    
        return 0;
    }
    
    
    static int user_info(struct utmp *user){
    
        setutent();
    
        printf("%12s %8s %22s %14s",
           user->ut_user,
           user->ut_line,
           user->ut_host,
           ctime(&user->ut_time)
    		);
        endutent();
    
        return 0;
    }
    
    static int print_banner(void) {
    
        const char *name = "Name";
        const char *term = "Terminal";
        const char *host = "Hostname";
        const char *time = "Time";
    
        printf("%12s %10s %20s %3s\n",name,term,host,time);
    
        return 0;
    
    }
    
    static int print_process_type_banner(void) {
    
        int i;
    
        for(i=0;i<70;i++) {
            printf("-");
        }
        printf("\n");
    
        const char *name ="Name";
        const char *type="Process Description";
    
        printf("%12s \t %12s\n",name,type);
    
        return 0;
    
    }
    
    int main(int argc, char **argv) {
        struct utmp log_file;
    
        FILE *fp;
    
        print_banner();
    
        if ((fp = fopen(LOG,"r")) != 0){
        for(;fread(&log_file,sizeof(struct utmp),1,fp) !=0;) {
            user_info(&log_file);
    	}
            if(!feof(fp)){
                perror(argv[0]);
                exit(EXIT_FAILURE);
            }
    
            fclose(fp);
        }
    
        print_process_type_banner();
    
        if(fp == NULL) {
        perror(argv[0]);
        exit(EXIT_FAILURE);
        }
    
        if ((fp = fopen(LOG,"r")) != 0) {
            for(;fread(&log_file,sizeof(struct utmp),1,fp) !=0;) {
                process_type(&log_file);
            }
            if(!feof(fp)){
                perror(argv[0]);
                exit(EXIT_FAILURE);
    	    }
    
            fclose(fp);
        }
        
        if(fp == NULL) {
            perror(argv[0]);
            exit(EXIT_FAILURE);
        }
    
        return 0;
    }
    The problem line is:
    Code:
    for(;fread(&log_file,sizeof(struct utmp),1,fp) !=0;)

    I was told to use a while loop and check for error codes.

    If I checked for error code using a while loop, would the following construction work:

    Code:
    while(fread(&log_file,sizeof(struct utmp),1,fp) >=0){ 
            if( (ferror(fp)) || feof(fp) ) 
              exit(1); 
    
    }
    Last edited by cdalten; 03-12-2006 at 04:18 PM.

  2. #2
    Dump Truck Internet valis's Avatar
    Join Date
    Jul 2005
    Posts
    357
    From FreeBSD 6
    Code:
    > man fread
    ...
    RETURN VALUES
         The functions fread() and fwrite() advance the file position indicator
         for the stream by the number of bytes read or written.  They return the
         number of objects read or written.  If an error occurs, or the end-of-
         file is reached, the return value is a short object count (or zero).
    
         The function fread() does not distinguish between end-of-file and error,
         and callers must use feof(3) and ferror(3) to determine which occurred.
         The function fwrite() returns a value less than nmemb only if a write
         error has occurred.
    ...
    Try this out.
    Code:
    while (fread == bytes to be read);
    
    if (we aren't at EOF)
        do error stuff

  3. #3
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    That doesn't account for data errors. It just accounts for EOF. Don't I also need ferror() to account for errors?

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Why not just check whether fread was successful?
    Code:
    while(fread(&log_file,sizeof(struct utmp),1,fp) == 1) 
    {
       process_type(&log_file);
    }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Okay, bear with this. I don't do that much programming on Linux.

    If I use your example, the loop will terminate when it encounters an error or EOF? I'm suspecting I've misunderstood the concept of error handling on Linux.

  6. #6
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Okay, I thought about this. Modifying your example. Couldn't I go like:

    Code:
    while(fread(&log_file,sizeof(struct utmp),1,fp) == 1) 
    {
       process_type(&log_file);
    
       if( (ferror(fp)) || (feof(fp)) ) 
              exit(1); 
    }
    The loop would continue to read the file until it encountered either an error or EOF. At that point and time, the loop would terminate and hence the file would no longer be read.
    Last edited by cdalten; 03-12-2006 at 07:40 PM.

  7. #7
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    The internal if statement would never evaluate to true because fread would fail before that would happen, breaking the loop.

  8. #8
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Okay, I'm drawing a blank. The only other thing I can think of based on what you've said is to do something like:

    Code:
    while(fread(&log_file,sizeof(struct utmp),1,fp) != ( ferror(fp) || feof(fp) ) )
    {
       process_type(&log_file);
    }

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    I'm on Winders, so I have to strip some things away; and please forgive my conventions while playing along. But...
    Code:
       struct utmp log;
       FILE *file = fopen(LOG, "r");
       if ( file != NULL )
       {
          while ( fread(&log, sizeof log, 1, file) == 1 )
          {
             process_type(&log);
          }
          if ( ferror(file) ) /* exited loop due to an input error */
          {
             perror(LOG);
             return EXIT_FAILURE;
          }
          /* okay -- exited due to end of file */
    
          /* do stuff */
    
          fclose(file);
       }
       else
       {
          perror(LOG);
       }
    Is hitting EOF a reason to bail? Or does that just mean you've got what you wanted? If EOF is terrible, then I'd say repeat -- or add to -- the after-loop check to bail. But one of the two is why you stopped the loop. This is why it doesn't make much sense to my: when are you ever successful?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  10. #10
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Okay, I was making unfounded assumptions at the time. I was assuming EOF was a good reason to bail. Maybe one day when I'm old and gray, I'll go to school for computer programming.

    Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Thinking of upgrading to linux...
    By Yarin in forum General Discussions
    Replies: 37
    Last Post: 07-24-2009, 12:40 PM
  2. Wireless Network Linux & C Testbed
    By james457 in forum Networking/Device Communication
    Replies: 3
    Last Post: 06-11-2009, 12:03 PM
  3. Dabbling with Linux.
    By Hunter2 in forum Tech Board
    Replies: 21
    Last Post: 04-21-2005, 05:17 PM
  4. installing linux for the first time
    By Micko in forum Tech Board
    Replies: 9
    Last Post: 12-06-2004, 05:15 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21