2
* Copyright (c) 2008 Jaakko Heinonen
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer
10
* in this position and unchanged.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
#include <sys/cdefs.h>
29
__FBSDID("$FreeBSD$");
33
#include <sys/types.h>
36
#include <archive_entry.h>
50
/* command line options */
51
static int b_opt; /* use alternative shar binary format */
52
static int r_opt; /* recurse into subdirectories */
53
static char *o_arg; /* output file name */
58
fprintf(stderr, "Usage: shar [-br] [-o filename] file ...\n");
63
* Initialize archive structure and create a shar archive.
65
static struct archive *
70
if ((a = archive_write_new()) == NULL)
71
errx(EXIT_FAILURE, "%s", archive_error_string(a));
74
archive_write_set_format_shar_dump(a);
76
archive_write_set_format_shar(a);
77
archive_write_set_compression_none(a);
79
if (archive_write_open_filename(a, o_arg) != ARCHIVE_OK)
80
errx(EX_CANTCREAT, "%s", archive_error_string(a));
85
/* buffer for file data */
86
static char buffer[32768];
89
* Write file data to an archive entry.
92
shar_write_entry_data(struct archive *a, const int fd)
94
ssize_t bytes_read, bytes_written;
99
bytes_read = read(fd, buffer, sizeof(buffer));
100
while (bytes_read != 0) {
101
if (bytes_read < 0) {
102
archive_set_error(a, errno, "Read failed");
103
return (ARCHIVE_WARN);
105
bytes_written = archive_write_data(a, buffer, bytes_read);
106
if (bytes_written < 0)
107
return (ARCHIVE_WARN);
108
bytes_read = read(fd, buffer, sizeof(buffer));
115
* Write a file to the archive. We have special handling for symbolic links.
118
shar_write_entry(struct archive *a, const char *pathname, const char *accpath,
119
const struct stat *st)
121
struct archive_entry *entry;
123
int ret = ARCHIVE_OK;
126
assert(pathname != NULL);
127
assert(accpath != NULL);
130
entry = archive_entry_new();
132
if (S_ISREG(st->st_mode) && st->st_size > 0) {
134
if ((fd = open(accpath, O_RDONLY)) == -1) {
139
} else if (S_ISLNK(st->st_mode)) {
141
char lnkbuff[PATH_MAX + 1];
143
if ((lnklen = readlink(accpath, lnkbuff, PATH_MAX)) == -1) {
148
lnkbuff[lnklen] = '\0';
149
archive_entry_set_symlink(entry, lnkbuff);
151
archive_entry_copy_stat(entry, st);
152
archive_entry_set_pathname(entry, pathname);
153
if (!S_ISREG(st->st_mode) || st->st_size == 0)
154
archive_entry_set_size(entry, 0);
155
if (archive_write_header(a, entry) != ARCHIVE_OK) {
156
warnx("%s: %s", pathname, archive_error_string(a));
161
if ((ret = shar_write_entry_data(a, fd)) != ARCHIVE_OK)
162
warnx("%s: %s", accpath, archive_error_string(a));
165
archive_entry_free(entry);
173
* Write singe path to the archive. The path can be a regular file, directory
174
* or device. Symbolic links are followed.
177
shar_write_path(struct archive *a, const char *pathname)
182
assert(pathname != NULL);
184
if ((stat(pathname, &st)) == -1) {
185
warn("%s", pathname);
186
return (ARCHIVE_WARN);
189
return (shar_write_entry(a, pathname, pathname, &st));
193
* Write tree to the archive. If pathname is a symbolic link it will be
194
* followed. Other symbolic links are stored as such to the archive.
197
shar_write_tree(struct archive *a, const char *pathname)
200
const struct stat *lst, *st;
206
assert(pathname != NULL);
208
t = tree_open(pathname);
209
for (first = 1; (tree_ret = tree_next(t)); first = 0) {
210
if (tree_ret == TREE_ERROR_DIR) {
211
warnx("%s: %s", tree_current_path(t),
212
strerror(tree_errno(t)));
215
} else if (tree_ret != TREE_REGULAR)
217
if ((lst = tree_current_lstat(t)) == NULL) {
218
warn("%s", tree_current_path(t));
223
* If the symlink was given on command line then
224
* follow it rather than write it as symlink.
226
if (first && S_ISLNK(lst->st_mode)) {
227
if ((st = tree_current_stat(t)) == NULL) {
228
warn("%s", tree_current_path(t));
235
if (shar_write_entry(a, tree_current_path(t),
236
tree_current_access_path(t), st) != ARCHIVE_OK)
244
return ((error != 0) ? ARCHIVE_WARN : ARCHIVE_OK);
248
* Create a shar archive and write files/trees into it.
251
shar_write(char **fn, size_t nfn)
262
for (i = 0; i < nfn; i++) {
264
if (shar_write_tree(a, fn[i]) != ARCHIVE_OK)
267
if (shar_write_path(a, fn[i]) != ARCHIVE_OK)
272
if (archive_write_finish(a) != ARCHIVE_OK)
273
errx(EXIT_FAILURE, "%s", archive_error_string(a));
276
warnx("Error exit delayed from previous errors.");
282
main(int argc, char **argv)
286
while ((opt = getopt(argc, argv, "bro:")) != -1) {
308
if (shar_write(argv, argc) != 0)