home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * $Id: ak_dir.c,v 1.3 1992/10/29 10:26:35 ak Exp $
- *****************************************************************************
- * $Log: ak_dir.c,v $
- * Revision 1.3 1992/10/29 10:26:35 ak
- * *** empty log message ***
- *
- * Revision 1.2 1992/09/12 15:57:09 ak
- * - Usenet patches for GNU TAR 1.10
- * - Bugfixes and patches of Kai Uwe Rommel:
- * filename conversion for FAT
- * EMX 0.8e
- * -0..1 alias for a: b:
- * -2..7 alias for +++TAPE$x
- *
- * Revision 1.1 1992/09/02 20:07:32 ak
- * Initial revision
- *
- *****************************************************************************/
-
- static char *rcsid = "$Id: ak_dir.c,v 1.3 1992/10/29 10:26:35 ak Exp $";
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "tar.h"
- #include "port.h"
- #include "rmt.h"
-
- extern union record *head; /* Points to current tape header */
- extern struct stat hstat; /* Stat struct corresponding */
- extern int head_standard; /* Tape header is in ANSI format */
-
- /*
- * Random archive access.
- */
- void
- seek_exec(do_something, name, vol, voloff, rec, skip)
- void (*do_something)();
- char *name;
- int vol;
- long voloff, rec, skip;
- {
- long r;
- static int error_flag;
- extern int volno;
- extern long baserec;
- static long lastseek = - 1, lastend;
-
- if (f_multivol) {
- if (vol != volno) {
- /* next volume */
- close_archive(1);
- sprintf(ar_file + strlen(ar_file) - 3, "%03d", vol);
- open_archive(1);
- ar_last = ar_record = ar_block;
- baserec = 0;
- volno = vol;
- }
- }
-
- if (voloff + rec != lastseek) {
- lastseek = voloff + rec;
- msg("Seek to physical block %ld", voloff + rec);
- r = rmtlseek(archive, (voloff + rec) * RECORDSIZE,
- _isrmt(archive) ? 3 : 0);
- ar_last = ar_record = ar_block;
- baserec = rec;
-
- if (r < 0) {
- if (vol)
- msg_perror("Seek error on %s, volume %d record %ld",
- ar_file, vol, rec);
- else
- msg_perror("Seek error on %s, record %ld",
- ar_file, rec);
- if (++error_flag > 10) {
- msg("Too many errors, quitting.");
- exit(EX_BADARCH);
- }
- return;
- }
- }
- else
- skip -= lastend;
-
- /* skip alignment blocks */
- if (skip) {
- long record_skip = skip % blocking;
- long block_skip = skip - record_skip;
- /* msg("Skip over %ld logical blocks", skip); */
- if (block_skip) {
- r = rmtlseek(archive, block_skip * RECORDSIZE, 1);
- baserec += block_skip;
- }
- while (record_skip--)
- userec(findrec());
- }
-
- if (read_header() == 1) {
- /* We should decode next field (mode) first... */
- /* Ensure incoming names are null terminated. */
- head->header.name[NAMSIZ-1] = '\0';
-
- /* Handle the archive member */
- (*do_something)();
- lastend = baserec - rec + ar_record - ar_block;
- } else {
- if (vol)
- msg("File %s volume %d record %ld has invalid header, wrong map file?",
- name, vol, rec);
- else
- msg("File %s record %ld has invalid header, wrong map file?",
- name, rec);
- if (++error_flag > 10) {
- msg("Too many errors, quitting.");
- exit(EX_BADARCH);
- }
- }
- }
-
- /*
- * Main loop for random access.
- */
- void
- seek_and(do_something)
- void (*do_something)();
- {
- extern FILE *map_file;
- struct name *nlp;
- char line[60 + FILENAME_MAX];
- long voloff, offset, skip;
- char *p;
- int len, volume;
- #if 0
- struct Volmap {
- long base; /* physical base record no */
- short ctrl; /* no of inserted control records */
- short num; /* volume no */
- struct Volmap *prev; /* previous volume */
- } *volmap, *q;
- #endif
- name_gather(); /* Gather all the names */
- open_archive(1); /* Open for reading */
-
- volume = voloff = 0;
- rewind(map_file);
- while (fgets(line, 60 + FILENAME_MAX, map_file)) {
- char *name = line + strlen(line);
- char *key = strtok(line, " \t");
- char *arg = key ? strtok(NULL, ": \t\r\n") : NULL;
- char *mode = arg ? strtok(NULL, " \t") : NULL;
- char *q;
- offset = arg ? strtol(arg, &q, 0) : 0;
- skip = (q && *q == '+') ? strtol(q+1, &q, 0) : 0;
- if (strncmp(key, "vol", 3) == 0) {
- /* base address of tape file */
- voloff = offset;
- continue;
- }
- if (key[0] == 'V') {
- /* tape number */
- volume = atoi(key+1);
- continue;
- }
- if (strcmp(key, "blk") == 0) {
- extern long tapeblock;
- voloff = 0;
- offset = offset * tapeblock / RECORDSIZE;
- } else if (strncmp(key, "rec", 3) != 0)
- continue;
- if (mode[0] == 'M')
- continue;
-
- /* get file name from record line -- skip "(..)" descr */
- while (isspace(*(name-1)))
- --name;
- if (mode[0] == 'A' && *(name-1) == ')')
- while (*--name != '(')
- ;
- while (isspace(*(name-1)))
- --name;
- *name = '\0';
- while (!isspace(*(name-1)))
- --name;
- len = strlen(name);
-
- /* look if name is mentioned in command line */
- for (nlp = namelist; nlp; nlp = nlp->next) {
- /* fast check for first character */
- if (nlp->firstch && nlp->name[0] != name[0])
- continue;
-
- /* regular expression? */
- if (nlp->regexp) {
- if (wildmat(name, nlp->name))
- goto match;
- continue;
- }
-
- /* plain name */
- if (nlp->length <= len
- && (name[nlp->length] == '\0'
- || name[nlp->length] == '/')
- #ifdef MSDOS
- && strnicmp(name, nlp->name, nlp->length) == 0)
- #else
- && strncmp(name, nlp->name, nlp->length) == 0)
- #endif
- goto match;
- continue;
-
- match: seek_exec(do_something, name, volume, voloff, offset, skip);
- if (mode[0] != 'A')
- nlp->found = 1;
- }
- }
-
- close_archive(1);
- names_notfound(); /* Print names not found */
- }
-
-
-