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