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
20 #include <sys/param.h>
21 #include <sys/types.h>
38 typedef struct tar_dev tar_dev_t
;
43 char ti_name
[MAXPATHLEN
];
45 typedef struct tar_ino tar_ino_t
;
48 /* free memory associated with a tar_dev_t */
50 tar_dev_free(tar_dev_t
*tdp
)
52 libtar_hash_free(tdp
->td_h
, free
);
57 /* appends a file to the tar archive */
59 tar_append_file(TAR
*t
, const char *realname
, const char *savename
)
66 char path
[MAXPATHLEN
];
69 printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
70 "savename=\"%s\")\n", t
, t
->pathname
, realname
,
71 (savename
? savename
: "[NULL]"));
74 if (lstat(realname
, &s
) != 0)
82 /* set header block */
84 puts(" tar_append_file(): setting header block...");
86 memset(&(t
->th_buf
), 0, sizeof(struct tar_header
));
87 th_set_from_stat(t
, &s
);
89 /* set the header path */
91 puts(" tar_append_file(): setting header path...");
93 th_set_path(t
, (savename
? savename
: realname
));
95 /* check if it's a hardlink */
97 puts(" tar_append_file(): checking inode cache for hardlink...");
99 libtar_hashptr_reset(&hp
);
100 if (libtar_hash_getkey(t
->h
, &hp
, &(s
.st_dev
),
101 (libtar_matchfunc_t
)dev_match
) != 0)
102 td
= (tar_dev_t
*)libtar_hashptr_data(&hp
);
106 printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
107 major(s
.st_dev
), minor(s
.st_dev
));
109 td
= (tar_dev_t
*)calloc(1, sizeof(tar_dev_t
));
110 td
->td_dev
= s
.st_dev
;
111 td
->td_h
= libtar_hash_new(256, (libtar_hashfunc_t
)ino_hash
);
112 if (td
->td_h
== NULL
)
114 if (libtar_hash_add(t
->h
, td
) == -1)
117 libtar_hashptr_reset(&hp
);
118 if (libtar_hash_getkey(td
->td_h
, &hp
, &(s
.st_ino
),
119 (libtar_matchfunc_t
)ino_match
) != 0)
121 ti
= (tar_ino_t
*)libtar_hashptr_data(&hp
);
123 printf(" tar_append_file(): encoding hard link \"%s\" "
124 "to \"%s\"...\n", realname
, ti
->ti_name
);
126 t
->th_buf
.typeflag
= LNKTYPE
;
127 th_set_link(t
, ti
->ti_name
);
132 printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
133 "(\"%s\")...\n", major(s
.st_dev
), minor(s
.st_dev
),
136 ti
= (tar_ino_t
*)calloc(1, sizeof(tar_ino_t
));
139 ti
->ti_ino
= s
.st_ino
;
140 snprintf(ti
->ti_name
, sizeof(ti
->ti_name
), "%s",
141 savename
? savename
: realname
);
142 libtar_hash_add(td
->td_h
, ti
);
145 /* check if it's a symlink */
148 i
= readlink(realname
, path
, sizeof(path
));
155 printf(" tar_append_file(): encoding symlink \"%s\" -> "
156 "\"%s\"...\n", realname
, path
);
158 th_set_link(t
, path
);
161 /* print file info */
162 if (t
->options
& TAR_VERBOSE
)
166 puts(" tar_append_file(): writing header");
169 if (th_write(t
) != 0)
172 printf("t->fd = %d\n", t
->fd
);
177 puts(" tar_append_file(): back from th_write()");
180 /* if it's a regular file, write the contents as well */
181 if (TH_ISREG(t
) && tar_append_regfile(t
, realname
) != 0)
188 /* write EOF indicator */
190 tar_append_eof(TAR
*t
)
193 char block
[T_BLOCKSIZE
];
195 memset(&block
, 0, T_BLOCKSIZE
);
196 for (j
= 0; j
< 2; j
++)
198 i
= tar_block_write(t
, &block
);
199 if (i
!= T_BLOCKSIZE
)
211 /* add file contents to a tarchive */
213 tar_append_regfile(TAR
*t
, const char *realname
)
215 char block
[T_BLOCKSIZE
];
221 #if defined(O_BINARY)
222 filefd
= open(realname
, O_RDONLY
|O_BINARY
);
224 filefd
= open(realname
, O_RDONLY
);
234 size
= th_get_size(t
);
235 for (i
= size
; i
> T_BLOCKSIZE
; i
-= T_BLOCKSIZE
)
237 j
= read(filefd
, &block
, T_BLOCKSIZE
);
238 if (j
!= T_BLOCKSIZE
)
244 if (tar_block_write(t
, &block
) == -1)
250 j
= read(filefd
, &block
, i
);
253 memset(&(block
[i
]), 0, T_BLOCKSIZE
- i
);
254 if (tar_block_write(t
, &block
) == -1)