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 # include <sys/param.h>
23 #include <libtar/compat.h>
24 #include <sys/types.h>
44 typedef struct tar_dev tar_dev_t
;
49 char ti_name
[TAR_MAXPATHLEN
];
51 typedef struct tar_ino tar_ino_t
;
54 /* free memory associated with a tar_dev_t */
56 tar_dev_free(tar_dev_t
*tdp
)
58 libtar_hash_free(tdp
->td_h
, free
);
63 /* appends a file to the tar archive */
65 tar_append_file(TAR
*t
, char *realname
, char *savename
)
71 #if !defined(_WIN32) || defined(__CYGWIN__)
76 char path
[TAR_MAXPATHLEN
];
79 printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
80 "savename=\"%s\")\n", t
, t
->pathname
, realname
,
81 (savename
? savename
: "[NULL]"));
84 #if defined(_WIN32) && !defined(__CYGWIN__)
85 strncpy(path
, realname
, sizeof(path
)-1);
86 path
[sizeof(path
)-1] = 0;
88 if (path
[plen
-1] == '/' )
92 if (stat(path
, &s
) != 0)
94 if (lstat(realname
, &s
) != 0)
103 /* set header block */
105 puts(" tar_append_file(): setting header block...");
107 memset(&(t
->th_buf
), 0, sizeof(struct tar_header
));
108 th_set_from_stat(t
, &s
);
110 /* set the header path */
112 puts(" tar_append_file(): setting header path...");
114 th_set_path(t
, (savename
? savename
: realname
));
116 /* check if it's a hardlink */
118 puts(" tar_append_file(): checking inode cache for hardlink...");
120 libtar_hashptr_reset(&hp
);
121 if (libtar_hash_getkey(t
->h
, &hp
, &(s
.st_dev
),
122 (libtar_matchfunc_t
)dev_match
) != 0)
123 td
= (tar_dev_t
*)libtar_hashptr_data(&hp
);
127 printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
128 major(s
.st_dev
), minor(s
.st_dev
));
130 td
= (tar_dev_t
*)calloc(1, sizeof(tar_dev_t
));
131 td
->td_dev
= s
.st_dev
;
132 td
->td_h
= libtar_hash_new(256, (libtar_hashfunc_t
)ino_hash
);
133 if (td
->td_h
== NULL
)
135 if (libtar_hash_add(t
->h
, td
) == -1)
138 libtar_hashptr_reset(&hp
);
139 #if !defined(_WIN32) || defined(__CYGWIN__)
140 if (libtar_hash_getkey(td
->td_h
, &hp
, &(s
.st_ino
),
141 (libtar_matchfunc_t
)ino_match
) != 0)
143 ti
= (tar_ino_t
*)libtar_hashptr_data(&hp
);
145 printf(" tar_append_file(): encoding hard link \"%s\" "
146 "to \"%s\"...\n", realname
, ti
->ti_name
);
148 t
->th_buf
.typeflag
= LNKTYPE
;
149 th_set_link(t
, ti
->ti_name
);
155 printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
156 "(\"%s\")...\n", major(s
.st_dev
), minor(s
.st_dev
),
159 ti
= (tar_ino_t
*)calloc(1, sizeof(tar_ino_t
));
162 ti
->ti_ino
= s
.st_ino
;
163 snprintf(ti
->ti_name
, sizeof(ti
->ti_name
), "%s",
164 savename
? savename
: realname
);
165 libtar_hash_add(td
->td_h
, ti
);
168 #if !defined(_WIN32) || defined(__CYGWIN__)
169 /* check if it's a symlink */
172 #if defined(_WIN32) && !defined(__CYGWIN__)
175 i
= readlink(realname
, path
, sizeof(path
));
179 if (i
>= TAR_MAXPATHLEN
)
180 i
= TAR_MAXPATHLEN
- 1;
183 printf(" tar_append_file(): encoding symlink \"%s\" -> "
184 "\"%s\"...\n", realname
, path
);
186 th_set_link(t
, path
);
190 /* print file info */
191 if (t
->options
& TAR_VERBOSE
)
195 puts(" tar_append_file(): writing header");
198 if (th_write(t
) != 0)
201 printf("t->fd = %d\n", t
->fd
);
206 puts(" tar_append_file(): back from th_write()");
209 /* if it's a regular file, write the contents as well */
210 if (TH_ISREG(t
) && tar_append_regfile(t
, realname
) != 0)
217 /* write EOF indicator */
219 tar_append_eof(TAR
*t
)
222 char block
[T_BLOCKSIZE
];
224 memset(&block
, 0, T_BLOCKSIZE
);
225 for (j
= 0; j
< 2; j
++)
227 i
= tar_block_write(t
, &block
);
228 if (i
!= T_BLOCKSIZE
)
240 /* add file contents to a tarchive */
242 tar_append_regfile(TAR
*t
, char *realname
)
244 char block
[T_BLOCKSIZE
];
249 #if defined( _WIN32 ) || defined(__CYGWIN__)
250 filefd
= open(realname
, O_RDONLY
| O_BINARY
);
252 filefd
= open(realname
, O_RDONLY
);
262 size
= th_get_size(t
);
263 for (i
= size
; i
> T_BLOCKSIZE
; i
-= T_BLOCKSIZE
)
265 j
= read(filefd
, &block
, T_BLOCKSIZE
);
266 if (j
!= T_BLOCKSIZE
)
270 fprintf(stderr
, "Unexpected size of read data: %d <> %d for file: %s\n",
271 (int)j
, T_BLOCKSIZE
, realname
);
276 if (tar_block_write(t
, &block
) == -1)
282 j
= (size_t)read(filefd
, &block
, (unsigned int)i
);
285 memset(&(block
[i
]), 0, T_BLOCKSIZE
- i
);
286 if (tar_block_write(t
, &block
) == -1)