Fixed short int / int compiler warnings in va_arg() usage
[libtar.git] / lib / append.c
blob05024b92609b0db687e289a934c4c49edc3397da
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 <internal.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <sys/param.h>
19 #include <sys/types.h>
21 #ifdef STDC_HEADERS
22 # include <stdlib.h>
23 # include <string.h>
24 #endif
26 #ifdef HAVE_UNISTD_H
27 # include <unistd.h>
28 #endif
31 struct tar_dev
33 dev_t td_dev;
34 libtar_hash_t *td_h;
36 typedef struct tar_dev tar_dev_t;
38 struct tar_ino
40 ino_t ti_ino;
41 char ti_name[MAXPATHLEN];
43 typedef struct tar_ino tar_ino_t;
46 /* free memory associated with a tar_dev_t */
47 void
48 tar_dev_free(tar_dev_t *tdp)
50 libtar_hash_free(tdp->td_h, free);
51 free(tdp);
55 /* appends a file to the tar archive */
56 int
57 tar_append_file(TAR *t, char *realname, char *savename)
59 struct stat s;
60 int i;
61 libtar_hashptr_t hp;
62 tar_dev_t *td = NULL;
63 tar_ino_t *ti = NULL;
64 char path[MAXPATHLEN];
66 #ifdef DEBUG
67 printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
68 "savename=\"%s\")\n", t, t->pathname, realname,
69 (savename ? savename : "[NULL]"));
70 #endif
72 if (lstat(realname, &s) != 0)
74 #ifdef DEBUG
75 perror("lstat()");
76 #endif
77 return -1;
80 /* set header block */
81 #ifdef DEBUG
82 puts(" tar_append_file(): setting header block...");
83 #endif
84 memset(&(t->th_buf), 0, sizeof(struct tar_header));
85 th_set_from_stat(t, &s);
87 /* set the header path */
88 #ifdef DEBUG
89 puts(" tar_append_file(): setting header path...");
90 #endif
91 th_set_path(t, (savename ? savename : realname));
93 /* check if it's a hardlink */
94 #ifdef DEBUG
95 puts(" tar_append_file(): checking inode cache for hardlink...");
96 #endif
97 libtar_hashptr_reset(&hp);
98 if (libtar_hash_getkey(t->h, &hp, &(s.st_dev),
99 (libtar_matchfunc_t)dev_match) != 0)
100 td = (tar_dev_t *)libtar_hashptr_data(&hp);
101 else
103 #ifdef DEBUG
104 printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
105 major(s.st_dev), minor(s.st_dev));
106 #endif
107 td = (tar_dev_t *)calloc(1, sizeof(tar_dev_t));
108 td->td_dev = s.st_dev;
109 td->td_h = libtar_hash_new(256, (libtar_hashfunc_t)ino_hash);
110 if (td->td_h == NULL)
111 return -1;
112 if (libtar_hash_add(t->h, td) == -1)
113 return -1;
115 libtar_hashptr_reset(&hp);
116 if (libtar_hash_getkey(td->td_h, &hp, &(s.st_ino),
117 (libtar_matchfunc_t)ino_match) != 0)
119 ti = (tar_ino_t *)libtar_hashptr_data(&hp);
120 #ifdef DEBUG
121 printf(" tar_append_file(): encoding hard link \"%s\" "
122 "to \"%s\"...\n", realname, ti->ti_name);
123 #endif
124 t->th_buf.typeflag = LNKTYPE;
125 th_set_link(t, ti->ti_name);
127 else
129 #ifdef DEBUG
130 printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
131 "(\"%s\")...\n", major(s.st_dev), minor(s.st_dev),
132 s.st_ino, realname);
133 #endif
134 ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t));
135 if (ti == NULL)
136 return -1;
137 ti->ti_ino = s.st_ino;
138 snprintf(ti->ti_name, sizeof(ti->ti_name), "%s",
139 savename ? savename : realname);
140 libtar_hash_add(td->td_h, ti);
143 /* check if it's a symlink */
144 if (TH_ISSYM(t))
146 i = readlink(realname, path, sizeof(path));
147 if (i == -1)
148 return -1;
149 if (i >= MAXPATHLEN)
150 i = MAXPATHLEN - 1;
151 path[i] = '\0';
152 #ifdef DEBUG
153 printf(" tar_append_file(): encoding symlink \"%s\" -> "
154 "\"%s\"...\n", realname, path);
155 #endif
156 th_set_link(t, path);
159 /* print file info */
160 if (t->options & TAR_VERBOSE)
161 th_print_long_ls(t);
163 #ifdef DEBUG
164 puts(" tar_append_file(): writing header");
165 #endif
166 /* write header */
167 if (th_write(t) != 0)
169 #ifdef DEBUG
170 printf("t->fd = %d\n", t->fd);
171 #endif
172 return -1;
174 #ifdef DEBUG
175 puts(" tar_append_file(): back from th_write()");
176 #endif
178 /* if it's a regular file, write the contents as well */
179 if (TH_ISREG(t) && tar_append_regfile(t, realname) != 0)
180 return -1;
182 return 0;
186 /* write EOF indicator */
188 tar_append_eof(TAR *t)
190 int i, j;
191 char block[T_BLOCKSIZE];
193 memset(&block, 0, T_BLOCKSIZE);
194 for (j = 0; j < 2; j++)
196 i = tar_block_write(t, &block);
197 if (i != T_BLOCKSIZE)
199 if (i != -1)
200 errno = EINVAL;
201 return -1;
205 return 0;
209 /* add file contents to a tarchive */
211 tar_append_regfile(TAR *t, char *realname)
213 char block[T_BLOCKSIZE];
214 int filefd;
215 int i, j;
216 size_t size;
218 filefd = open(realname, O_RDONLY);
219 if (filefd == -1)
221 #ifdef DEBUG
222 perror("open()");
223 #endif
224 return -1;
227 size = th_get_size(t);
228 for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE)
230 j = read(filefd, &block, T_BLOCKSIZE);
231 if (j != T_BLOCKSIZE)
233 if (j != -1)
234 errno = EINVAL;
235 return -1;
237 if (tar_block_write(t, &block) == -1)
238 return -1;
241 if (i > 0)
243 j = read(filefd, &block, i);
244 if (j == -1)
245 return -1;
246 memset(&(block[i]), 0, T_BLOCKSIZE - i);
247 if (tar_block_write(t, &block) == -1)
248 return -1;
251 close(filefd);
253 return 0;