|
|
1.1 root 1: #include <stddef.h>
2: #include <stdio.h>
3: #include <sys/types.h>
4: #include <sys/stat.h>
5: #include <libv.h>
6: #include "ftwlk.h"
7: #include "tar.h"
8: #include "misc.h"
9:
10: #define MIN(A, B) ((A) < (B) ? (A) : (B))
11:
12: int vflag;
13:
14: int nerr;
15:
16: struct hardlink {
17: char *name;
18: int ino;
19: int dev;
20: struct hardlink *next;
21: };
22:
23: struct hardlink *links;
24:
25: struct hardlink *
26: findlink(char *name, int ino, int dev)
27: {
28: struct hardlink *h;
29:
30: for (h = links; h; h = h->next)
31: if (ino == h->ino && dev == h->dev)
32: return h;
33: h = xmalloc(sizeof (struct hardlink));
34: h->name = xstrdup(name);
35: h->ino = ino;
36: h->dev = dev;
37: h->next = links;
38: links = h;
39: return 0; /* make a new entry, but say we didn't find it */
40: }
41:
42: #ifndef S_ISREG
43: #define S_ISREG(M) (((M) & S_IFMT) == S_IFREG)
44: #endif
45:
46: void
47: zeropad(long from, long to)
48: {
49: static char zero[512];
50: static int n;
51:
52: while (from < to) {
53: n = MIN(to - from, sizeof zero);
54: if (fwrite(zero, 1, n, stdout) != n) {
55: fprintf(stderr, "tarc: zero padding failed\n");
56: exit(1);
57: }
58: from += n;
59: }
60: }
61:
62: int
63: dofile(char *name, struct stat *st, int code, struct FTWLK *f)
64: {
65: struct tarhdr hdr;
66: struct tarbuf buf;
67: struct hardlink *hl;
68: FILE *fp;
69: long cc;
70:
71: if (code == FTWLK_NSL || code == FTWLK_SL)
72: lstat(name, st); /* fix ftwlk braindamage */
73:
74: memset(&hdr, 0, sizeof hdr);
75: if (strlen(name) > TNAMEMAX) {
76: fprintf(stderr, "tarc: file name too long '%s'\n", name);
77: exit(1);
78: }
79:
80: strcpy(hdr.name, name);
81: hdr.mode = st->st_mode & TMASK;
82: hdr.uid = st->st_uid;
83: hdr.gid = st->st_gid;
84: hdr.size = st->st_size;
85: hdr.mtime = st->st_mtime;
86:
87: switch (code) {
88: case FTWLK_D:
89: if (strlen(name) <= TNAMEMAX - 1)
90: strcat(hdr.name, "/");
91: hdr.typeflag = DIRTYPE;
92: break;
93:
94: case FTWLK_F:
95: if (st->st_nlink > 1
96: && (hl = findlink(name, st->st_ino, st->st_dev))
97: && strlen(hl->name) <= TLINKMAX) {
98: hdr.typeflag = LNKTYPE;
99: strcpy(hdr.linkname, hl->name);
100: } else if (S_ISREG(st->st_mode))
101: hdr.typeflag = REGTYPE;
102: else {
103: fprintf(stderr, "tarc: not a regular file '%s'\n",
104: name);
105: ++nerr;
106: return 0;
107: }
108: break;
109:
110: case FTWLK_SL:
111: if (f->level == 0) {
112: f->quit = FTWLK_FOLLOW;
113: return 0;
114: }
115: hdr.typeflag = SYMTYPE;
116: cc = readlink(name, hdr.linkname, sizeof hdr.linkname);
117: if (cc < 0) {
118: fprintf(stderr, "tarc: can't read symlink '%s'\n",
119: name);
120: ++nerr;
121: return 0;
122: }
123: break;
124:
125: default:
126: return 0;
127: }
128:
129: if (hdr.typeflag != REGTYPE)
130: hdr.size = 0;
131: if (vflag)
132: fprintf(stderr, "%s\n", hdr.name);
133: if (thdrput(&buf, &hdr) != 0) {
134: fprintf(stderr, "tarc: failed making header for '%s'\n", name);
135: ++nerr;
136: return 0;
137: }
138: if (hdr.typeflag == REGTYPE && !(fp = fopen(name, "r")))
139: return 0;
140: if (fwrite(&buf, sizeof buf, 1, stdout) != 1) {
141: fprintf(stderr, "tarc: write failed\n");
142: exit(1);
143: }
144: if (hdr.typeflag == REGTYPE) {
145: cc = fpcopy(stdout, fp, st->st_size);
146: if (cc < 0) {
147: fprintf(stderr, "tarc: file copy failed '%s'\n", name);
148: exit(1);
149: }
150: if (cc != st->st_size)
151: fprintf(stderr, "tarc: warning: size change '%s'\n",
152: name);
153: zeropad(cc, (st->st_size + TSIZE - 1) / TSIZE * TSIZE);
154: fclose(fp);
155: }
156: return 0;
157: }
158:
159: void
160: usage(void)
161: {
162: fprintf(stderr, "usage: tarc [-v] files...\n");
163: exit(1);
164: }
165:
166: int
167: main(int argc, char *argv[])
168: {
169: int i, c;
170:
171: prog = argv[0];
172: while ((c = getopt(argc, argv, "v")) != EOF)
173: switch (c) {
174: case 'v':
175: ++vflag;
176: break;
177: default:
178: usage();
179: break;
180: }
181: for (i = optind; i < argc; ++i)
182: ftwlk(argv[i], dofile, 10);
183: zeropad(0, 2 * TSIZE);
184: return nerr ? 1 : 0;
185: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.