xref: /onnv-gate/usr/src/lib/libcmdutils/common/writefile.c (revision 6812:febeba71273d)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
21*6812Sraf 
22*6812Sraf /*
23*6812Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*6812Sraf  * Use is subject to license terms.
25*6812Sraf  */
26*6812Sraf 
275331Samw /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
285331Samw /*	  All Rights Reserved  	*/
295331Samw 
305331Samw /*
315331Samw  * University Copyright- Copyright (c) 1982, 1986, 1988
325331Samw  * The Regents of the University of California
335331Samw  * All Rights Reserved
345331Samw  *
355331Samw  * University Acknowledgment- Portions of this document are derived from
365331Samw  * software developed by the University of California, Berkeley, and its
375331Samw  * contributors.
385331Samw  */
395331Samw 
405331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
415331Samw 
425331Samw #include "libcmdutils.h"
435331Samw 
445331Samw 
455331Samw int
writefile(int fi,int fo,char * infile,char * outfile,char * asfile,char * atfile,struct stat * s1p,struct stat * s2p)465331Samw writefile(int fi, int fo, char *infile, char *outfile, char *asfile,
475331Samw     char *atfile, struct stat *s1p, struct stat *s2p)
485331Samw {
495331Samw 	int mapsize, munmapsize;
505331Samw 	caddr_t cp;
515331Samw 	off_t filesize = s1p->st_size;
525331Samw 	off_t offset;
535331Samw 	int nbytes;
545331Samw 	int remains;
555331Samw 	int n;
565331Samw 	size_t src_size;
575331Samw 	size_t targ_size;
585331Samw 	char *srcbuf;
595331Samw 	char *targbuf;
605331Samw 
615331Samw 	if (asfile != NULL) {
625331Samw 		src_size = strlen(infile) + strlen(asfile) +
635331Samw 		    strlen(dgettext(TEXT_DOMAIN, " attribute ")) + 1;
645331Samw 	} else {
655331Samw 		src_size = strlen(infile) + 1;
665331Samw 	}
675331Samw 	srcbuf = malloc(src_size);
685331Samw 	if (srcbuf == NULL) {
695331Samw 		(void) fprintf(stderr,
705331Samw 		    dgettext(TEXT_DOMAIN, "could not allocate memory"
715331Samw 		    " for path buffer: "));
725331Samw 		return (1);
735331Samw 	}
745331Samw 	if (asfile != NULL) {
755331Samw 		(void) snprintf(srcbuf, src_size, "%s%s%s",
765331Samw 		    infile, dgettext(TEXT_DOMAIN, " attribute "), asfile);
775331Samw 	} else {
785331Samw 		(void) snprintf(srcbuf, src_size, "%s", infile);
795331Samw 	}
805331Samw 
815331Samw 	if (atfile != NULL) {
825331Samw 		targ_size = strlen(outfile) + strlen(atfile) +
835331Samw 		    strlen(dgettext(TEXT_DOMAIN, " attribute ")) + 1;
845331Samw 	} else {
855331Samw 		targ_size = strlen(outfile) + 1;
865331Samw 	}
875331Samw 	targbuf = malloc(targ_size);
885331Samw 	if (targbuf == NULL) {
895331Samw 		(void) fprintf(stderr,
905331Samw 		    dgettext(TEXT_DOMAIN, "could not allocate memory"
915331Samw 		    " for path buffer: "));
925331Samw 		return (1);
935331Samw 	}
945331Samw 	if (atfile != NULL) {
955331Samw 		(void) snprintf(targbuf, targ_size, "%s%s%s",
965331Samw 		    outfile, dgettext(TEXT_DOMAIN, " attribute "), atfile);
975331Samw 	} else {
985331Samw 		(void) snprintf(targbuf, targ_size, "%s", outfile);
995331Samw 	}
1005331Samw 
1015331Samw 	if (ISREG(*s1p) && s1p->st_size > SMALLFILESIZE) {
1025331Samw 		/*
1035331Samw 		 * Determine size of initial mapping.  This will determine the
1045331Samw 		 * size of the address space chunk we work with.  This initial
1055331Samw 		 * mapping size will be used to perform munmap() in the future.
1065331Samw 		 */
1075331Samw 		mapsize = MAXMAPSIZE;
1085331Samw 		if (s1p->st_size < mapsize) mapsize = s1p->st_size;
1095331Samw 		munmapsize = mapsize;
1105331Samw 
1115331Samw 		/*
1125331Samw 		 * Mmap time!
1135331Samw 		 */
1145331Samw 		if ((cp = mmap((caddr_t)NULL, mapsize, PROT_READ,
1155331Samw 		    MAP_SHARED, fi, (off_t)0)) == MAP_FAILED)
1165331Samw 			mapsize = 0;   /* can't mmap today */
1175331Samw 	} else
1185331Samw 		mapsize = 0;
1195331Samw 
1205331Samw 	if (mapsize != 0) {
1215331Samw 		offset = 0;
1225331Samw 
1235331Samw 		for (;;) {
1245331Samw 			nbytes = write(fo, cp, mapsize);
1255331Samw 			/*
1265331Samw 			 * if we write less than the mmaped size it's due to a
1275331Samw 			 * media error on the input file or out of space on
1285331Samw 			 * the output file.  So, try again, and look for errno.
1295331Samw 			 */
1305331Samw 			if ((nbytes >= 0) && (nbytes != (int)mapsize)) {
1315331Samw 				remains = mapsize - nbytes;
1325331Samw 				while (remains > 0) {
1335331Samw 					nbytes = write(fo,
1345331Samw 					    cp + mapsize - remains, remains);
1355331Samw 					if (nbytes < 0) {
1365331Samw 						if (errno == ENOSPC)
1375331Samw 							perror(targbuf);
1385331Samw 						else
1395331Samw 							perror(srcbuf);
1405331Samw 						(void) close(fi);
1415331Samw 						(void) close(fo);
1425331Samw 						(void) munmap(cp, munmapsize);
1435331Samw 						if (ISREG(*s2p))
1445331Samw 							(void) unlink(targbuf);
1455331Samw 						return (1);
1465331Samw 					}
1475331Samw 					remains -= nbytes;
1485331Samw 					if (remains == 0)
1495331Samw 						nbytes = mapsize;
1505331Samw 				}
1515331Samw 			}
1525331Samw 			/*
1535331Samw 			 * although the write manual page doesn't specify this
1545331Samw 			 * as a possible errno, it is set when the nfs read
1555331Samw 			 * via the mmap'ed file is accessed, so report the
1565331Samw 			 * problem as a source access problem, not a target file
1575331Samw 			 * problem
1585331Samw 			 */
1595331Samw 			if (nbytes < 0) {
1605331Samw 				if (errno == EACCES)
1615331Samw 					perror(srcbuf);
1625331Samw 				else
1635331Samw 					perror(targbuf);
1645331Samw 				(void) close(fi);
1655331Samw 				(void) close(fo);
1665331Samw 				(void) munmap(cp, munmapsize);
1675331Samw 				if (ISREG(*s2p))
1685331Samw 					(void) unlink(targbuf);
1695331Samw 				if (srcbuf != NULL)
1705331Samw 					free(srcbuf);
1715331Samw 				if (targbuf != NULL)
1725331Samw 					free(targbuf);
1735331Samw 				return (1);
1745331Samw 			}
1755331Samw 			filesize -= nbytes;
1765331Samw 			if (filesize == 0)
1775331Samw 				break;
1785331Samw 			offset += nbytes;
1795331Samw 			if (filesize < mapsize)
1805331Samw 				mapsize = filesize;
1815331Samw 			if (mmap(cp, mapsize, PROT_READ, MAP_SHARED |
1825331Samw 			    MAP_FIXED, fi, offset) == MAP_FAILED) {
1835331Samw 				perror(srcbuf);
1845331Samw 				(void) close(fi);
1855331Samw 				(void) close(fo);
1865331Samw 				(void) munmap(cp, munmapsize);
1875331Samw 				if (ISREG(*s2p))
1885331Samw 					(void) unlink(targbuf);
1895331Samw 				if (srcbuf != NULL)
1905331Samw 					free(srcbuf);
1915331Samw 				if (targbuf != NULL)
1925331Samw 					free(targbuf);
1935331Samw 				return (1);
1945331Samw 			}
1955331Samw 		}
1965331Samw 		(void) munmap(cp, munmapsize);
1975331Samw 	} else {
1985331Samw 		char buf[SMALLFILESIZE];
1995331Samw 		for (;;) {
2005331Samw 			n = read(fi, buf, sizeof (buf));
2015331Samw 			if (n == 0) {
2025331Samw 				return (0);
2035331Samw 			} else if (n < 0) {
2045331Samw 				(void) close(fi);
2055331Samw 				(void) close(fo);
2065331Samw 				if (ISREG(*s2p))
2075331Samw 					(void) unlink(targbuf);
2085331Samw 				if (srcbuf != NULL)
2095331Samw 					free(srcbuf);
2105331Samw 				if (targbuf != NULL)
2115331Samw 					free(targbuf);
2125331Samw 				return (1);
2135331Samw 			} else if (write(fo, buf, n) != n) {
2145331Samw 				(void) close(fi);
2155331Samw 				(void) close(fo);
2165331Samw 				if (ISREG(*s2p))
2175331Samw 					(void) unlink(targbuf);
2185331Samw 				if (srcbuf != NULL)
2195331Samw 					free(srcbuf);
2205331Samw 				if (targbuf != NULL)
2215331Samw 					free(targbuf);
2225331Samw 				return (1);
2235331Samw 			}
2245331Samw 		}
2255331Samw 	}
2265331Samw 	if (srcbuf != NULL)
2275331Samw 		free(srcbuf);
2285331Samw 	if (targbuf != NULL)
2295331Samw 		free(targbuf);
2305331Samw 	return (0);
2315331Samw }
232