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
18 #include <sys/param.h>
19 #include <sys/types.h>
36 typedef struct tar_dev tar_dev_t
;
41 char ti_name
[MAXPATHLEN
];
43 typedef struct tar_ino tar_ino_t
;
46 /* free memory associated with a tar_dev_t */
48 tar_dev_free(tar_dev_t
*tdp
)
50 libtar_hash_free(tdp
->td_h
, free
);
55 /* appends a file to the tar archive */
57 tar_append_file(TAR
*t
, const char *realname
, const char *savename
)
64 char path
[MAXPATHLEN
];
67 printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
68 "savename=\"%s\")\n", t
, t
->pathname
, realname
,
69 (savename
? savename
: "[NULL]"));
72 if (lstat(realname
, &s
) != 0)
80 /* set header block */
82 puts(" tar_append_file(): setting header block...");
84 memset(&(t
->th_buf
), 0, sizeof(struct tar_header
));
85 th_set_from_stat(t
, &s
);
87 /* set the header path */
89 puts(" tar_append_file(): setting header path...");
91 th_set_path(t
, (savename
? savename
: realname
));
93 /* check if it's a hardlink */
95 puts(" tar_append_file(): checking inode cache for hardlink...");
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
);
104 printf("+++ adding hash for device (0x%lx, 0x%lx)...\n",
105 major(s
.st_dev
), minor(s
.st_dev
));
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
)
112 if (libtar_hash_add(t
->h
, td
) == -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
);
121 printf(" tar_append_file(): encoding hard link \"%s\" "
122 "to \"%s\"...\n", realname
, ti
->ti_name
);
124 t
->th_buf
.typeflag
= LNKTYPE
;
125 th_set_link(t
, ti
->ti_name
);
130 printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
131 "(\"%s\")...\n", major(s
.st_dev
), minor(s
.st_dev
),
134 ti
= (tar_ino_t
*)calloc(1, sizeof(tar_ino_t
));
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 */
146 i
= readlink(realname
, path
, sizeof(path
));
153 printf(" tar_append_file(): encoding symlink \"%s\" -> "
154 "\"%s\"...\n", realname
, path
);
156 th_set_link(t
, path
);
159 /* print file info */
160 if (t
->options
& TAR_VERBOSE
)
164 puts(" tar_append_file(): writing header");
167 if (th_write(t
) != 0)
170 printf("t->fd = %d\n", t
->fd
);
175 puts(" tar_append_file(): back from th_write()");
178 /* if it's a regular file, write the contents as well */
179 if (TH_ISREG(t
) && tar_append_regfile(t
, realname
) != 0)
186 /* write EOF indicator */
188 tar_append_eof(TAR
*t
)
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
)
209 /* add file contents to a tarchive */
211 tar_append_regfile(TAR
*t
, const char *realname
)
213 char block
[T_BLOCKSIZE
];
218 filefd
= open(realname
, O_RDONLY
);
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
)
237 if (tar_block_write(t
, &block
) == -1)
243 j
= read(filefd
, &block
, i
);
246 memset(&(block
[i
]), 0, T_BLOCKSIZE
- i
);
247 if (tar_block_write(t
, &block
) == -1)