#include "common.h"
-#define dbassert(x) \
- ((x) ? (void)0 : \
- fatal("Error in database.\n" \
- " Requirement not met: %s:%d: %s", __FILE__,__LINE__, #x))
-
-void fgetsline(FILE *f, char *lbuf, size_t lbufsz) {
- errno=0;
- char *s= fgets(lbuf,lbufsz,f);
- sysassert(!ferror(f));
- dbassert(!feof(f));
- assert(s);
- int l= strlen(lbuf);
- dbassert(l>0); dbassert(lbuf[--l]='\n');
- lbuf[l]= 0;
-}
-
void *mmalloc(size_t sz) {
void *r;
if (!sz) return 0;
sysassert( r= realloc(p,sz) );
return r;
}
+
+
+FILE *dbfile;
+static const char *basepath; /* as passed in by caller */
+static pid_t dbzcat;
+
+int dbfile_gzopen(const char *basepath_spec) {
+ assert(!dbfile);
+
+ basepath= basepath_spec;
+
+ char *zpath= masprintf("%s.gz", basepath);
+ int e= gzopen(zpath, O_RDONLY, &dbfile, &dbzcat, 0);
+ free(zpath);
+ if (e) { errno=e; sysassert(errno==ENOENT); return 0; }
+
+ return 1;
+}
+
+int dbfile_open(const char *tpath) {
+ assert(!dbfile);
+
+ basepath= tpath;
+
+ dbzcat= -1;
+ dbfile= fopen(tpath,"r");
+ if (!dbfile) { sysassert(errno==ENOENT); return 0; }
+ return 1;
+}
+
+void dbfile_close(void) {
+ gzclose(&dbfile, &dbzcat, basepath);
+}
+
+#define dbassertgl(x) ((x) ? (void)0 : dbfile_assertfail(file,line,#x))
+
+void dbfile_getsline(char *lbuf, size_t lbufsz, const char *file, int line) {
+ errno=0;
+ char *s= fgets(lbuf,lbufsz,dbfile);
+ sysassert(!ferror(dbfile));
+ dbassertgl(!feof(dbfile));
+ assert(s);
+ int l= strlen(lbuf);
+ dbassertgl(l>0); dbassertgl(lbuf[--l]=='\n');
+ lbuf[l]= 0;
+}
+
+int dbfile_vscanf(const char *fmt, va_list al) {
+ int r= vfscanf(dbfile,fmt,al);
+ sysassert(!ferror(dbfile));
+ return r;
+}
+
+int dbfile_scanf(const char *fmt, ...) {
+ va_list al;
+ va_start(al,fmt);
+ int r= dbfile_vscanf(fmt,al);
+ va_end(al);
+ return r;
+}
+
+void dbfile_assertfail(const char *file, int line, const char *m) {
+ if (dbzcat)
+ fatal("Error in dictionary file %s.gz:\n"
+ " Requirement not met at %s:%d:\n"
+ " %s",
+ basepath, file,line, m);
+ else if (dbfile)
+ fatal("Error in dictionary file %s at byte %ld:\n"
+ " Requirement not met at %s:%d:\n"
+ " %s",
+ basepath,(long)ftell(dbfile), file,line, m);
+ else
+ fatal("Semantic error in dictionaries:\n"
+ " Requirement not met at %s:%d:\n"
+ " %s",
+ file,line, m);
+}
+
+int gzopen(const char *zpath, int oflags, FILE **f_r, pid_t *pid_r,
+ const char *gziplevel /* 0 for read; may be 0, or "-1" etc. */) {
+
+ int zfd= open(zpath, oflags, 0666);
+ if (!zfd) return errno;
+
+ int pipefds[2];
+ sysassert(! pipe(pipefds) );
+
+ int oi,io; const char *cmd; const char *stdiomode;
+ switch ((oflags & O_ACCMODE)) {
+ case O_RDONLY: oi=0; io=1; cmd="gunzip"; stdiomode="r"; break;
+ case O_WRONLY: oi=1; io=0; cmd="gzip"; stdiomode="w"; break;
+ default: abort();
+ }
+
+ sysassert( (*pid_r=fork()) != -1 );
+ if (!*pid_r) {
+ sysassert( dup2(zfd,oi)==oi );
+ sysassert( dup2(pipefds[io],io)==io );
+ sysassert(! close(zfd) );
+ sysassert(! close(pipefds[0]) );
+ sysassert(! close(pipefds[1]) );
+ execlp(cmd,cmd,gziplevel,(char*)0);
+ sysassert(!"execlp gzip/gunzip");
+ }
+ sysassert(! close(zfd) );
+ sysassert(! close(pipefds[io]) );
+ sysassert( *f_r= fdopen(pipefds[oi], stdiomode) );
+
+ return 0;
+}
+
+void gzclose(FILE **f, pid_t *p, const char *what) {
+ if (!*f) return;
+
+ sysassert(!ferror(*f));
+ sysassert(!fclose(*f));
+
+ if (*p != -1) {
+ char *process= masprintf("%s (de)compressor",what);
+ waitpid_check_exitstatus(*p,process,1);
+ free(process);
+ *p= -1;
+ }
+
+ *f= 0;
+}