2 ** Copyright 1998-2003 University of Illinois Board of Trustees
3 ** Copyright 1998-2003 Mark D. Roth
4 ** All rights reserved.
6 ** append.c - libtar code to append files to a tar archive
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>
18 #if defined(_WIN32) && !defined(__CYGWIN__)
19 # include <libtar/compat.h>
21 # ifdef HAVE_SYS_PARAM_H
22 # include <sys/param.h>
25 #include <libtar/compat.h>
26 #include <sys/types.h>
46 typedef struct tar_dev tar_dev_t
;
51 char ti_name
[TAR_MAXPATHLEN
];
53 typedef struct tar_ino tar_ino_t
;
56 /* free memory associated with a tar_dev_t */
58 tar_dev_free(tar_dev_t
*tdp
)
60 libtar_hash_free(tdp
->td_h
, free
);
65 /* appends a file to the tar archive */
67 tar_append_file(TAR
*t
, char *realname
, char *savename
)
73 #if !defined(_WIN32) || defined(__CYGWIN__)
78 char path
[TAR_MAXPATHLEN
];
81 printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
82 "savename=\"%s\")\n", t
, t
->pathname
, realname
,
83 (savename
? savename
: "[NULL]"));
86 #if defined(_WIN32) && !defined(__CYGWIN__)
87 strncpy(path
, realname
, sizeof(path
)-1);
88 path
[sizeof(path
)-1] = 0;
90 if (path
[plen
-1] == '/' )
94 if (stat(path
, &s
) != 0)
96 if (lstat(realname
, &s
) != 0)
105 /* set header block */
107 puts(" tar_append_file(): setting header block...");
109 memset(&(t
->th_buf
), 0, sizeof(struct tar_header
));
110 th_set_from_stat(t
, &s
);
112 /* set the header path */
114 puts(" tar_append_file(): setting header path...");
116 th_set_path(t
, (savename
? savename
: realname
));
118 /* check if it's a hardlink */
120 puts(" tar_append_file(): checking inode cache for hardlink...");
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
);
129 printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
130 major(s
.st_dev
), minor(s
.st_dev
));
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
)
137 if (libtar_hash_add(t
->h
, td
) == -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
);
147 printf(" tar_append_file(): encoding hard link \"%s\" "
148 "to \"%s\"...\n", realname
, ti
->ti_name
);
150 t
->th_buf
.typeflag
= LNKTYPE
;
151 th_set_link(t
, ti
->ti_name
);
157 printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
158 "(\"%s\")...\n", major(s
.st_dev
), minor(s
.st_dev
),
161 ti
= (tar_ino_t
*)calloc(1, sizeof(tar_ino_t
));
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 */
174 #if defined(_WIN32) && !defined(__CYGWIN__)
177 i
= readlink(realname
, path
, sizeof(path
));
181 if (i
>= TAR_MAXPATHLEN
)
182 i
= TAR_MAXPATHLEN
- 1;
185 printf(" tar_append_file(): encoding symlink \"%s\" -> "
186 "\"%s\"...\n", realname
, path
);
188 th_set_link(t
, path
);
192 /* print file info */
193 if (t
->options
& TAR_VERBOSE
)
197 puts(" tar_append_file(): writing header");
200 if (th_write(t
) != 0)
203 printf("t->fd = %d\n", t
->fd
);
208 puts(" tar_append_file(): back from th_write()");
211 /* if it's a regular file, write the contents as well */
212 if (TH_ISREG(t
) && tar_append_regfile(t
, realname
) != 0)
219 /* write EOF indicator */
221 tar_append_eof(TAR
*t
)
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
)
242 /* add file contents to a tarchive */
244 tar_append_regfile(TAR
*t
, char *realname
)
246 char block
[T_BLOCKSIZE
];
251 #if defined( _WIN32 ) || defined(__CYGWIN__)
252 filefd
= open(realname
, O_RDONLY
| O_BINARY
);
254 filefd
= open(realname
, O_RDONLY
);
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
)
272 fprintf(stderr
, "Unexpected size of read data: %d <> %d for file: %s\n",
273 (int)j
, T_BLOCKSIZE
, realname
);
278 if (tar_block_write(t
, &block
) == -1)
284 j
= (size_t)read(filefd
, &block
, (unsigned int)i
);
287 memset(&(block
[i
]), 0, T_BLOCKSIZE
- i
);
288 if (tar_block_write(t
, &block
) == -1)