Index: cmp.c =================================================================== --- cmp.c (revision 257216) +++ cmp.c (working copy) @@ -101,7 +101,10 @@ #include #include #include +#include +#include + /* Exit status codes */ #define FILES_ARE_IDENTICAL_RC 0 #define FILES_DIFFER_RC 1 @@ -117,6 +120,7 @@ #define S_DASH_L_FORMAT "%d %o %o\n" #endif #define S_EOF_FORMAT "cmp: EOF on %s\n" +#define S_ERR_FORMAT "cmp: error %d reading %s\n" /* Language independent messages */ #define TXT(s) s @@ -154,10 +158,100 @@ -s = 'silent' operation - don't print anything out, just give ret code --------------------------------------------------------------------------*/ + +#define FSTREAM_FLAG_INVALID 0x1 +#define FSTREAM_FLAG_EOF 0x2 +#define FSTREAM_FLAG_ERR 0x4 +#define FSTREAM_FLAG_OPENFD 0x8 + +struct filestream { + int fd; + off_t cur_off; + int last_err; + unsigned stream_flags; +}; +typedef struct filestream* filestar_t; + + +filestar_t fstream_open(char *fname, int omode) { + struct filestream* p; + + if((p=malloc(sizeof(*p))) == NULL) { + return p; + } + p->fd = open(fname, omode); + + if(p->fd < 0) { + free(p); + return NULL; + } + + p->cur_off=0; + p->stream_flags=0; + p->last_err = EOK; + return p; +} + +filestar_t fstream_fdopen(int fd) { + struct filestream *p; + + if(fd < 0 ) return NULL; + if((p=malloc(sizeof(*p))) == NULL) { + return p; + } + p->fd=fd; + p->cur_off=0; + p->stream_flags=FSTREAM_FLAG_OPENFD; + p->last_err = EOK; + return p; +} + +int fstream_close(filestar_t fs) { + int rv = -1; + if(fs) { + if((fs->stream_flags & FSTREAM_FLAG_OPENFD) == 0) close(fs->fd); + free(fs); + rv=0; + } + return rv; +} + +size_t fstream_read(filestar_t fs, void* buf, size_t len) { + int nread; + size_t nleft=len; + unsigned char* curptr=buf; + + do { + nread=read(fs->fd, curptr, nleft); + if(nread > 0) { + nleft-=nread; + curptr+=nread; + fs->cur_off+=nread; + fs->stream_flags &= ~(FSTREAM_FLAG_EOF|FSTREAM_FLAG_ERR); /* turn off conditions */ + } if(nread < 0) { + fs->stream_flags |= FSTREAM_FLAG_ERR; + fs->last_err = errno; + } else { + fs->stream_flags |= FSTREAM_FLAG_EOF; + } + } while(nleft && (nread > 0)); + return len-nleft; +} + +int fstream_eof(filestar_t fs) { + return fs->stream_flags & FSTREAM_FLAG_EOF; +} + +int fstream_err(filestar_t fs) { + return fs->stream_flags & FSTREAM_FLAG_ERR ? fs->last_err : EOK; +} + int main( int argc, char *argv[] ) { int opt; int i; + filestar_t fs1; + filestar_t fs2; nerrors = 0; @@ -191,9 +285,9 @@ } if ( strcmp( file1, "-" ) == 0 ) - fd1 = STDIN_FILENO; + fs1 = fstream_fdopen(STDIN_FILENO); else { - if (( fd1 = open( file1, O_RDONLY )) == -1) { + if (( fs1 = fstream_open( file1, O_RDONLY )) == NULL) { if (!silent) fprintf( stderr, TXT( T_CANT_OPEN_FILE ), file1 ); exit( IO_ERROR_RC ); @@ -201,17 +295,17 @@ } if ( strcmp( file2, "-" ) == 0 ) - fd2 = STDIN_FILENO; + fs2 = fstream_fdopen(STDIN_FILENO); else { - if (( fd2 = open( file2, O_RDONLY)) == -1) { + if (( fs2 = fstream_open( file2, O_RDONLY)) == NULL) { if (!silent) fprintf( stderr, TXT( T_CANT_OPEN_FILE ), file2 ); exit( IO_ERROR_RC ); } } if ( strcmp( file1, file2 ) == 0 ) { - close(fd1); - close(fd2); + fstream_close(fs1); + fstream_close(fs2); exit( FILES_ARE_IDENTICAL_RC ); } /* if */ @@ -220,15 +314,26 @@ line_count = 1; for( ;; ) { - fd1_nread = read(fd1, file1buf, sizeof(file1buf)); - fd2_nread = read(fd2, file2buf, sizeof(file2buf)); + fd1_nread = fstream_read(fs1, file1buf, sizeof(file1buf)); + fd2_nread = fstream_read(fs2, file2buf, sizeof(file2buf)); - if((fd1_nread <= 0) || (fd2_nread <= 0)) { - if((fd1_nread == 0) != (fd2_nread == 0)) { + if(fd1_nread != fd2_nread) { + if(fstream_eof(fs1) || fstream_eof(fs2)) { if ( silent == FALSE ) - fprintf( stderr, S_EOF_FORMAT, fd1_nread==0 ? file1 : file2 ); + fprintf( stderr, S_EOF_FORMAT, fd1_nread < fd2_nread ? file1 : file2 ); + + fstream_close(fs1); + fstream_close(fs2); exit( differ ? IO_ERROR_RC : FILES_DIFFER_RC ); - } /* if */ + } else if(fstream_err(fs1) || fstream_err(fs2)) { + if ( silent == FALSE ) { + if(fstream_err(fs1)) fprintf(stderr, S_ERR_FORMAT, fstream_err(fs1), file1); + if(fstream_err(fs2)) fprintf(stderr, S_ERR_FORMAT, fstream_err(fs2), file1); + } + fstream_close(fs1); + fstream_close(fs2); + exit( differ ? IO_ERROR_RC : FILES_DIFFER_RC); + } } if(memcmp(file1buf,file2buf,min(fd1_nread,fd2_nread))) { @@ -244,6 +349,9 @@ } else { if ( silent == FALSE ) fprintf( stdout, S_NORMAL_FORMAT, file1, file2, char_count, line_count ); + + fstream_close(fs1); + fstream_close(fs2); exit( FILES_DIFFER_RC ); } } @@ -258,6 +366,10 @@ line_count++; } } /* for */ + + + fstream_close(fs2); + fstream_close(fs1); return ( differ ? FILES_DIFFER_RC : FILES_ARE_IDENTICAL_RC ); } /* main() */ Index: common.mk =================================================================== --- common.mk (revision 257216) +++ common.mk (working copy) @@ -9,6 +9,7 @@ PINFO DESCRIPTION=compare two files endef +CCFLAGS_darwin=-DEOK=0 USEFILE=$(PROJECT_ROOT)/$(NAME).c include $(MKFILES_ROOT)/qtargets.mk