archive_write_open_filename.c revision 228759
1172106Srwatson/*-
2172106Srwatson * Copyright (c) 2003-2007 Tim Kientzle
3172106Srwatson * All rights reserved.
4172106Srwatson *
5172106Srwatson * Redistribution and use in source and binary forms, with or without
6172106Srwatson * modification, are permitted provided that the following conditions
7172106Srwatson * are met:
8172106Srwatson * 1. Redistributions of source code must retain the above copyright
9172106Srwatson *    notice, this list of conditions and the following disclaimer.
10172106Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11172106Srwatson *    notice, this list of conditions and the following disclaimer in the
12172106Srwatson *    documentation and/or other materials provided with the distribution.
13172106Srwatson *
14172106Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15172106Srwatson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16172106Srwatson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17172106Srwatson * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18172106Srwatson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19172106Srwatson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20172106Srwatson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21172106Srwatson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22172106Srwatson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23172106Srwatson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24172106Srwatson */
25172106Srwatson
26172106Srwatson#include "archive_platform.h"
27172106Srwatson__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_filename.c 191165 2009-04-17 00:39:35Z kientzle $");
28172106Srwatson
29172106Srwatson#ifdef HAVE_SYS_STAT_H
30172106Srwatson#include <sys/stat.h>
31172106Srwatson#endif
32172106Srwatson#ifdef HAVE_ERRNO_H
33172106Srwatson#include <errno.h>
34172106Srwatson#endif
35172106Srwatson#ifdef HAVE_FCNTL_H
36172106Srwatson#include <fcntl.h>
37172106Srwatson#endif
38172106Srwatson#ifdef HAVE_STDLIB_H
39172106Srwatson#include <stdlib.h>
40172106Srwatson#endif
41172106Srwatson#ifdef HAVE_STRING_H
42172106Srwatson#include <string.h>
43172106Srwatson#endif
44172106Srwatson#ifdef HAVE_UNISTD_H
45172106Srwatson#include <unistd.h>
46172106Srwatson#endif
47172106Srwatson
48172106Srwatson#include "archive.h"
49172106Srwatson
50172106Srwatson#ifndef O_BINARY
51172106Srwatson#define O_BINARY 0
52172106Srwatson#endif
53172106Srwatson
54172106Srwatsonstruct write_file_data {
55172106Srwatson	int		fd;
56172106Srwatson	char		filename[1];
57172106Srwatson};
58172106Srwatson
59172106Srwatsonstatic int	file_close(struct archive *, void *);
60172106Srwatsonstatic int	file_open(struct archive *, void *);
61172106Srwatsonstatic ssize_t	file_write(struct archive *, void *, const void *buff, size_t);
62172106Srwatson
63172106Srwatsonint
64172106Srwatsonarchive_write_open_file(struct archive *a, const char *filename)
65172106Srwatson{
66172106Srwatson	return (archive_write_open_filename(a, filename));
67172106Srwatson}
68172106Srwatson
69172106Srwatsonint
70172106Srwatsonarchive_write_open_filename(struct archive *a, const char *filename)
71172106Srwatson{
72172106Srwatson	struct write_file_data *mine;
73172106Srwatson
74172106Srwatson	if (filename == NULL || filename[0] == '\0')
75172106Srwatson		return (archive_write_open_fd(a, 1));
76172106Srwatson
77172106Srwatson	mine = (struct write_file_data *)malloc(sizeof(*mine) + strlen(filename));
78172106Srwatson	if (mine == NULL) {
79172106Srwatson		archive_set_error(a, ENOMEM, "No memory");
80172106Srwatson		return (ARCHIVE_FATAL);
81172106Srwatson	}
82172106Srwatson	strcpy(mine->filename, filename);
83172106Srwatson	mine->fd = -1;
84172106Srwatson	return (archive_write_open(a, mine,
85172106Srwatson		file_open, file_write, file_close));
86172106Srwatson}
87172106Srwatson
88172106Srwatsonstatic int
89172106Srwatsonfile_open(struct archive *a, void *client_data)
90172106Srwatson{
91172106Srwatson	int flags;
92172106Srwatson	struct write_file_data *mine;
93172106Srwatson	struct stat st;
94172106Srwatson
95172106Srwatson	mine = (struct write_file_data *)client_data;
96172106Srwatson	flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY;
97172106Srwatson
98172106Srwatson	/*
99172106Srwatson	 * Open the file.
100172106Srwatson	 */
101172106Srwatson	mine->fd = open(mine->filename, flags, 0666);
102172106Srwatson	if (mine->fd < 0) {
103172106Srwatson		archive_set_error(a, errno, "Failed to open '%s'",
104172106Srwatson		    mine->filename);
105172106Srwatson		return (ARCHIVE_FATAL);
106172106Srwatson	}
107172106Srwatson
108172106Srwatson	if (fstat(mine->fd, &st) != 0) {
109172106Srwatson               archive_set_error(a, errno, "Couldn't stat '%s'",
110                   mine->filename);
111               return (ARCHIVE_FATAL);
112	}
113
114	/*
115	 * Set up default last block handling.
116	 */
117	if (archive_write_get_bytes_in_last_block(a) < 0) {
118		if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ||
119		    S_ISFIFO(st.st_mode))
120			/* Pad last block when writing to device or FIFO. */
121			archive_write_set_bytes_in_last_block(a, 0);
122		else
123			/* Don't pad last block otherwise. */
124			archive_write_set_bytes_in_last_block(a, 1);
125	}
126
127	/*
128	 * If the output file is a regular file, don't add it to
129	 * itself.  If it's a device file, it's okay to add the device
130	 * entry to the output archive.
131	 */
132	if (S_ISREG(st.st_mode))
133		archive_write_set_skip_file(a, st.st_dev, st.st_ino);
134
135	return (ARCHIVE_OK);
136}
137
138static ssize_t
139file_write(struct archive *a, void *client_data, const void *buff, size_t length)
140{
141	struct write_file_data	*mine;
142	ssize_t	bytesWritten;
143
144	mine = (struct write_file_data *)client_data;
145	for (;;) {
146		bytesWritten = write(mine->fd, buff, length);
147		if (bytesWritten <= 0) {
148			if (errno == EINTR)
149				continue;
150			archive_set_error(a, errno, "Write error");
151			return (-1);
152		}
153		return (bytesWritten);
154	}
155}
156
157static int
158file_close(struct archive *a, void *client_data)
159{
160	struct write_file_data	*mine = (struct write_file_data *)client_data;
161
162	(void)a; /* UNUSED */
163	close(mine->fd);
164	free(mine);
165	return (ARCHIVE_OK);
166}
167