Import libarchive and bsdtar. The default tar (/usr/bin/tar) can be choosen
[dragonfly.git] / contrib / libarchive / archive_write_open_fd.c
1 /*-
2  * Copyright (c) 2003-2004 Tim Kientzle
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
14  *
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.
25  */
26
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_fd.c,v 1.4 2004/10/17 23:47:30 kientzle Exp $");
29
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include "archive.h"
37 #include "archive_private.h"
38
39 struct write_fd_data {
40         off_t           offset;
41         int             fd;
42 };
43
44 static int      file_close(struct archive *, void *);
45 static int      file_open(struct archive *, void *);
46 static ssize_t  file_write(struct archive *, void *, void *buff, size_t);
47
48 int
49 archive_write_open_fd(struct archive *a, int fd)
50 {
51         struct write_fd_data *mine;
52
53         mine = malloc(sizeof(*mine));
54         if (mine == NULL) {
55                 archive_set_error(a, ENOMEM, "No memory");
56                 return (ARCHIVE_FATAL);
57         }
58         mine->fd = fd;
59         return (archive_write_open(a, mine,
60                     file_open, file_write, file_close));
61 }
62
63 static int
64 file_open(struct archive *a, void *client_data)
65 {
66         struct write_fd_data *mine;
67         struct stat st, *pst;
68
69         pst = NULL;
70         mine = client_data;
71
72         /*
73          * If client hasn't explicitly set the last block handling,
74          * then set it here: If the output is a block or character
75          * device, pad the last block, otherwise leave it unpadded.
76          */
77         if (mine->fd >= 0 && a->bytes_in_last_block < 0) {
78                 /* Last block will be fully padded. */
79                 if (fstat(mine->fd, &st) == 0) {
80                         pst = &st;
81                         if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
82                             S_ISFIFO(st.st_mode))
83                                 archive_write_set_bytes_in_last_block(a, 0);
84                         else
85                                 archive_write_set_bytes_in_last_block(a, 1);
86                 }
87         }
88
89         if (mine->fd == 1) {
90                 if (a->bytes_in_last_block < 0) /* Still default? */
91                         /* Last block will be fully padded. */
92                         archive_write_set_bytes_in_last_block(a, 0);
93         }
94
95         if (mine->fd < 0) {
96                 archive_set_error(a, errno, "Failed to open");
97                 return (ARCHIVE_FATAL);
98         }
99
100         if (pst == NULL && fstat(mine->fd, &st) == 0)
101                 pst = &st;
102         if (pst == NULL) {
103                 archive_set_error(a, errno, "Couldn't stat fd %d", mine->fd);
104                 return (ARCHIVE_FATAL);
105         }
106
107         return (ARCHIVE_OK);
108 }
109
110 static ssize_t
111 file_write(struct archive *a, void *client_data, void *buff, size_t length)
112 {
113         struct write_fd_data    *mine;
114         ssize_t bytesWritten;
115
116         mine = client_data;
117         bytesWritten = write(mine->fd, buff, length);
118         if (bytesWritten <= 0) {
119                 archive_set_error(a, errno, "Write error");
120                 return (-1);
121         }
122         return (bytesWritten);
123 }
124
125 static int
126 file_close(struct archive *a, void *client_data)
127 {
128         struct write_fd_data    *mine = client_data;
129
130         (void)a; /* UNUSED */
131         free(mine);
132         return (ARCHIVE_OK);
133 }