1 /* $XConsortium: misc.c /main/3 1995/11/01 17:01:03 rswiston $ */
2 /***************************************************************
6 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
9 * Copyright (c) 1995 AT&T Corp. *
10 * All Rights Reserved *
12 * This software is licensed by AT&T Corp. *
13 * under the terms and conditions of the license in *
14 * http://www.research.att.com/orgs/ssr/book/reuse *
16 * This software was created by the *
17 * Software Engineering Research Department *
18 * AT&T Bell Laboratories *
20 * For further information contact *
21 * gsf@research.att.com *
23 ***************************************************************/
25 /* : : generated by proto : : */
27 #if !defined(__PROTO__)
28 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
29 #if defined(__cplusplus)
30 #define __MANGLE__ "C"
35 #define __PROTO__(x) x
37 #define __PARAM__(n,o) n
38 #if !defined(__STDC__) && !defined(__cplusplus)
39 #if !defined(c_plusplus)
50 #define __PROTO__(x) ()
51 #define __OTORP__(x) x
52 #define __PARAM__(n,o) o
60 #if defined(__cplusplus) || defined(c_plusplus)
61 #define __VARARG__ ...
65 #if defined(__STDARG__)
66 #define __VA_START__(p,a) va_start(p,a)
68 #define __VA_START__(p,a) va_start(p)
77 * return format index given format name
81 getformat __PARAM__((register char* name), (name)) __OTORP__(register char* name;){
85 for (i = 0; format[i].name; i++)
86 if (streq(name, format[i].name))
88 return(format[i].name ? i : streq(name, "-") || streq(name, "pax") ? OUT_DEFAULT : -1);
96 pathcmp __PARAM__((register const char* s, register const char* t), (s, t)) __OTORP__(register const char* s; register const char* t;){
107 if (tc == 0 || tc == '/')
111 return(strcoll(s - 1, t - 1));
117 * check base archive ordering
121 ordered __PARAM__((Archive_t* ap, const char* prv, const char* cur), (ap, prv, cur)) __OTORP__(Archive_t* ap; const char* prv; const char* cur;){
122 if (pathcmp(prv, cur) > 0)
123 error(3, "%s: %s: archive member must appear before %s", ap->name, prv, cur);
127 * check f with patterns given on cmd line
131 selectfile __PARAM__((register Archive_t* ap, register File_t* f), (ap, f)) __OTORP__(register Archive_t* ap; register File_t* f;){
132 register Archive_t* bp;
133 register Member_t* d;
136 if (f->skip || f->namesize <= 1)
140 ordered(ap, ap->path.prev, f->name);
141 strcpy(ap->path.prev, f->name);
143 if (f->record.format && state.record.pattern)
147 fmt[0] = f->record.format;
148 if (!strmatch(fmt, state.record.pattern))
151 if (state.append || ap->parent)
157 if (!(d = newof(0, Member_t, 1, 0)))
158 error(3, "%s: out of space", f->name);
159 d->dev = f->st->st_dev;
160 d->ino = f->st->st_ino;
161 d->mtime = f->st->st_mtime;
162 d->offset = ap->io.offset + ap->io.count;
163 d->size = f->st->st_size;
164 d->expand = f->delta.size;
165 if (!(d->info = (File_t*)memdup(f, sizeof(File_t))) || !(d->info->st = (struct stat*)memdup(f->st, sizeof(struct stat))))
166 error(3, "%s: out of space", f->name);
167 d->info->name = d->info->path = hashput(ap->parent->delta->tab, f->name, d);
168 if (d->info->uidname) d->info->uidname = strdup(d->info->uidname);
169 if (d->info->gidname) d->info->gidname = strdup(d->info->gidname);
170 d->info->delta.base = d;
174 if (!match(f->name) || state.verify && f->type != X_IFDIR && !verify(ap, f))
177 if (state.list && !linked)
179 if (state.ordered && ap->delta && ap->delta->format != COMPRESS && (bp = ap->delta->base))
186 if (bp->peek) bp->peek = 0;
189 if (bp->skip && bp->skip == bp->io.offset + bp->io.count)
190 fileskip(bp, &bp->file);
191 if (!getheader(bp, &bp->file)) break;
192 bp->skip = bp->io.offset + bp->io.count;
194 ordered(bp, bp->path.prev, bp->file.name);
195 if ((m = pathcmp(bp->file.name, f->name)) > 0)
200 n = selectfile(bp, &bp->file);
202 if (n && !state.list)
208 initfile(ap, &tmp, bp->file.name, X_IFREG);
209 tmp.delta.op = DELTA_delete;
211 puttrailer(ap, &tmp);
217 if (!(*state.statf)(f->name, &st))
219 if (S_ISDIR(st.st_mode))
221 if (!streq(f->name, ".") && !streq(f->name, ".."))
223 if (rmdir(f->name)) error(ERROR_SYSTEM|2, "%s: cannot remove directory", f->name);
227 else if (remove(f->name)) error(ERROR_SYSTEM|2, "%s: cannot remove file", f->name);
238 * verify action on file
247 verify __PARAM__((Archive_t* ap, register File_t* f), (ap, f)) __OTORP__(Archive_t* ap; register File_t* f;){
248 register char* prompt;
252 if (state.yesno) switch (state.operation)
264 else prompt = "Rename";
265 sfprintf(state.wtty, "%s %s: " , prompt, f->name);
266 if (!(name = sfgetr(state.rtty, '\n', 1)))
268 sfputc(state.wtty, '\n');
272 return(*name == 'y');
278 if (!*(name + 1)) break;
281 f->namesize = pathcanon(f->name = name, 0) - name + 1;
288 * check for file name mapping
289 * static data possibly returned
290 * two simultaneous calls supported
294 map __PARAM__((register char* name), (name)) __OTORP__(register char* name;){
299 static char filebuffer[4][PATH_MAX];
300 static int filename = 0;
304 for (mp = state.maps; mp; mp = mp->next)
305 if (reexec(mp->re, from))
308 to = filebuffer[filename];
309 resub(mp->re, from, mp->into, to, mp->flags);
310 if (mp->flags & RE_VERBOSE) sfprintf(sfstderr, "%s >> %s\n", from, to);
311 if (mp->flags & RE_STOP) break;
324 * sfkeyprintf() lookup
328 listlookup __PARAM__((__V_* handle, register const char* name, const char* arg, int cc, char** ps, long* pn), (handle, name, arg, cc, ps, pn)) __OTORP__(__V_* handle; register const char* name; const char* arg; int cc; char** ps; long* pn;){
329 List_handle_t* gp = (List_handle_t*)handle;
330 register File_t* f = gp->file;
331 register struct stat* st = f->st;
332 register char* s = 0;
337 static const char fmt_time[] = "time=%?%l";
338 static const char fmt_mode[] = "mode";
340 static char buf[PATH_MAX];
343 if (!(op = (Option_t*)hashget(state.options, name)))
347 if (!(op = newof(0, Option_t, 1, 0)))
348 error(3, "out of space [option]");
349 op->name = hashput(state.options, 0, op);
350 op->macro = getenv(name + 1);
351 op->index = OPT_environ;
352 op->flags |= OPT_DISABLE;
354 if (op->macro && !(op->flags & OPT_DISABLE))
356 op->flags |= OPT_DISABLE;
357 if (!mp && !(mp = sfstropen()))
358 error(3, "out of space [macro]");
359 sfkeyprintf(mp, handle, op->macro, listlookup, NiL);
361 op->flags &= ~OPT_DISABLE;
363 else switch (op->index)
377 if (!gp->archive || gp->archive->format != PAX && gp->archive->format != TAR && gp->archive->format != USTAR)
382 s = tar_header.chksum;
385 s = tar_header.magic;
388 n = tar_header.typeflag;
391 s = tar_header.version;
419 sfsprintf(s = huh, sizeof(huh), "[op=%c]", f->delta.op);
424 if (f->type == X_IFBLK || f->type == X_IFCHR)
429 n = major(st->st_dev);
432 n = minor(st->st_dev);
435 if (!(s = op->macro))
441 if (cc == 's') s = f->gidname;
442 else n = strgid(f->gidname);
444 else if (cc == 's') s = fmtgid(st->st_gid);
464 if (f->linktype == NOLINK)
469 if (f->linktype == HARDLINK)
471 else if (f->linktype == SOFTLINK)
473 else if (f->type == X_IFDIR)
475 else if (f->type == X_IFIFO || f->type == X_IFSOCK)
477 else if (f->type == X_IFBLK || f->type == X_IFCHR)
479 else if (st->st_mode & (X_IXUSR|X_IXGRP|X_IXOTH))
494 if (s = strrchr(f->name, '/')) s++;
504 sfsprintf(s = buf, sizeof(buf), "%d-%d", gp->archive->volume, gp->archive->entry);
507 if (f->linktype == SOFTLINK) n = f->linknamesize - 1;
508 else if (f->delta.size != -1) n = f->delta.size;
509 else n = st->st_size;
514 if (cc == 's') s = f->uidname;
515 else n = strgid(f->uidname);
517 else if (cc == 's') s = fmtuid(st->st_uid);
524 else if (cc == 's' && arg)
526 if (strneq(arg, fmt_mode, 4))
528 else if (strneq(arg, fmt_time, 4))
529 *ps = fmttime((*(arg + 4) == '=' ? arg : fmt_time) + 5, n);
536 * set up lookup() handle and call sfkeyprintf()
540 listprintf __PARAM__((Sfio_t* sp, Archive_t* ap, File_t* f, const char* format), (sp, ap, f, format)) __OTORP__(Sfio_t* sp; Archive_t* ap; File_t* f; const char* format;){
544 list.archive = state.in;
546 return(sfkeyprintf(sp, &list, format, listlookup, NiL));
550 * list entry information based on state.drop, state.list and state.verbose
554 listentry __PARAM__((register File_t* f), (f)) __OTORP__(register File_t* f;){
555 if (!f->extended && !f->skip && (state.drop || state.list || state.verbose))
559 if (++state.dropcount >= 50)
562 sfprintf(sfstderr, ".\n");
566 sfprintf(sfstderr, ".");
570 else listprintf(state.list ? sfstdout : sfstderr, state.in, f, state.listformat);
575 * prepare patterns for match()
579 initmatch __PARAM__((char** p), (p)) __OTORP__(char** p;){
589 * determine if file s matches input patterns
593 match __PARAM__((register char* s), (s)) __OTORP__(register char* s;){
598 if (!(p = state.patterns)) return(state.matchsense);
614 else while (t = *p++)
616 if (state.descend && dirprefix(t, s) || strmatch(s, t))
617 return(state.matchsense);
619 return(!state.matchsense);
623 * return 1 if p is a directory prefix of s
627 dirprefix __PARAM__((register char* p, register char* s), (p, s)) __OTORP__(register char* p; register char* s;){
628 if (*p == '.' && !*(p + 1) && *s != '/' && (*s != '.' || *(s + 1) != '.' || *(s + 2) && *(s + 2) != '/'))
630 if (*p == '/' && !*(p + 1))
635 return(!*s || *s == '/');
639 * return 1 if s is a portable string
643 portable __PARAM__((const char* s), (s)) __OTORP__(const char* s;){
644 register unsigned char* u = (unsigned char*)s;