]>
Commit | Line | Data |
---|---|---|
1 | /* $Id$ | |
2 | * | |
3 | * Utility routines for writing tar files. | |
4 | * | |
5 | * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. | |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
8 | */ | |
9 | ||
10 | #include <mit-copyright.h> | |
11 | #include <moira.h> | |
12 | #include <moira_site.h> | |
13 | ||
14 | #include <stdio.h> | |
15 | #include <stdlib.h> | |
16 | ||
17 | #include "util.h" | |
18 | ||
19 | RCSID("$Header$"); | |
20 | ||
21 | static char tar_zeros[512]; | |
22 | ||
23 | TARFILE *tarfile_open(char *file) | |
24 | { | |
25 | TARFILE *tf; | |
26 | ||
27 | tf = malloc(sizeof(TARFILE)); | |
28 | if (!tf) | |
29 | { | |
30 | perror("couldn't open tarfile"); | |
31 | exit(MR_OCONFIG); | |
32 | } | |
33 | ||
34 | tf->fp = fopen(file, "w"); | |
35 | if (!tf->fp) | |
36 | { | |
37 | perror("couldn't open tarfile"); | |
38 | exit(MR_OCONFIG); | |
39 | } | |
40 | ||
41 | return tf; | |
42 | } | |
43 | ||
44 | void tarfile_close(TARFILE *tf) | |
45 | { | |
46 | long offset; | |
47 | int blocks; | |
48 | ||
49 | offset = ftell(tf->fp); | |
50 | /* The tar file must have two empty 512-byte blocks at the end, and | |
51 | * then must be padded to a multiple of 20 512-byte blocks. This | |
52 | * calculates how many blocks to add. | |
53 | */ | |
54 | blocks = (20 - ((offset / 512) + 2) % 20) + 2; | |
55 | ||
56 | while (blocks--) | |
57 | { | |
58 | if (fwrite(tar_zeros, 512, 1, tf->fp) != 1) | |
59 | { | |
60 | perror("could not write last tarfile block"); | |
61 | exit(MR_OCONFIG); | |
62 | } | |
63 | } | |
64 | ||
65 | fclose(tf->fp); | |
66 | free(tf); | |
67 | } | |
68 | ||
69 | FILE *tarfile_start(TARFILE *tf, char *name, mode_t mode, uid_t uid, gid_t gid, | |
70 | char *user, char *group, time_t mtime) | |
71 | { | |
72 | memset(&(tf->th), 0, sizeof(tf->th)); | |
73 | memset(tf->th.chksum, ' ', sizeof(tf->th.chksum)); | |
74 | strcpy(tf->th.name, name); | |
75 | sprintf(tf->th.mode, "%07lo", (unsigned long)mode); | |
76 | sprintf(tf->th.uid, "%07lo", (unsigned long)uid); | |
77 | sprintf(tf->th.gid, "%07lo", (unsigned long)gid); | |
78 | sprintf(tf->th.mtime, "%011lo", (unsigned long)mtime); | |
79 | tf->th.typeflag[0] = '0'; | |
80 | sprintf(tf->th.magic, "ustar"); | |
81 | sprintf(tf->th.version, "00"); | |
82 | sprintf(tf->th.uname, "%.32s", user); | |
83 | sprintf(tf->th.gname, "%.32s", group); | |
84 | ||
85 | tf->offset = ftell(tf->fp); | |
86 | ||
87 | if (fwrite(&(tf->th), sizeof(tf->th), 1, tf->fp) != 1) | |
88 | { | |
89 | perror("could not write tarfile header"); | |
90 | exit(MR_OCONFIG); | |
91 | } | |
92 | return tf->fp; | |
93 | } | |
94 | ||
95 | void tarfile_end(TARFILE *tf) | |
96 | { | |
97 | long offset = ftell(tf->fp); | |
98 | unsigned long size; | |
99 | int chksum = 0; | |
100 | char *p; | |
101 | ||
102 | size = offset - tf->offset; | |
103 | if (size % 512) | |
104 | { | |
105 | if (fwrite(tar_zeros, 512 - (size % 512), 1, tf->fp) != 1) | |
106 | goto err; | |
107 | } | |
108 | sprintf(tf->th.size, "%011lo", size - 512); | |
109 | ||
110 | for (p = (char *)&(tf->th); p < (char *)(&(tf->th) + 1); p++) | |
111 | chksum += (unsigned char)*p; | |
112 | sprintf(tf->th.chksum, "%07lo", chksum); | |
113 | ||
114 | if (fseek(tf->fp, tf->offset, SEEK_SET)) | |
115 | goto err; | |
116 | if (fwrite(&(tf->th), sizeof(tf->th), 1, tf->fp) != 1) | |
117 | goto err; | |
118 | if (fseek(tf->fp, 0, SEEK_END)) | |
119 | goto err; | |
120 | ||
121 | return; | |
122 | ||
123 | err: | |
124 | perror("could not finish tarfile entry"); | |
125 | exit(MR_OCONFIG); | |
126 | } | |
127 | ||
128 | void tarfile_mkdir(TARFILE *tf, char *name, mode_t mode, uid_t uid, gid_t gid, | |
129 | char *user, char *group, time_t mtime) | |
130 | { | |
131 | struct tarheader th; | |
132 | char *p; | |
133 | int chksum = 0; | |
134 | ||
135 | memset(&th, 0, sizeof(th)); | |
136 | memset(th.chksum, ' ', sizeof(th.chksum)); | |
137 | strcpy(th.name, name); | |
138 | sprintf(th.mode, "%07lo", (unsigned long)mode); | |
139 | sprintf(th.uid, "%07lo", (unsigned long)uid); | |
140 | sprintf(th.gid, "%07lo", (unsigned long)gid); | |
141 | sprintf(th.size, "%011lo", (unsigned long)0); | |
142 | sprintf(th.mtime, "%011lo", (unsigned long)mtime); | |
143 | th.typeflag[0] = '5'; | |
144 | sprintf(th.magic, "ustar"); | |
145 | sprintf(th.version, "00"); | |
146 | sprintf(th.uname, "%.32s", user); | |
147 | sprintf(th.gname, "%.32s", group); | |
148 | ||
149 | for (p = (char *)&th; p < (char *)(&th + 1); p++) | |
150 | chksum += (unsigned char)*p; | |
151 | sprintf(th.chksum, "%07lo", chksum); | |
152 | ||
153 | if (fwrite(&th, sizeof(th), 1, tf->fp) != 1) | |
154 | { | |
155 | perror("could not write tarfile header"); | |
156 | exit(MR_OCONFIG); | |
157 | } | |
158 | } |