1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*5c51f124SMoriah Waterland /* All Rights Reserved */ 29*5c51f124SMoriah Waterland 30*5c51f124SMoriah Waterland 31*5c51f124SMoriah Waterland 32*5c51f124SMoriah Waterland #include <stdio.h> 33*5c51f124SMoriah Waterland #include <string.h> 34*5c51f124SMoriah Waterland #include <errno.h> 35*5c51f124SMoriah Waterland #include <stdlib.h> 36*5c51f124SMoriah Waterland #include <unistd.h> 37*5c51f124SMoriah Waterland #include <libgen.h> 38*5c51f124SMoriah Waterland #include <fcntl.h> 39*5c51f124SMoriah Waterland #include <sys/types.h> 40*5c51f124SMoriah Waterland #include <utime.h> 41*5c51f124SMoriah Waterland #include <sys/stat.h> 42*5c51f124SMoriah Waterland #include <locale.h> 43*5c51f124SMoriah Waterland #include <libintl.h> 44*5c51f124SMoriah Waterland #include <sys/mman.h> 45*5c51f124SMoriah Waterland 46*5c51f124SMoriah Waterland /* 47*5c51f124SMoriah Waterland * consolidation pkg command library includes 48*5c51f124SMoriah Waterland */ 49*5c51f124SMoriah Waterland 50*5c51f124SMoriah Waterland #include "pkglib.h" 51*5c51f124SMoriah Waterland 52*5c51f124SMoriah Waterland /* 53*5c51f124SMoriah Waterland * local pkg command library includes 54*5c51f124SMoriah Waterland */ 55*5c51f124SMoriah Waterland #include "libinst.h" 56*5c51f124SMoriah Waterland #include "libadm.h" 57*5c51f124SMoriah Waterland #include "messages.h" 58*5c51f124SMoriah Waterland 59*5c51f124SMoriah Waterland /* 60*5c51f124SMoriah Waterland * MAXMAPSIZE controls the largest mapping to use at a time; please refer 61*5c51f124SMoriah Waterland * to mmap(2) for details of how this size is incremented and rounded; briefly 62*5c51f124SMoriah Waterland * each mapping request has an additional 16Kb added to it - mappings over 63*5c51f124SMoriah Waterland * 4Mb will be rounded to a 4Mb boundary - thus if there were 8mb, adding 64*5c51f124SMoriah Waterland * in the 16Kb overhead the mapping would use another 4Mb-16kb - that is 65*5c51f124SMoriah Waterland * why there is 16Kb subtracted from the total 66*5c51f124SMoriah Waterland */ 67*5c51f124SMoriah Waterland 68*5c51f124SMoriah Waterland #define MAXMAPSIZE (1024*1024*8)-(1024*16) /* map at most 8MB */ 69*5c51f124SMoriah Waterland #define SMALLFILESIZE (32*1024) /* dont mmap files less than 32kb */ 70*5c51f124SMoriah Waterland 71*5c51f124SMoriah Waterland /* 72*5c51f124SMoriah Waterland * Name: copyF 73*5c51f124SMoriah Waterland * Description: fast copy of file - use mmap()/write() loop if possible 74*5c51f124SMoriah Waterland * Arguments: char *srcPath - name of source file to copy from 75*5c51f124SMoriah Waterland * char *dstPath - name of target file to copy to 76*5c51f124SMoriah Waterland * time_t a_mytime: control setting of access/modification times: 77*5c51f124SMoriah Waterland * == 0 - replicate source file access/modification times 78*5c51f124SMoriah Waterland * != 0 - use specified time for access/modification times 79*5c51f124SMoriah Waterland * Returns: int 80*5c51f124SMoriah Waterland * == 0 - successful 81*5c51f124SMoriah Waterland * != 0 - failure 82*5c51f124SMoriah Waterland */ 83*5c51f124SMoriah Waterland 84*5c51f124SMoriah Waterland int 85*5c51f124SMoriah Waterland copyf(char *a_srcPath, char *a_dstPath, time_t a_mytime) 86*5c51f124SMoriah Waterland { 87*5c51f124SMoriah Waterland struct stat srcStatbuf; 88*5c51f124SMoriah Waterland struct utimbuf times; 89*5c51f124SMoriah Waterland int srcFd; 90*5c51f124SMoriah Waterland int dstFd; 91*5c51f124SMoriah Waterland int status; 92*5c51f124SMoriah Waterland char *pt; 93*5c51f124SMoriah Waterland 94*5c51f124SMoriah Waterland /* open source file for reading */ 95*5c51f124SMoriah Waterland 96*5c51f124SMoriah Waterland srcFd = open(a_srcPath, O_RDONLY, 0); 97*5c51f124SMoriah Waterland if (srcFd < 0) { 98*5c51f124SMoriah Waterland progerr(ERR_OPEN_READ, a_srcPath, errno, strerror(errno)); 99*5c51f124SMoriah Waterland return (-1); 100*5c51f124SMoriah Waterland } 101*5c51f124SMoriah Waterland 102*5c51f124SMoriah Waterland /* obtain file status of source file */ 103*5c51f124SMoriah Waterland 104*5c51f124SMoriah Waterland if (fstat(srcFd, &srcStatbuf) != 0) { 105*5c51f124SMoriah Waterland progerr(ERR_FSTAT, srcFd, a_srcPath, errno, strerror(errno)); 106*5c51f124SMoriah Waterland (void) close(srcFd); 107*5c51f124SMoriah Waterland return (-1); 108*5c51f124SMoriah Waterland } 109*5c51f124SMoriah Waterland 110*5c51f124SMoriah Waterland /* open target file for writing */ 111*5c51f124SMoriah Waterland 112*5c51f124SMoriah Waterland dstFd = open(a_dstPath, O_WRONLY | O_TRUNC | O_CREAT, 113*5c51f124SMoriah Waterland srcStatbuf.st_mode); 114*5c51f124SMoriah Waterland if (dstFd < 0) { 115*5c51f124SMoriah Waterland /* create directory structure if missing */ 116*5c51f124SMoriah Waterland pt = a_dstPath; 117*5c51f124SMoriah Waterland while (pt = strchr(pt+1, '/')) { 118*5c51f124SMoriah Waterland *pt = '\0'; 119*5c51f124SMoriah Waterland if (isdir(a_dstPath)) { 120*5c51f124SMoriah Waterland if (mkdir(a_dstPath, 0755)) { 121*5c51f124SMoriah Waterland progerr(ERR_NODIR, a_dstPath, 122*5c51f124SMoriah Waterland errno, strerror(errno)); 123*5c51f124SMoriah Waterland *pt = '/'; 124*5c51f124SMoriah Waterland (void) close(srcFd); 125*5c51f124SMoriah Waterland return (-1); 126*5c51f124SMoriah Waterland } 127*5c51f124SMoriah Waterland } 128*5c51f124SMoriah Waterland *pt = '/'; 129*5c51f124SMoriah Waterland } 130*5c51f124SMoriah Waterland 131*5c51f124SMoriah Waterland /* attempt to create target file again */ 132*5c51f124SMoriah Waterland dstFd = open(a_dstPath, O_WRONLY | O_TRUNC | O_CREAT, 133*5c51f124SMoriah Waterland srcStatbuf.st_mode); 134*5c51f124SMoriah Waterland if (dstFd < 0) { 135*5c51f124SMoriah Waterland progerr(ERR_OPEN_WRITE, a_dstPath, errno, 136*5c51f124SMoriah Waterland strerror(errno)); 137*5c51f124SMoriah Waterland (void) close(srcFd); 138*5c51f124SMoriah Waterland return (-1); 139*5c51f124SMoriah Waterland } 140*5c51f124SMoriah Waterland } 141*5c51f124SMoriah Waterland 142*5c51f124SMoriah Waterland /* 143*5c51f124SMoriah Waterland * source and target files are open: copy data 144*5c51f124SMoriah Waterland */ 145*5c51f124SMoriah Waterland 146*5c51f124SMoriah Waterland status = copyFile(srcFd, dstFd, a_srcPath, a_dstPath, &srcStatbuf, 0); 147*5c51f124SMoriah Waterland 148*5c51f124SMoriah Waterland (void) close(srcFd); 149*5c51f124SMoriah Waterland (void) close(dstFd); 150*5c51f124SMoriah Waterland 151*5c51f124SMoriah Waterland /* 152*5c51f124SMoriah Waterland * determine how to set access/modification times for target: 153*5c51f124SMoriah Waterland * -- a_mytime == 0: replicate source file access/modification times 154*5c51f124SMoriah Waterland * -- otherwise: use a_mytime for file access/modification times 155*5c51f124SMoriah Waterland */ 156*5c51f124SMoriah Waterland 157*5c51f124SMoriah Waterland if (a_mytime == 0) { 158*5c51f124SMoriah Waterland times.actime = srcStatbuf.st_atime; 159*5c51f124SMoriah Waterland times.modtime = srcStatbuf.st_mtime; 160*5c51f124SMoriah Waterland } else { 161*5c51f124SMoriah Waterland times.actime = a_mytime; 162*5c51f124SMoriah Waterland times.modtime = a_mytime; 163*5c51f124SMoriah Waterland } 164*5c51f124SMoriah Waterland 165*5c51f124SMoriah Waterland /* set access/modification times for target */ 166*5c51f124SMoriah Waterland 167*5c51f124SMoriah Waterland if (utime(a_dstPath, ×) != 0) { 168*5c51f124SMoriah Waterland progerr(ERR_MODTIM, a_dstPath, errno, strerror(errno)); 169*5c51f124SMoriah Waterland return (-1); 170*5c51f124SMoriah Waterland } 171*5c51f124SMoriah Waterland 172*5c51f124SMoriah Waterland /* return error if copy failed */ 173*5c51f124SMoriah Waterland 174*5c51f124SMoriah Waterland if (status != 0) { 175*5c51f124SMoriah Waterland progerr(ERR_READ, a_srcPath, errno, strerror(errno)); 176*5c51f124SMoriah Waterland return (-1); 177*5c51f124SMoriah Waterland } 178*5c51f124SMoriah Waterland 179*5c51f124SMoriah Waterland /* success! */ 180*5c51f124SMoriah Waterland 181*5c51f124SMoriah Waterland return (0); 182*5c51f124SMoriah Waterland } 183*5c51f124SMoriah Waterland 184*5c51f124SMoriah Waterland /* 185*5c51f124SMoriah Waterland * Name: copyFile 186*5c51f124SMoriah Waterland * Description: fast copy of file - use mmap()/write() loop if possible 187*5c51f124SMoriah Waterland * Arguments: int srcFd - file descriptor open on source file 188*5c51f124SMoriah Waterland * int dstFd - file descriptor open on target file 189*5c51f124SMoriah Waterland * char *srcPath - name of source file (for error messages) 190*5c51f124SMoriah Waterland * char *dstPath - name of target file (for error messages) 191*5c51f124SMoriah Waterland * struct stat *a_srcStatbuf - stat structure for source file 192*5c51f124SMoriah Waterland * long a_iosize - preferred io size for read/write loop 193*5c51f124SMoriah Waterland * Returns: int 194*5c51f124SMoriah Waterland * == 0 - successful 195*5c51f124SMoriah Waterland * != 0 - failure 196*5c51f124SMoriah Waterland */ 197*5c51f124SMoriah Waterland 198*5c51f124SMoriah Waterland int 199*5c51f124SMoriah Waterland copyFile(int a_srcFd, int a_dstFd, char *a_srcPath, char *a_dstPath, 200*5c51f124SMoriah Waterland struct stat *a_srcStatbuf, long a_iosize) 201*5c51f124SMoriah Waterland { 202*5c51f124SMoriah Waterland caddr_t cp; 203*5c51f124SMoriah Waterland off_t filesize = a_srcStatbuf->st_size; 204*5c51f124SMoriah Waterland size_t mapsize = 0; 205*5c51f124SMoriah Waterland size_t munmapsize = 0; 206*5c51f124SMoriah Waterland off_t offset = 0; 207*5c51f124SMoriah Waterland 208*5c51f124SMoriah Waterland echoDebug(DBG_COPY_FILE, a_srcPath, a_dstPath); 209*5c51f124SMoriah Waterland 210*5c51f124SMoriah Waterland /* 211*5c51f124SMoriah Waterland * if the source is a regular file and is not "too small", then cause 212*5c51f124SMoriah Waterland * the file to be mapped into memory 213*5c51f124SMoriah Waterland */ 214*5c51f124SMoriah Waterland 215*5c51f124SMoriah Waterland if (S_ISREG(a_srcStatbuf->st_mode) && (filesize > SMALLFILESIZE)) { 216*5c51f124SMoriah Waterland /* 217*5c51f124SMoriah Waterland * Determine size of initial mapping. This will determine the 218*5c51f124SMoriah Waterland * size of the address space chunk we work with. This initial 219*5c51f124SMoriah Waterland * mapping size will be used to perform munmap() in the future. 220*5c51f124SMoriah Waterland */ 221*5c51f124SMoriah Waterland 222*5c51f124SMoriah Waterland mapsize = MAXMAPSIZE; 223*5c51f124SMoriah Waterland if (filesize < mapsize) { 224*5c51f124SMoriah Waterland mapsize = filesize; 225*5c51f124SMoriah Waterland } 226*5c51f124SMoriah Waterland 227*5c51f124SMoriah Waterland /* 228*5c51f124SMoriah Waterland * remember size of mapping to "unmap" - if the source file 229*5c51f124SMoriah Waterland * exceeds MAXMAPSIZE bytes, then the final mapping of the 230*5c51f124SMoriah Waterland * source file will be less than MAXMAPSIZE, and we need to 231*5c51f124SMoriah Waterland * make sure that the entire mapping is unmapped when done. 232*5c51f124SMoriah Waterland */ 233*5c51f124SMoriah Waterland 234*5c51f124SMoriah Waterland munmapsize = mapsize; 235*5c51f124SMoriah Waterland 236*5c51f124SMoriah Waterland /* map the first segment of the source into memory */ 237*5c51f124SMoriah Waterland 238*5c51f124SMoriah Waterland cp = mmap((caddr_t)NULL, mapsize, PROT_READ, 239*5c51f124SMoriah Waterland (MAP_SHARED|MAP_ALIGN), a_srcFd, (off_t)0); 240*5c51f124SMoriah Waterland if (cp == MAP_FAILED) { 241*5c51f124SMoriah Waterland mapsize = 0; /* can't mmap today */ 242*5c51f124SMoriah Waterland } 243*5c51f124SMoriah Waterland } 244*5c51f124SMoriah Waterland 245*5c51f124SMoriah Waterland /* 246*5c51f124SMoriah Waterland * if the source was not mapped into memory, copy via read/write loop 247*5c51f124SMoriah Waterland */ 248*5c51f124SMoriah Waterland 249*5c51f124SMoriah Waterland if (mapsize == 0) { 250*5c51f124SMoriah Waterland char *buf = (char *)NULL; 251*5c51f124SMoriah Waterland size_t blocksize; 252*5c51f124SMoriah Waterland int pagesize = getpagesize(); 253*5c51f124SMoriah Waterland 254*5c51f124SMoriah Waterland /* set blocksize for copy */ 255*5c51f124SMoriah Waterland 256*5c51f124SMoriah Waterland blocksize = a_iosize; 257*5c51f124SMoriah Waterland if ((blocksize == 0) || (blocksize > SMALLFILESIZE)) { 258*5c51f124SMoriah Waterland blocksize = SMALLFILESIZE; 259*5c51f124SMoriah Waterland } else if (blocksize < pagesize) { 260*5c51f124SMoriah Waterland blocksize = pagesize; 261*5c51f124SMoriah Waterland } 262*5c51f124SMoriah Waterland 263*5c51f124SMoriah Waterland /* allocate i/o transfer buffer */ 264*5c51f124SMoriah Waterland 265*5c51f124SMoriah Waterland buf = memalign((size_t)pagesize, blocksize); 266*5c51f124SMoriah Waterland if (buf == (char *)NULL) { 267*5c51f124SMoriah Waterland progerr(ERR_COPY_MEMORY, a_srcPath, errno, 268*5c51f124SMoriah Waterland strerror(errno)); 269*5c51f124SMoriah Waterland return (1); 270*5c51f124SMoriah Waterland } 271*5c51f124SMoriah Waterland 272*5c51f124SMoriah Waterland /* copy the file contents */ 273*5c51f124SMoriah Waterland 274*5c51f124SMoriah Waterland for (;;) { 275*5c51f124SMoriah Waterland ssize_t n; 276*5c51f124SMoriah Waterland 277*5c51f124SMoriah Waterland /* read next block of data */ 278*5c51f124SMoriah Waterland 279*5c51f124SMoriah Waterland n = read(a_srcFd, buf, blocksize); 280*5c51f124SMoriah Waterland if (n == 0) { 281*5c51f124SMoriah Waterland /* end of file - return success */ 282*5c51f124SMoriah Waterland (void) free(buf); 283*5c51f124SMoriah Waterland return (0); 284*5c51f124SMoriah Waterland } else if (n < 0) { 285*5c51f124SMoriah Waterland /* read error - return error */ 286*5c51f124SMoriah Waterland progerr(ERR_READ, a_srcPath, 287*5c51f124SMoriah Waterland errno, strerror(errno)); 288*5c51f124SMoriah Waterland (void) free(buf); 289*5c51f124SMoriah Waterland return (1); 290*5c51f124SMoriah Waterland } 291*5c51f124SMoriah Waterland 292*5c51f124SMoriah Waterland /* write out block of data just read in */ 293*5c51f124SMoriah Waterland 294*5c51f124SMoriah Waterland if (vfpSafeWrite(a_dstFd, buf, (size_t)n) != n) { 295*5c51f124SMoriah Waterland /* short write/write error - return error */ 296*5c51f124SMoriah Waterland progerr(ERR_WRITE, a_dstPath, 297*5c51f124SMoriah Waterland errno, strerror(errno)); 298*5c51f124SMoriah Waterland (void) free(buf); 299*5c51f124SMoriah Waterland return (1); 300*5c51f124SMoriah Waterland } 301*5c51f124SMoriah Waterland } 302*5c51f124SMoriah Waterland } 303*5c51f124SMoriah Waterland 304*5c51f124SMoriah Waterland /* 305*5c51f124SMoriah Waterland * the source has been mapped into memory, copy via mappings 306*5c51f124SMoriah Waterland */ 307*5c51f124SMoriah Waterland 308*5c51f124SMoriah Waterland for (;;) { 309*5c51f124SMoriah Waterland ssize_t nbytes; 310*5c51f124SMoriah Waterland 311*5c51f124SMoriah Waterland /* write first mappings worth of data */ 312*5c51f124SMoriah Waterland 313*5c51f124SMoriah Waterland nbytes = write(a_dstFd, cp, mapsize); 314*5c51f124SMoriah Waterland 315*5c51f124SMoriah Waterland /* 316*5c51f124SMoriah Waterland * if we write less than the mmaped size it's due to a 317*5c51f124SMoriah Waterland * media error on the input file or out of space on 318*5c51f124SMoriah Waterland * the output file. So, try again, and look for errno. 319*5c51f124SMoriah Waterland */ 320*5c51f124SMoriah Waterland 321*5c51f124SMoriah Waterland if ((nbytes >= 0) && (nbytes != (ssize_t)mapsize)) { 322*5c51f124SMoriah Waterland size_t remains; 323*5c51f124SMoriah Waterland 324*5c51f124SMoriah Waterland remains = mapsize - nbytes; 325*5c51f124SMoriah Waterland while (remains > 0) { 326*5c51f124SMoriah Waterland nbytes = write(a_dstFd, 327*5c51f124SMoriah Waterland (cp + mapsize - remains), remains); 328*5c51f124SMoriah Waterland if (nbytes >= 0) { 329*5c51f124SMoriah Waterland remains -= nbytes; 330*5c51f124SMoriah Waterland if (remains == 0) { 331*5c51f124SMoriah Waterland nbytes = mapsize; 332*5c51f124SMoriah Waterland } 333*5c51f124SMoriah Waterland continue; 334*5c51f124SMoriah Waterland } 335*5c51f124SMoriah Waterland 336*5c51f124SMoriah Waterland /* i/o error - report and exit */ 337*5c51f124SMoriah Waterland 338*5c51f124SMoriah Waterland if (errno == ENOSPC) { 339*5c51f124SMoriah Waterland progerr(ERR_WRITE, a_dstPath, 340*5c51f124SMoriah Waterland errno, strerror(errno)); 341*5c51f124SMoriah Waterland } else { 342*5c51f124SMoriah Waterland progerr(ERR_READ, a_srcPath, 343*5c51f124SMoriah Waterland errno, strerror(errno)); 344*5c51f124SMoriah Waterland } 345*5c51f124SMoriah Waterland 346*5c51f124SMoriah Waterland /* unmap source file mapping */ 347*5c51f124SMoriah Waterland (void) munmap(cp, munmapsize); 348*5c51f124SMoriah Waterland return (1); 349*5c51f124SMoriah Waterland } 350*5c51f124SMoriah Waterland } 351*5c51f124SMoriah Waterland 352*5c51f124SMoriah Waterland /* 353*5c51f124SMoriah Waterland * although the write manual page doesn't specify this 354*5c51f124SMoriah Waterland * as a possible errno, it is set when the nfs read 355*5c51f124SMoriah Waterland * via the mmap'ed file is accessed, so report the 356*5c51f124SMoriah Waterland * problem as a source access problem, not a target file 357*5c51f124SMoriah Waterland * problem 358*5c51f124SMoriah Waterland */ 359*5c51f124SMoriah Waterland 360*5c51f124SMoriah Waterland if (nbytes < 0) { 361*5c51f124SMoriah Waterland if (errno == EACCES) { 362*5c51f124SMoriah Waterland progerr(ERR_READ, a_srcPath, 363*5c51f124SMoriah Waterland errno, strerror(errno)); 364*5c51f124SMoriah Waterland } else { 365*5c51f124SMoriah Waterland progerr(ERR_WRITE, a_dstPath, 366*5c51f124SMoriah Waterland errno, strerror(errno)); 367*5c51f124SMoriah Waterland } 368*5c51f124SMoriah Waterland 369*5c51f124SMoriah Waterland /* unmap source file mapping */ 370*5c51f124SMoriah Waterland (void) munmap(cp, munmapsize); 371*5c51f124SMoriah Waterland return (1); 372*5c51f124SMoriah Waterland } 373*5c51f124SMoriah Waterland 374*5c51f124SMoriah Waterland filesize -= nbytes; 375*5c51f124SMoriah Waterland if (filesize == 0) { 376*5c51f124SMoriah Waterland break; 377*5c51f124SMoriah Waterland } 378*5c51f124SMoriah Waterland 379*5c51f124SMoriah Waterland offset += nbytes; 380*5c51f124SMoriah Waterland if (filesize < mapsize) { 381*5c51f124SMoriah Waterland mapsize = filesize; 382*5c51f124SMoriah Waterland } 383*5c51f124SMoriah Waterland 384*5c51f124SMoriah Waterland /* map next segment of file on top of existing mapping */ 385*5c51f124SMoriah Waterland 386*5c51f124SMoriah Waterland cp = mmap(cp, mapsize, PROT_READ, (MAP_SHARED|MAP_FIXED), 387*5c51f124SMoriah Waterland a_srcFd, offset); 388*5c51f124SMoriah Waterland 389*5c51f124SMoriah Waterland if (cp == MAP_FAILED) { 390*5c51f124SMoriah Waterland progerr(ERR_MAPFAILED, a_srcPath, errno, 391*5c51f124SMoriah Waterland strerror(errno)); 392*5c51f124SMoriah Waterland /* unmap source file mapping */ 393*5c51f124SMoriah Waterland (void) munmap(cp, munmapsize); 394*5c51f124SMoriah Waterland return (1); 395*5c51f124SMoriah Waterland } 396*5c51f124SMoriah Waterland } 397*5c51f124SMoriah Waterland 398*5c51f124SMoriah Waterland /* unmap source file mapping */ 399*5c51f124SMoriah Waterland 400*5c51f124SMoriah Waterland (void) munmap(cp, munmapsize); 401*5c51f124SMoriah Waterland 402*5c51f124SMoriah Waterland return (0); 403*5c51f124SMoriah Waterland } 404*5c51f124SMoriah Waterland 405*5c51f124SMoriah Waterland /* 406*5c51f124SMoriah Waterland * Name: openLocal 407*5c51f124SMoriah Waterland * Description: open a file and assure that the descriptor returned is open on 408*5c51f124SMoriah Waterland * a file that is local to the current system - if the file is not 409*5c51f124SMoriah Waterland * local to this system, copy the file to a temporary file first, 410*5c51f124SMoriah Waterland * and then pass a handle back opened on the temporary file 411*5c51f124SMoriah Waterland * Arguments: a_path - [RO, *RO] - (char *) 412*5c51f124SMoriah Waterland * Pointer to string representing the path to the file 413*5c51f124SMoriah Waterland * to open 414*5c51f124SMoriah Waterland * a_oflag - [RO, *RO] - (int) 415*5c51f124SMoriah Waterland * Integer representing the "mode" bits for an open(2) call 416*5c51f124SMoriah Waterland * a_tmpdir - [RO, *RO] - (char *) 417*5c51f124SMoriah Waterland * Pointer to string representing the path to a directory 418*5c51f124SMoriah Waterland * where a temporary copy of the file can be placed if 419*5c51f124SMoriah Waterland * the source file is not local to this system. If this is 420*5c51f124SMoriah Waterland * NULL or does not exist, P_tmpdir is used. 421*5c51f124SMoriah Waterland * Returns: int 422*5c51f124SMoriah Waterland * >= 0 - file descriptor opened on the file 423*5c51f124SMoriah Waterland * == -1 - failed to open - errno contains error code 424*5c51f124SMoriah Waterland * NOTE: If the file is not local and is copied locally, the file is 425*5c51f124SMoriah Waterland * setup in such a way that it will be removed when the last 426*5c51f124SMoriah Waterland * file descriptor opened on the file is closed - there is no need 427*5c51f124SMoriah Waterland * to know the path to the temporary file or to remove it 428*5c51f124SMoriah Waterland * when done. 429*5c51f124SMoriah Waterland */ 430*5c51f124SMoriah Waterland 431*5c51f124SMoriah Waterland int 432*5c51f124SMoriah Waterland openLocal(char *a_path, int a_oflag, char *a_tmpdir) 433*5c51f124SMoriah Waterland { 434*5c51f124SMoriah Waterland char *bn; 435*5c51f124SMoriah Waterland char template[PATH_MAX]; 436*5c51f124SMoriah Waterland int fd; 437*5c51f124SMoriah Waterland int lerrno; 438*5c51f124SMoriah Waterland int n; 439*5c51f124SMoriah Waterland int tmpFd; 440*5c51f124SMoriah Waterland struct stat statbuf; 441*5c51f124SMoriah Waterland 442*5c51f124SMoriah Waterland /* open source file */ 443*5c51f124SMoriah Waterland 444*5c51f124SMoriah Waterland fd = open(a_path, a_oflag); 445*5c51f124SMoriah Waterland if (fd < 0) { 446*5c51f124SMoriah Waterland return (fd); 447*5c51f124SMoriah Waterland } 448*5c51f124SMoriah Waterland 449*5c51f124SMoriah Waterland /* return open fd if the source file is not remote */ 450*5c51f124SMoriah Waterland 451*5c51f124SMoriah Waterland if (!isFdRemote(fd)) { 452*5c51f124SMoriah Waterland return (fd); 453*5c51f124SMoriah Waterland } 454*5c51f124SMoriah Waterland 455*5c51f124SMoriah Waterland /* 456*5c51f124SMoriah Waterland * source file is remote - must make a local copy 457*5c51f124SMoriah Waterland */ 458*5c51f124SMoriah Waterland 459*5c51f124SMoriah Waterland /* get the source file's status */ 460*5c51f124SMoriah Waterland 461*5c51f124SMoriah Waterland n = fstat(fd, &statbuf); 462*5c51f124SMoriah Waterland if (n < 0) { 463*5c51f124SMoriah Waterland lerrno = errno; 464*5c51f124SMoriah Waterland (void) close(fd); 465*5c51f124SMoriah Waterland errno = lerrno; 466*5c51f124SMoriah Waterland return (-1); 467*5c51f124SMoriah Waterland } 468*5c51f124SMoriah Waterland 469*5c51f124SMoriah Waterland /* generate unique temporary file name */ 470*5c51f124SMoriah Waterland 471*5c51f124SMoriah Waterland if ((a_tmpdir == (char *)NULL) || (*a_tmpdir == '\0') || 472*5c51f124SMoriah Waterland (isdir(a_tmpdir) != 0)) { 473*5c51f124SMoriah Waterland a_tmpdir = P_tmpdir; 474*5c51f124SMoriah Waterland } 475*5c51f124SMoriah Waterland bn = basename(a_path); 476*5c51f124SMoriah Waterland n = strlen(a_tmpdir); 477*5c51f124SMoriah Waterland n = snprintf(template, sizeof (template), "%s%s%sXXXXXX", 478*5c51f124SMoriah Waterland a_tmpdir, a_tmpdir[n-1] == '/' ? "" : "/", bn); 479*5c51f124SMoriah Waterland if (n > sizeof (template)) { 480*5c51f124SMoriah Waterland (void) close(fd); 481*5c51f124SMoriah Waterland return (EINVAL); 482*5c51f124SMoriah Waterland } 483*5c51f124SMoriah Waterland 484*5c51f124SMoriah Waterland /* create the temporary file and open it */ 485*5c51f124SMoriah Waterland 486*5c51f124SMoriah Waterland tmpFd = mkstemp(template); 487*5c51f124SMoriah Waterland if (tmpFd < 0) { 488*5c51f124SMoriah Waterland lerrno = errno; 489*5c51f124SMoriah Waterland (void) close(fd); 490*5c51f124SMoriah Waterland errno = lerrno; 491*5c51f124SMoriah Waterland return (tmpFd); 492*5c51f124SMoriah Waterland } 493*5c51f124SMoriah Waterland 494*5c51f124SMoriah Waterland /* unlink the file so when it is closed it is automatically deleted */ 495*5c51f124SMoriah Waterland 496*5c51f124SMoriah Waterland (void) unlink(template); 497*5c51f124SMoriah Waterland 498*5c51f124SMoriah Waterland /* copy the source file to the temporary file */ 499*5c51f124SMoriah Waterland 500*5c51f124SMoriah Waterland n = copyFile(fd, tmpFd, a_path, template, &statbuf, 0L); 501*5c51f124SMoriah Waterland lerrno = errno; 502*5c51f124SMoriah Waterland (void) close(fd); 503*5c51f124SMoriah Waterland if (n != 0) { 504*5c51f124SMoriah Waterland (void) close(tmpFd); 505*5c51f124SMoriah Waterland errno = lerrno; 506*5c51f124SMoriah Waterland return (-1); 507*5c51f124SMoriah Waterland } 508*5c51f124SMoriah Waterland 509*5c51f124SMoriah Waterland /* return handle to temporary file created */ 510*5c51f124SMoriah Waterland 511*5c51f124SMoriah Waterland return (tmpFd); 512*5c51f124SMoriah Waterland } 513