From: Lawrence D'O. <ld...@ge...> - 2008-09-27 23:54:02
|
The dvdauthor programs use a common routine called "varied_open" (in compat.c) to open all their files. All the calling sequences check for open failures, except one--in readxml.c. This means that the dvdauthor tools can segfault if an XML file does not exist, instead of reporting a proper error message. This patch moves the error checking into the varied_open routine itself, and takes it out from all the callers. It also simplifies the varied_open code a bit, and adds some partial checking for write failures to varied_close. diff -ur 0.6.14-orig/src/compat.c 0.6.14-check-opens/src/compat.c --- 0.6.14-orig/src/compat.c 2007-01-15 08:07:52.000000000 +1300 +++ 0.6.14-check-opens/src/compat.c 2008-09-27 17:24:33.000000000 +1200 @@ -4,6 +4,7 @@ #include <ctype.h> #include <fcntl.h> +#include <errno.h> #ifndef HAVE_STRSEP /* Match STRING against the filename pattern PATTERN, returning zero if @@ -28,47 +29,65 @@ } #endif /* HAVE_STRSEP */ -/* Mode is either O_RDONLY or O_WRONLY, nothing more */ -struct vfile varied_open(const char *fname,int mode) -{ +struct vfile varied_open + ( + const char * fname, + int mode, /* either O_RDONLY or O_WRONLY, nothing more */ + const char * what /* description of what I'm trying to open, for error message */ + ) + { struct vfile vf; - - if( !strcmp(fname,"-") ) { - vf.ftype=2; - if( mode==O_RDONLY ) - vf.h=stdin; - else - vf.h=stdout; - return vf; - } else if( fname[0]=='&' && isdigit(fname[1])) { - vf.ftype=0; - vf.h=fdopen(atoi(fname+1),(mode==O_RDONLY)?"rb":"wb"); - return vf; - } else if( mode==O_RDONLY ) { - int l=strlen(fname); - if( l>0 && fname[l-1]=='|' ) { - char *fcopy=strdup(fname); - fcopy[l-1]=0; - vf.ftype=1; - vf.h=popen(fcopy,"r"); - free(fcopy); - return vf; - } - } else if( fname[0]=='|' ) { - vf.ftype=1; - vf.h=popen(fname+1,"w"); - return vf; - } - vf.ftype=0; - vf.h=fopen(fname,(mode==O_RDONLY)?"rb":"wb"); + if (strcmp(fname, "-") == 0) + { + vf.ftype = VFTYPE_REDIR; + vf.h = mode == O_RDONLY ? stdin : stdout; + } + else if (fname[0] == '&' && isdigit(fname[1])) + { + vf.ftype = VFTYPE_FILE; + vf.h = fdopen(atoi(fname + 1), mode == O_RDONLY ? "rb" : "wb"); + } + else if (fname[0] == '|') + { + vf.ftype = VFTYPE_PIPE; + vf.h = popen(fname + 1, mode == O_RDONLY ? "r" : "w"); + } + else + { + vf.ftype = VFTYPE_FILE; + vf.h = fopen(fname, mode == O_RDONLY ? "rb" : "wb"); + } /*if*/ + if (vf.h == NULL) + { + fprintf(stderr, "ERR: %d opening %s \"%s\" -- %s\n", errno, what, fname, strerror(errno)); + exit(1); + } /*if*/ + vf.mode = mode; return vf; -} + } /*varied_open*/ void varied_close(struct vfile vf) -{ - switch( vf.ftype ) { - case 0: fclose(vf.h); break; - case 1: pclose(vf.h); break; - case 2: break; - } -} + { + if (vf.mode == O_WRONLY) + { + /* check for errors on final write before closing */ + if (fflush(vf.h) != 0) + { + fprintf(stderr, "ERR: %d on fflush -- %s\n", errno, strerror(errno)); + exit(1); + } /*if*/ + } /*if*/ + switch (vf.ftype) + { + case VFTYPE_FILE: + fclose(vf.h); + break; + case VFTYPE_PIPE: + pclose(vf.h); + break; + case VFTYPE_REDIR: + default: + /* nothing to do */ + break; + } /*switch*/ + } /*varied_close*/ diff -ur 0.6.14-orig/src/compat.h 0.6.14-check-opens/src/compat.h --- 0.6.14-orig/src/compat.h 2007-01-11 14:29:34.000000000 +1300 +++ 0.6.14-check-opens/src/compat.h 2008-09-27 17:13:34.000000000 +1200 @@ -107,9 +107,19 @@ #define FT_GLYPH_H <freetype/ftglyph.h> #endif -struct vfile { - FILE *h; - int ftype; -}; -extern struct vfile varied_open(const char *fname,int mode); -extern void varied_close(struct vfile vf); +/* values for vfile.ftype */ +#define VFTYPE_FILE 0 +#define VFTYPE_PIPE 1 +#define VFTYPE_REDIR 2 +struct vfile + { + FILE * h; + int ftype, mode; + } /*vfile*/; +struct vfile varied_open + ( + const char * fname, + int mode, /* either O_RDONLY or O_WRONLY, nothing more */ + const char * what /* description of what I'm trying to open, for error message */ + ); +void varied_close(struct vfile vf); diff -ur 0.6.14-orig/src/dvdcli.c 0.6.14-check-opens/src/dvdcli.c --- 0.6.14-orig/src/dvdcli.c 2007-01-11 14:38:08.000000000 +1300 +++ 0.6.14-check-opens/src/dvdcli.c 2008-09-27 17:16:51.000000000 +1200 @@ -175,12 +175,8 @@ int i,rgbf; struct vfile h; - h=varied_open(fname,O_RDONLY); + h=varied_open(fname, O_RDONLY, "palette file"); - if( !h.h ) { - fprintf(stderr,"ERR: Cannot open palette file '%s'\n",fname); - exit(1); - } /* write out colors, the hex is the 0yuv combined in one integer 00yyuuvv */ i=strlen(fname); rgbf=( i>=4 && !strcasecmp(fname+i-4,".rgb") ); diff -ur 0.6.14-orig/src/dvdvob.c 0.6.14-check-opens/src/dvdvob.c --- 0.6.14-orig/src/dvdvob.c 2007-01-13 12:52:20.000000000 +1300 +++ 0.6.14-check-opens/src/dvdvob.c 2008-09-27 17:21:50.000000000 +1200 @@ -851,11 +851,7 @@ vsi.firstgop=1; fprintf(stderr,"\nSTAT: Processing %s...\n",s->fname); - vf=varied_open(s->fname,O_RDONLY); - if( !vf.h ) { - fprintf(stderr,"ERR: Error opening %s: %s\n",s->fname,strerror(errno)); - exit(1); - } + vf=varied_open(s->fname, O_RDONLY, "input video file"); memset(mp2hdr,0,8*sizeof(struct mp2info)); while(1) { if( fsect == 524272 ) { diff -ur 0.6.14-orig/src/readxml.c 0.6.14-check-opens/src/readxml.c --- 0.6.14-orig/src/readxml.c 2007-01-11 14:43:37.000000000 +1300 +++ 0.6.14-check-opens/src/readxml.c 2008-09-27 17:19:53.000000000 +1200 @@ -56,7 +56,7 @@ xmlTextReaderPtr f; struct vfile fd; - fd=varied_open(xmlfile,O_RDONLY); + fd=varied_open(xmlfile, O_RDONLY, "XML file"); f=xmlReaderForIO(xml_varied_read,xml_varied_close,&fd,xmlfile,NULL,0); if(!f) { fprintf(stderr,"ERR: Unable to open XML file %s\n",xmlfile); diff -ur 0.6.14-orig/src/spuunmux.c 0.6.14-check-opens/src/spuunmux.c --- 0.6.14-orig/src/spuunmux.c 2007-01-27 15:00:15.000000000 +1300 +++ 0.6.14-check-opens/src/spuunmux.c 2008-09-27 17:19:18.000000000 +1200 @@ -828,12 +828,7 @@ add_offset = 450; // for rounding purposes while (inc < Inc) { - fd = varied_open(iname[inc], O_RDONLY); - if (fd.h == 0) { - fprintf(stderr, "error opening file %s\n", iname[inc]); - - exit(-1); - } + fd = varied_open(iname[inc], O_RDONLY, "input file"); if (debug > 0) fprintf(stderr, "file: %s\n", iname[inc]); |