2 * Copyright (c) 2003-2007 Tim Kientzle
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 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_open_filename.c,v 1.20 2008/02/19 05:46:58 kientzle Exp $");
29 #ifdef HAVE_SYS_STAT_H
54 struct write_file_data
{
59 static int file_close(struct archive
*, void *);
60 static int file_open(struct archive
*, void *);
61 static ssize_t
file_write(struct archive
*, void *, const void *buff
, size_t);
64 archive_write_open_file(struct archive
*a
, const char *filename
)
66 return (archive_write_open_filename(a
, filename
));
70 archive_write_open_filename(struct archive
*a
, const char *filename
)
72 struct write_file_data
*mine
;
74 if (filename
== NULL
|| filename
[0] == '\0') {
75 mine
= (struct write_file_data
*)malloc(sizeof(*mine
));
77 archive_set_error(a
, ENOMEM
, "No memory");
78 return (ARCHIVE_FATAL
);
80 mine
->filename
[0] = '\0'; /* Record that we're using stdout. */
82 mine
= (struct write_file_data
*)malloc(sizeof(*mine
) + strlen(filename
));
84 archive_set_error(a
, ENOMEM
, "No memory");
85 return (ARCHIVE_FATAL
);
87 strcpy(mine
->filename
, filename
);
90 return (archive_write_open(a
, mine
,
91 file_open
, file_write
, file_close
));
95 file_open(struct archive
*a
, void *client_data
)
98 struct write_file_data
*mine
;
101 mine
= (struct write_file_data
*)client_data
;
102 flags
= O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
;
107 if (mine
->filename
[0] != '\0') {
108 mine
->fd
= open(mine
->filename
, flags
, 0666);
110 archive_set_error(a
, errno
, "Failed to open '%s'",
112 return (ARCHIVE_FATAL
);
116 * NULL filename is stdout.
119 /* By default, pad archive when writing to stdout. */
120 if (archive_write_get_bytes_in_last_block(a
) < 0)
121 archive_write_set_bytes_in_last_block(a
, 0);
124 if (fstat(mine
->fd
, &st
) != 0) {
125 archive_set_error(a
, errno
, "Couldn't stat '%s'",
127 return (ARCHIVE_FATAL
);
131 * Set up default last block handling.
133 if (archive_write_get_bytes_in_last_block(a
) < 0) {
134 if (S_ISCHR(st
.st_mode
) || S_ISBLK(st
.st_mode
) ||
135 S_ISFIFO(st
.st_mode
))
136 /* Pad last block when writing to device or FIFO. */
137 archive_write_set_bytes_in_last_block(a
, 0);
139 /* Don't pad last block otherwise. */
140 archive_write_set_bytes_in_last_block(a
, 1);
144 * If the output file is a regular file, don't add it to
145 * itself. If it's a device file, it's okay to add the device
146 * entry to the output archive.
148 if (S_ISREG(st
.st_mode
))
149 archive_write_set_skip_file(a
, st
.st_dev
, st
.st_ino
);
155 file_write(struct archive
*a
, void *client_data
, const void *buff
, size_t length
)
157 struct write_file_data
*mine
;
158 ssize_t bytesWritten
;
160 mine
= (struct write_file_data
*)client_data
;
161 bytesWritten
= write(mine
->fd
, buff
, length
);
162 if (bytesWritten
<= 0) {
163 archive_set_error(a
, errno
, "Write error");
166 return (bytesWritten
);
170 file_close(struct archive
*a
, void *client_data
)
172 struct write_file_data
*mine
= (struct write_file_data
*)client_data
;
174 (void)a
; /* UNUSED */
175 if (mine
->filename
[0] != '\0')