Updated formatting of documentation plus a little reorganization.
[cmake.git] / Utilities / cmtar / append.c
blob14c7362932d6a1192cbb2de28ca34cc966c53f5f
1 /*
2 ** Copyright 1998-2003 University of Illinois Board of Trustees
3 ** Copyright 1998-2003 Mark D. Roth
4 ** All rights reserved.
5 **
6 ** append.c - libtar code to append files to a tar archive
7 **
8 ** Mark D. Roth <roth@uiuc.edu>
9 ** Campus Information Technologies and Educational Services
10 ** University of Illinois at Urbana-Champaign
13 #include <libtarint/internal.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #if defined(_WIN32) && !defined(__CYGWIN__)
19 # include <libtar/compat.h>
20 #else
21 # ifdef HAVE_SYS_PARAM_H
22 # include <sys/param.h>
23 # endif
24 #endif
25 #include <libtar/compat.h>
26 #include <sys/types.h>
28 #ifdef STDC_HEADERS
29 # include <stdlib.h>
30 # include <string.h>
31 #endif
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
37 #ifdef HAVE_IO_H
38 # include <io.h>
39 #endif
41 struct tar_dev
43 dev_t td_dev;
44 libtar_hash_t *td_h;
46 typedef struct tar_dev tar_dev_t;
48 struct tar_ino
50 ino_t ti_ino;
51 char ti_name[TAR_MAXPATHLEN];
53 typedef struct tar_ino tar_ino_t;
56 /* free memory associated with a tar_dev_t */
57 void
58 tar_dev_free(tar_dev_t *tdp)
60 libtar_hash_free(tdp->td_h, free);
61 free(tdp);
65 /* appends a file to the tar archive */
66 int
67 tar_append_file(TAR *t, char *realname, char *savename)
69 struct stat s;
70 libtar_hashptr_t hp;
71 tar_dev_t *td;
72 tar_ino_t *ti;
73 #if !defined(_WIN32) || defined(__CYGWIN__)
74 int i;
75 #else
76 size_t plen;
77 #endif
78 char path[TAR_MAXPATHLEN];
80 #ifdef DEBUG
81 printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
82 "savename=\"%s\")\n", t, t->pathname, realname,
83 (savename ? savename : "[NULL]"));
84 #endif
86 #if defined(_WIN32) && !defined(__CYGWIN__)
87 strncpy(path, realname, sizeof(path)-1);
88 path[sizeof(path)-1] = 0;
89 plen = strlen(path);
90 if (path[plen-1] == '/' )
92 path[plen-1] = 0;
94 if (stat(path, &s) != 0)
95 #else
96 if (lstat(realname, &s) != 0)
97 #endif
99 #ifdef DEBUG
100 perror("lstat()");
101 #endif
102 return -1;
105 /* set header block */
106 #ifdef DEBUG
107 puts(" tar_append_file(): setting header block...");
108 #endif
109 memset(&(t->th_buf), 0, sizeof(struct tar_header));
110 th_set_from_stat(t, &s);
112 /* set the header path */
113 #ifdef DEBUG
114 puts(" tar_append_file(): setting header path...");
115 #endif
116 th_set_path(t, (savename ? savename : realname));
118 /* check if it's a hardlink */
119 #ifdef DEBUG
120 puts(" tar_append_file(): checking inode cache for hardlink...");
121 #endif
122 libtar_hashptr_reset(&hp);
123 if (libtar_hash_getkey(t->h, &hp, &(s.st_dev),
124 (libtar_matchfunc_t)dev_match) != 0)
125 td = (tar_dev_t *)libtar_hashptr_data(&hp);
126 else
128 #ifdef DEBUG
129 printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
130 major(s.st_dev), minor(s.st_dev));
131 #endif
132 td = (tar_dev_t *)calloc(1, sizeof(tar_dev_t));
133 td->td_dev = s.st_dev;
134 td->td_h = libtar_hash_new(256, (libtar_hashfunc_t)ino_hash);
135 if (td->td_h == NULL)
136 return -1;
137 if (libtar_hash_add(t->h, td) == -1)
138 return -1;
140 libtar_hashptr_reset(&hp);
141 #if !defined(_WIN32) || defined(__CYGWIN__)
142 if (libtar_hash_getkey(td->td_h, &hp, &(s.st_ino),
143 (libtar_matchfunc_t)ino_match) != 0)
145 ti = (tar_ino_t *)libtar_hashptr_data(&hp);
146 #ifdef DEBUG
147 printf(" tar_append_file(): encoding hard link \"%s\" "
148 "to \"%s\"...\n", realname, ti->ti_name);
149 #endif
150 t->th_buf.typeflag = LNKTYPE;
151 th_set_link(t, ti->ti_name);
153 else
154 #endif
156 #ifdef DEBUG
157 printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
158 "(\"%s\")...\n", major(s.st_dev), minor(s.st_dev),
159 s.st_ino, realname);
160 #endif
161 ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t));
162 if (ti == NULL)
163 return -1;
164 ti->ti_ino = s.st_ino;
165 snprintf(ti->ti_name, sizeof(ti->ti_name), "%s",
166 savename ? savename : realname);
167 libtar_hash_add(td->td_h, ti);
170 #if !defined(_WIN32) || defined(__CYGWIN__)
171 /* check if it's a symlink */
172 if (TH_ISSYM(t))
174 #if defined(_WIN32) && !defined(__CYGWIN__)
175 i = -1;
176 #else
177 i = readlink(realname, path, sizeof(path));
178 #endif
179 if (i == -1)
180 return -1;
181 if (i >= TAR_MAXPATHLEN)
182 i = TAR_MAXPATHLEN - 1;
183 path[i] = '\0';
184 #ifdef DEBUG
185 printf(" tar_append_file(): encoding symlink \"%s\" -> "
186 "\"%s\"...\n", realname, path);
187 #endif
188 th_set_link(t, path);
190 #endif
192 /* print file info */
193 if (t->options & TAR_VERBOSE)
194 th_print_long_ls(t);
196 #ifdef DEBUG
197 puts(" tar_append_file(): writing header");
198 #endif
199 /* write header */
200 if (th_write(t) != 0)
202 #ifdef DEBUG
203 printf("t->fd = %d\n", t->fd);
204 #endif
205 return -1;
207 #ifdef DEBUG
208 puts(" tar_append_file(): back from th_write()");
209 #endif
211 /* if it's a regular file, write the contents as well */
212 if (TH_ISREG(t) && tar_append_regfile(t, realname) != 0)
213 return -1;
215 return 0;
219 /* write EOF indicator */
221 tar_append_eof(TAR *t)
223 ssize_t i, j;
224 char block[T_BLOCKSIZE];
226 memset(&block, 0, T_BLOCKSIZE);
227 for (j = 0; j < 2; j++)
229 i = tar_block_write(t, &block);
230 if (i != T_BLOCKSIZE)
232 if (i != -1)
233 errno = EINVAL;
234 return -1;
238 return 0;
242 /* add file contents to a tarchive */
244 tar_append_regfile(TAR *t, char *realname)
246 char block[T_BLOCKSIZE];
247 int filefd;
248 ssize_t i, j;
249 size_t size;
251 #if defined( _WIN32 ) || defined(__CYGWIN__)
252 filefd = open(realname, O_RDONLY | O_BINARY);
253 #else
254 filefd = open(realname, O_RDONLY);
255 #endif
256 if (filefd == -1)
258 #ifdef DEBUG
259 perror("open()");
260 #endif
261 return -1;
264 size = th_get_size(t);
265 for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE)
267 j = read(filefd, &block, T_BLOCKSIZE);
268 if (j != T_BLOCKSIZE)
270 if (j != -1)
272 fprintf(stderr, "Unexpected size of read data: %d <> %d for file: %s\n",
273 (int)j, T_BLOCKSIZE, realname);
274 errno = EINVAL;
276 return -1;
278 if (tar_block_write(t, &block) == -1)
279 return -1;
282 if (i > 0)
284 j = (size_t)read(filefd, &block, (unsigned int)i);
285 if (j == -1)
286 return -1;
287 memset(&(block[i]), 0, T_BLOCKSIZE - i);
288 if (tar_block_write(t, &block) == -1)
289 return -1;
292 close(filefd);
294 return 0;