From: jwalz Date: Sat, 5 Jan 2002 21:06:00 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: MOVE2GIT~3622 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e96d5aba248e15fc8bc2f973fc379d180b59e3fc;p=nethack *** empty log message *** --- diff --git a/util/dlb_main.c b/util/dlb_main.c new file mode 100644 index 000000000..d161fea70 --- /dev/null +++ b/util/dlb_main.c @@ -0,0 +1,543 @@ +/* SCCS Id: @(#)dlb_main.c 3.3 98/08/16 */ +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* data librarian; only useful if you are making the library version, DLBLIB */ + +#include "config.h" +#include "dlb.h" +#if !defined(O_WRONLY) && !defined(MAC) && !defined(AZTEC_C) +#include +#endif +#if defined(__DJGPP__) +#include +#endif + +static void FDECL(xexit, (int)); + +#ifdef DLB +#ifdef DLBLIB + +#define DLB_DIRECTORY "Directory" /* name of lib directory */ +#define LIBLISTFILE "dlb.lst" /* default list file */ + +/* library functions (from dlb.c) */ +extern boolean FDECL(open_library,(const char *,library *)); +extern void FDECL(close_library,(library *)); + +char *FDECL(eos, (char *)); /* also used by dlb.c */ +FILE *FDECL(fopen_datafile, (const char *,const char *)); + +#ifdef VMS +extern char *FDECL(vms_basename, (const char *)); +extern int FDECL(vms_open, (const char *,int,unsigned int)); +#endif + +static void FDECL(Write, (int,char *,long)); +static void NDECL(usage); +static void NDECL(verbose_help); +static void FDECL(write_dlb_directory, (int,int,libdir *,long,long,long)); + +static char default_progname[] = "dlb"; +static char *progname = default_progname; + +/* fixed library and list file names - can be overridden if necessary */ +static const char *library_file = DLBFILE; +static const char *list_file = LIBLISTFILE; + +#ifdef AMIGA +static char origdir[255]=""; +#endif + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#define MAX_DLB_FILES 200 /* max # of files we'll handle */ +#define DLB_VERS 1 /* version of dlb file we will write */ + +/* + * How the file is encoded within the library. Don't use a space + * because (at least) the SunOS 4.1.3 C library will eat the white + * space instead of preserving it like the man page says it should. + */ +#define ENC_NORMAL 'n' /* normal: not compressed in any way */ + + +/* + * If you know tar, you have a small clue how to use this (note: - does + * NOT mean stdin/stdout). + * + * dlb COMMANDoptions arg... files... + * commands: + * dlb x extract all files + * dlb c build the archive + * dlb t list the archive + * options: + * v verbose + * f file specify archive file (default DLBFILE) + * I file specify file for list of files (default LIBLISTFILE) + * C dir chdir to dir (used ONCE, not like tar's -C) + */ + +static void +usage() +{ + (void) printf("Usage: %s [ctxCIfv] arguments... [files...]\n", progname); + (void) printf(" default library is %s\n", library_file); + (void) printf(" default list file is %s\n", list_file); + xexit(EXIT_FAILURE); +} + +static void +verbose_help() +{ + static const char *long_help[] = { + "", + "dlb COMMANDoptions args... files...", + " commands:", + " dlb ? print this text", + " dlb h ditto", + " dlb x extract all files", + " dlb c create the archive", + " dlb t list table of contents", + " options:", + " v verbose operation", + " f file specify archive file name", + " I file specify file for list of file names", + " C dir change directory before processing any files", + "", + (char *)0 + }; + const char **str; + + for (str = long_help; *str; str++) + (void) printf("%s\n", *str); + usage(); +} + +static void +Write(out,buf,len) + int out; + char *buf; + long len; +{ +#if defined(MSDOS) && !defined(__DJGPP__) + unsigned short slen; + + if (len > 65534) { + printf("%d Length specified for write() too large for 16 bit env.", + len); + xexit(EXIT_FAILURE); + } + slen = (unsigned short)len; + if (write(out,buf,slen) != slen) { +#else + if (write(out,buf,len) != len) { +#endif + printf("Write Error in '%s'\n",library_file); + xexit(EXIT_FAILURE); + } +} + + +char * +eos(s) + char *s; +{ + while (*s) s++; + return s; +} + + +#ifdef VMS /* essential to have punctuation, to avoid logical names */ +static FILE * +vms_fopen(filename, mode) +const char *filename, *mode; +{ + char tmp[BUFSIZ]; + + if (!index(filename, '.') && !index(filename, ';')) + filename = strcat(strcpy(tmp, filename), ";0"); + return fopen(filename, mode, "mbc=16"); +} +#define fopen vms_fopen +#endif /* VMS */ + +/* open_library(dlb.c) needs this (which normally comes from src/files.c) */ +FILE * +fopen_datafile(filename, mode) +const char *filename, *mode; +{ + return fopen(filename, mode); +} + +#endif /* DLBLIB */ +#endif /* DLB */ + +int +main(argc, argv) + int argc; + char **argv; +{ +#ifdef DLB +#ifdef DLBLIB + int i, r; + int ap=2; /* argument pointer */ + int cp; /* command pointer */ + int iseen=0, fseen=0, verbose=0; /* flags */ + char action=' '; + library lib; + + if (argc > 0 && argv[0] && *argv[0]) progname = argv[0]; +#ifdef VMS + progname = vms_basename(progname); +#endif + + if (argc<2) { + usage(); + /* doesn't return */ + } + + for(cp=0;argv[1][cp];cp++){ + switch(argv[1][cp]){ + default: + usage(); /* doesn't return */ + case '-': /* silently ignore */ + break; + case '?': + case 'h': + verbose_help(); + break; + case 'I': + if (ap == argc) usage(); + list_file=argv[ap++]; + if(iseen) + printf("Warning: multiple I options. Previous ignored.\n"); + iseen=1; + break; + case 'f': + if (ap == argc) usage(); + library_file=argv[ap++]; + if(fseen) + printf("Warning: multiple f options. Previous ignored.\n"); + fseen=1; + break; + case 'C': + if (ap == argc) usage(); +#ifdef AMIGA + if(!getcwd(origdir,sizeof(origdir))){ + printf("Can't get current directory.\n"); + xexit(EXIT_FAILURE); + } +#endif + if(chdir(argv[ap++])){ + printf("Can't chdir to %s\n",argv[--ap]); + xexit(EXIT_FAILURE); + } + break; + case 'v': + verbose=1; + break; + case 't': + case 'c': + case 'x': + if(action != ' '){ + printf("Only one of t,x,c may be specified.\n"); + usage(); + } + action=argv[1][cp]; + break; + } + } + + if(argv[ap] && iseen){ + printf("Too many arguments.\n"); + xexit(EXIT_FAILURE); + } + + switch(action){ + default: + printf("Internal error - action.\n"); + xexit(EXIT_FAILURE); + break; + case 't': /* list archive */ + if (!open_library(library_file, &lib)) { + printf("Can't open dlb file\n"); + xexit(EXIT_FAILURE); + } + + for (i = 0; i < lib.nentries; i++) { + if (verbose) + printf("%-14s %6ld %6ld\n", + lib.dir[i].fname, lib.dir[i].foffset, lib.dir[i].fsize); + else + printf("%s\n", lib.dir[i].fname); + } + + if (verbose) + printf("Revision:%ld File count:%ld String size:%ld\n", + lib.rev, lib.nentries, lib.strsize); + + close_library(&lib); + xexit(EXIT_SUCCESS); + + case 'x': { /* extract archive contents */ + int f, n; + long remainder, total_read; + char buf[BUFSIZ]; + + if (!open_library(library_file, &lib)) { + printf("Can't open dlb file\n"); + xexit(EXIT_FAILURE); + } + + for (i = 0; i < lib.nentries; i++) { + if (argv[ap]) { + /* if files are listed, see if current is wanted */ + int c; + for (c = ap; c < argc; c++) + if (!FILENAME_CMP(lib.dir[i].fname, argv[c])) break; + if (c == argc) continue; /* skip */ + } else if (!FILENAME_CMP(lib.dir[i].fname, DLB_DIRECTORY)) { + /* + * Don't extract the directory unless the user + * specifically asks for it. + * + * Perhaps we should never extract the directory??? + */ + continue; + } + fseek(lib.fdata, lib.dir[i].foffset, SEEK_SET); + + f = open(lib.dir[i].fname, O_WRONLY|O_TRUNC|O_BINARY|O_CREAT, 0640); + if (f < 0) { + printf("Can't create '%s'\n", lib.dir[i].fname); + xexit(EXIT_FAILURE); + } + + /* read chunks from library and write them out */ + total_read = 0; + do { + remainder = lib.dir[i].fsize - total_read; + if (remainder > (long) sizeof(buf)) + r = (int) sizeof(buf); + else + r = remainder; + + n = fread(buf, 1, r, lib.fdata); + if (n != r) { + printf("Read Error in '%s'\n", lib.dir[i].fname); + xexit(EXIT_FAILURE); + } + if (write(f, buf, n) != n) { + printf("Write Error in '%s'\n", lib.dir[i].fname); + xexit(EXIT_FAILURE); + } + + total_read += n; + } while (total_read != lib.dir[i].fsize); + + (void) close(f); + + if (verbose) printf("x %s\n", lib.dir[i].fname); + } + + close_library(&lib); + xexit(EXIT_SUCCESS); + } + + case 'c': /* create archive */ + { + libdir ld[MAX_DLB_FILES]; + char buf[BUFSIZ]; + int fd, out, nfiles = 0; + long dir_size, slen, flen, fsiz; + boolean rewrite_directory = FALSE; + + /* + * Get names from either/both an argv list and a file + * list. This does not do any duplicate checking + */ + + /* get file name in argv list */ + if (argv[ap]) { + for ( ; ap < argc; ap++, nfiles++) { + if (nfiles >= MAX_DLB_FILES) { + printf("Too many dlb files! Stopping at %d.\n", + MAX_DLB_FILES); + break; + } + ld[nfiles].fname = (char *) alloc(strlen(argv[ap]) + 1); + Strcpy(ld[nfiles].fname, argv[ap]); + } + } + + if (iseen) { + /* want to do a list file */ + FILE *list = fopen(list_file, "r"); + if (!list) { + printf("Can't open %s\n",list_file); + xexit(EXIT_FAILURE); + } + + /* get file names, one per line */ + for ( ; fgets(buf, sizeof(buf), list); nfiles++) { + if (nfiles >= MAX_DLB_FILES) { + printf("Too many dlb files! Stopping at %d.\n", + MAX_DLB_FILES); + break; + } + *(eos(buf)-1) = '\0'; /* strip newline */ + ld[nfiles].fname = (char *) alloc(strlen(buf) + 1); + Strcpy(ld[nfiles].fname, buf); + } + fclose(list); + } + + if (nfiles == 0) { + printf("No files to archive\n"); + xexit(EXIT_FAILURE); + } + + + /* + * Get file sizes and name string length. Don't include + * the directory information yet. + */ + for (i = 0, slen = 0, flen = 0; i < nfiles; i++) { + fd = open(ld[i].fname, O_RDONLY|O_BINARY, 0); + if (fd < 0) { + printf("Can't open %s\n", ld[i].fname); + xexit(EXIT_FAILURE); + } + ld[i].fsize = lseek(fd, 0, SEEK_END); + ld[i].foffset = flen; + + slen += strlen(ld[i].fname); /* don't add null (yet) */ + flen += ld[i].fsize; + close(fd); + } + + /* open output file */ + out = open(library_file, O_RDWR|O_TRUNC|O_BINARY|O_CREAT, FCMASK); + if (out < 0) { + printf("Can't open %s for output\n", library_file); + xexit(EXIT_FAILURE); + } + + /* caculate directory size */ + dir_size = 40 /* header line (see below) */ + + ((nfiles+1)*11) /* handling+file offset+SP+newline */ + + slen+strlen(DLB_DIRECTORY); /* file names */ + + /* write directory */ + write_dlb_directory(out, nfiles, ld, slen, dir_size, flen); + + flen = 0L; + /* write each file */ + for (i = 0; i < nfiles; i++) { + fd = open(ld[i].fname, O_RDONLY|O_BINARY, 0); + if (fd < 0) { + printf("Can't open input file '%s'\n", ld[i].fname); + xexit(EXIT_FAILURE); + } + if (verbose) printf("%s\n",ld[i].fname); + + fsiz = 0L; + while ((r = read(fd, buf, sizeof buf)) != 0) { + if (r == -1) { + printf("Read Error in '%s'\n", ld[i].fname); + xexit(EXIT_FAILURE); + } + if (write(out, buf, r) != r) { + printf("Write Error in '%s'\n", ld[i].fname); + xexit(EXIT_FAILURE); + } + fsiz += r; + } + (void) close(fd); + if (fsiz != ld[i].fsize) rewrite_directory = TRUE; + /* in case directory rewrite is needed */ + ld[i].fsize = fsiz; + ld[i].foffset = flen; + flen += fsiz; + } + + if (rewrite_directory) { + if (verbose) printf("(rewriting dlb directory info)\n"); + (void) lseek(out, 0, SEEK_SET); /* rewind */ + write_dlb_directory(out, nfiles, ld, slen, dir_size, flen); + } + + for (i = 0; i < nfiles; i++) + free((genericptr_t) ld[i].fname), ld[i].fname = 0; + + (void) close(out); + xexit(EXIT_SUCCESS); + } + } +#endif /* DLBLIB */ +#endif /* DLB */ + + xexit(EXIT_SUCCESS); + /*NOTREACHED*/ + return 0; +} + +#ifdef DLB +#ifdef DLBLIB + +static void +write_dlb_directory(out, nfiles, ld, slen, dir_size, flen) +int out, nfiles; +libdir *ld; +long slen, dir_size, flen; +{ + char buf[BUFSIZ]; + int i; + + sprintf(buf,"%3ld %8ld %8ld %8ld %8ld\n", + (long) DLB_VERS, /* version of dlb file */ + (long) nfiles+1, /* # of entries (includes directory) */ + /* string length + room for nulls */ + (long) slen+strlen(DLB_DIRECTORY)+nfiles+1, + (long) dir_size, /* start of first file */ + (long) flen+dir_size); /* total file size */ + Write(out, buf, strlen(buf)); + + /* write each file entry */ +#define ENTRY_FORMAT "%c%s %8ld\n" + sprintf(buf, ENTRY_FORMAT, ENC_NORMAL, DLB_DIRECTORY, (long) 0); + Write(out, buf, strlen(buf)); + for (i = 0; i < nfiles; i++) { + sprintf(buf, ENTRY_FORMAT, + ENC_NORMAL, /* encoding */ + ld[i].fname, /* name */ + ld[i].foffset + dir_size); /* offset */ + Write(out, buf, strlen(buf)); + } +} + +#endif /* DLBLIB */ +#endif /* DLB */ + +static void +xexit(retcd) + int retcd; +{ +#ifdef DLB +#ifdef AMIGA + if (origdir[0]) chdir(origdir); +#endif +#endif + exit(retcd); +} + + +#ifdef AMIGA +#include "date.h" +const char amiga_version_string[] = AMIGA_VERSION_STRING; +#endif + +/*dlb_main.c*/