dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libcmdutils / common / writefile.c
blobd2738f8f473b22d1970e7603fefe4550753cca88
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
40 #include "libcmdutils.h"
43 int
44 writefile(int fi, int fo, char *infile, char *outfile, char *asfile,
45 char *atfile, struct stat *s1p, struct stat *s2p)
47 int mapsize, munmapsize;
48 caddr_t cp;
49 off_t filesize = s1p->st_size;
50 off_t offset;
51 int nbytes;
52 int remains;
53 int n;
54 size_t src_size;
55 size_t targ_size;
56 char *srcbuf;
57 char *targbuf;
59 if (asfile != NULL) {
60 src_size = strlen(infile) + strlen(asfile) +
61 strlen(dgettext(TEXT_DOMAIN, " attribute ")) + 1;
62 } else {
63 src_size = strlen(infile) + 1;
65 srcbuf = malloc(src_size);
66 if (srcbuf == NULL) {
67 (void) fprintf(stderr,
68 dgettext(TEXT_DOMAIN, "could not allocate memory"
69 " for path buffer: "));
70 return (1);
72 if (asfile != NULL) {
73 (void) snprintf(srcbuf, src_size, "%s%s%s",
74 infile, dgettext(TEXT_DOMAIN, " attribute "), asfile);
75 } else {
76 (void) snprintf(srcbuf, src_size, "%s", infile);
79 if (atfile != NULL) {
80 targ_size = strlen(outfile) + strlen(atfile) +
81 strlen(dgettext(TEXT_DOMAIN, " attribute ")) + 1;
82 } else {
83 targ_size = strlen(outfile) + 1;
85 targbuf = malloc(targ_size);
86 if (targbuf == NULL) {
87 (void) fprintf(stderr,
88 dgettext(TEXT_DOMAIN, "could not allocate memory"
89 " for path buffer: "));
90 return (1);
92 if (atfile != NULL) {
93 (void) snprintf(targbuf, targ_size, "%s%s%s",
94 outfile, dgettext(TEXT_DOMAIN, " attribute "), atfile);
95 } else {
96 (void) snprintf(targbuf, targ_size, "%s", outfile);
99 if (S_ISREG(s1p->st_mode) && s1p->st_size > SMALLFILESIZE) {
101 * Determine size of initial mapping. This will determine the
102 * size of the address space chunk we work with. This initial
103 * mapping size will be used to perform munmap() in the future.
105 mapsize = MAXMAPSIZE;
106 if (s1p->st_size < mapsize) mapsize = s1p->st_size;
107 munmapsize = mapsize;
110 * Mmap time!
112 if ((cp = mmap(NULL, mapsize, PROT_READ,
113 MAP_SHARED, fi, (off_t)0)) == MAP_FAILED)
114 mapsize = 0; /* can't mmap today */
115 } else
116 mapsize = 0;
118 if (mapsize != 0) {
119 offset = 0;
121 for (;;) {
122 nbytes = write(fo, cp, mapsize);
124 * if we write less than the mmaped size it's due to a
125 * media error on the input file or out of space on
126 * the output file. So, try again, and look for errno.
128 if ((nbytes >= 0) && (nbytes != (int)mapsize)) {
129 remains = mapsize - nbytes;
130 while (remains > 0) {
131 nbytes = write(fo,
132 cp + mapsize - remains, remains);
133 if (nbytes < 0) {
134 if (errno == ENOSPC)
135 perror(targbuf);
136 else
137 perror(srcbuf);
138 (void) close(fi);
139 (void) close(fo);
140 (void) munmap(cp, munmapsize);
141 if (S_ISREG(s2p->st_mode))
142 (void) unlink(targbuf);
143 return (1);
145 remains -= nbytes;
146 if (remains == 0)
147 nbytes = mapsize;
151 * although the write manual page doesn't specify this
152 * as a possible errno, it is set when the nfs read
153 * via the mmap'ed file is accessed, so report the
154 * problem as a source access problem, not a target file
155 * problem
157 if (nbytes < 0) {
158 if (errno == EACCES)
159 perror(srcbuf);
160 else
161 perror(targbuf);
162 (void) close(fi);
163 (void) close(fo);
164 (void) munmap(cp, munmapsize);
165 if (S_ISREG(s2p->st_mode))
166 (void) unlink(targbuf);
167 free(srcbuf);
168 free(targbuf);
169 return (1);
171 filesize -= nbytes;
172 if (filesize == 0)
173 break;
174 offset += nbytes;
175 if (filesize < mapsize)
176 mapsize = filesize;
177 if (mmap(cp, mapsize, PROT_READ, MAP_SHARED |
178 MAP_FIXED, fi, offset) == MAP_FAILED) {
179 perror(srcbuf);
180 (void) close(fi);
181 (void) close(fo);
182 (void) munmap(cp, munmapsize);
183 if (S_ISREG(s2p->st_mode))
184 (void) unlink(targbuf);
185 free(srcbuf);
186 free(targbuf);
187 return (1);
190 (void) munmap(cp, munmapsize);
191 } else {
192 char buf[SMALLFILESIZE];
193 for (;;) {
194 n = read(fi, buf, sizeof (buf));
195 if (n == 0) {
196 return (0);
197 } else if (n < 0) {
198 (void) close(fi);
199 (void) close(fo);
200 if (S_ISREG(s2p->st_mode))
201 (void) unlink(targbuf);
202 free(srcbuf);
203 free(targbuf);
204 return (1);
205 } else if (write(fo, buf, n) != n) {
206 (void) close(fi);
207 (void) close(fo);
208 if (S_ISREG(s2p->st_mode))
209 (void) unlink(targbuf);
210 free(srcbuf);
211 free(targbuf);
212 return (1);
216 free(srcbuf);
217 free(targbuf);
218 return (0);