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 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