1*5fbb8099SNobutomo Nakano /* 2*5fbb8099SNobutomo Nakano * CDDL HEADER START 3*5fbb8099SNobutomo Nakano * 4*5fbb8099SNobutomo Nakano * The contents of this file are subject to the terms of the 5*5fbb8099SNobutomo Nakano * Common Development and Distribution License (the "License"). 6*5fbb8099SNobutomo Nakano * You may not use this file except in compliance with the License. 7*5fbb8099SNobutomo Nakano * 8*5fbb8099SNobutomo Nakano * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5fbb8099SNobutomo Nakano * or http://www.opensolaris.org/os/licensing. 10*5fbb8099SNobutomo Nakano * See the License for the specific language governing permissions 11*5fbb8099SNobutomo Nakano * and limitations under the License. 12*5fbb8099SNobutomo Nakano * 13*5fbb8099SNobutomo Nakano * When distributing Covered Code, include this CDDL HEADER in each 14*5fbb8099SNobutomo Nakano * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5fbb8099SNobutomo Nakano * If applicable, add the following below this CDDL HEADER, with the 16*5fbb8099SNobutomo Nakano * fields enclosed by brackets "[]" replaced with your own identifying 17*5fbb8099SNobutomo Nakano * information: Portions Copyright [yyyy] [name of copyright owner] 18*5fbb8099SNobutomo Nakano * 19*5fbb8099SNobutomo Nakano * CDDL HEADER END 20*5fbb8099SNobutomo Nakano */ 21*5fbb8099SNobutomo Nakano /* 22*5fbb8099SNobutomo Nakano * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*5fbb8099SNobutomo Nakano * Use is subject to license terms. 24*5fbb8099SNobutomo Nakano */ 25*5fbb8099SNobutomo Nakano 26*5fbb8099SNobutomo Nakano /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27*5fbb8099SNobutomo Nakano /* All Rights Reserved */ 28*5fbb8099SNobutomo Nakano 29*5fbb8099SNobutomo Nakano /* 30*5fbb8099SNobutomo Nakano * Portions of this source code were derived from Berkeley 4.3 BSD 31*5fbb8099SNobutomo Nakano * under license from the Regents of the University of California. 32*5fbb8099SNobutomo Nakano */ 33*5fbb8099SNobutomo Nakano 34*5fbb8099SNobutomo Nakano #include <stdio.h> 35*5fbb8099SNobutomo Nakano #include <stdlib.h> 36*5fbb8099SNobutomo Nakano #include <stdarg.h> 37*5fbb8099SNobutomo Nakano #include <string.h> 38*5fbb8099SNobutomo Nakano #include <sys/stat.h> 39*5fbb8099SNobutomo Nakano #include <unistd.h> 40*5fbb8099SNobutomo Nakano #include <ctype.h> 41*5fbb8099SNobutomo Nakano #include <limits.h> 42*5fbb8099SNobutomo Nakano #include <errno.h> 43*5fbb8099SNobutomo Nakano #include <fcntl.h> 44*5fbb8099SNobutomo Nakano 45*5fbb8099SNobutomo Nakano #include "cpio.h" 46*5fbb8099SNobutomo Nakano 47*5fbb8099SNobutomo Nakano /* 48*5fbb8099SNobutomo Nakano * Allocation wrappers. Used to centralize error handling for 49*5fbb8099SNobutomo Nakano * failed allocations. 50*5fbb8099SNobutomo Nakano */ 51*5fbb8099SNobutomo Nakano static void * 52*5fbb8099SNobutomo Nakano e_alloc_fail(int flag) 53*5fbb8099SNobutomo Nakano { 54*5fbb8099SNobutomo Nakano if (flag == E_EXIT) 55*5fbb8099SNobutomo Nakano msg(EXTN, "Out of memory"); 56*5fbb8099SNobutomo Nakano 57*5fbb8099SNobutomo Nakano return (NULL); 58*5fbb8099SNobutomo Nakano } 59*5fbb8099SNobutomo Nakano 60*5fbb8099SNobutomo Nakano /* 61*5fbb8099SNobutomo Nakano * Note: unlike the other e_*lloc functions, e_realloc does not zero out the 62*5fbb8099SNobutomo Nakano * additional memory it returns. Ensure that you do not trust its contents 63*5fbb8099SNobutomo Nakano * when you call it. 64*5fbb8099SNobutomo Nakano */ 65*5fbb8099SNobutomo Nakano void * 66*5fbb8099SNobutomo Nakano e_realloc(int flag, void *old, size_t newsize) 67*5fbb8099SNobutomo Nakano { 68*5fbb8099SNobutomo Nakano void *ret = realloc(old, newsize); 69*5fbb8099SNobutomo Nakano 70*5fbb8099SNobutomo Nakano if (ret == NULL) { 71*5fbb8099SNobutomo Nakano return (e_alloc_fail(flag)); 72*5fbb8099SNobutomo Nakano } 73*5fbb8099SNobutomo Nakano 74*5fbb8099SNobutomo Nakano return (ret); 75*5fbb8099SNobutomo Nakano } 76*5fbb8099SNobutomo Nakano 77*5fbb8099SNobutomo Nakano char * 78*5fbb8099SNobutomo Nakano e_strdup(int flag, const char *arg) 79*5fbb8099SNobutomo Nakano { 80*5fbb8099SNobutomo Nakano char *ret = strdup(arg); 81*5fbb8099SNobutomo Nakano 82*5fbb8099SNobutomo Nakano if (ret == NULL) { 83*5fbb8099SNobutomo Nakano return (e_alloc_fail(flag)); 84*5fbb8099SNobutomo Nakano } 85*5fbb8099SNobutomo Nakano 86*5fbb8099SNobutomo Nakano return (ret); 87*5fbb8099SNobutomo Nakano } 88*5fbb8099SNobutomo Nakano 89*5fbb8099SNobutomo Nakano void * 90*5fbb8099SNobutomo Nakano e_valloc(int flag, size_t size) 91*5fbb8099SNobutomo Nakano { 92*5fbb8099SNobutomo Nakano void *ret = valloc(size); 93*5fbb8099SNobutomo Nakano 94*5fbb8099SNobutomo Nakano if (ret == NULL) { 95*5fbb8099SNobutomo Nakano return (e_alloc_fail(flag)); 96*5fbb8099SNobutomo Nakano } 97*5fbb8099SNobutomo Nakano 98*5fbb8099SNobutomo Nakano return (ret); 99*5fbb8099SNobutomo Nakano } 100*5fbb8099SNobutomo Nakano 101*5fbb8099SNobutomo Nakano void * 102*5fbb8099SNobutomo Nakano e_zalloc(int flag, size_t size) 103*5fbb8099SNobutomo Nakano { 104*5fbb8099SNobutomo Nakano void *ret = malloc(size); 105*5fbb8099SNobutomo Nakano 106*5fbb8099SNobutomo Nakano if (ret == NULL) { 107*5fbb8099SNobutomo Nakano return (e_alloc_fail(flag)); 108*5fbb8099SNobutomo Nakano } 109*5fbb8099SNobutomo Nakano 110*5fbb8099SNobutomo Nakano (void) memset(ret, 0, size); 111*5fbb8099SNobutomo Nakano return (ret); 112*5fbb8099SNobutomo Nakano } 113*5fbb8099SNobutomo Nakano 114*5fbb8099SNobutomo Nakano /* 115*5fbb8099SNobutomo Nakano * Simple printf() which only support "%s" conversion. 116*5fbb8099SNobutomo Nakano * We need secure version of printf since format string can be supplied 117*5fbb8099SNobutomo Nakano * from gettext(). 118*5fbb8099SNobutomo Nakano */ 119*5fbb8099SNobutomo Nakano void 120*5fbb8099SNobutomo Nakano str_fprintf(FILE *fp, const char *fmt, ...) 121*5fbb8099SNobutomo Nakano { 122*5fbb8099SNobutomo Nakano const char *s = fmt; 123*5fbb8099SNobutomo Nakano va_list ap; 124*5fbb8099SNobutomo Nakano 125*5fbb8099SNobutomo Nakano va_start(ap, fmt); 126*5fbb8099SNobutomo Nakano while (*s != '\0') { 127*5fbb8099SNobutomo Nakano if (*s != '%') { 128*5fbb8099SNobutomo Nakano (void) fputc(*s++, fp); 129*5fbb8099SNobutomo Nakano continue; 130*5fbb8099SNobutomo Nakano } 131*5fbb8099SNobutomo Nakano s++; 132*5fbb8099SNobutomo Nakano if (*s != 's') { 133*5fbb8099SNobutomo Nakano (void) fputc(*(s - 1), fp); 134*5fbb8099SNobutomo Nakano (void) fputc(*s++, fp); 135*5fbb8099SNobutomo Nakano continue; 136*5fbb8099SNobutomo Nakano } 137*5fbb8099SNobutomo Nakano (void) fputs(va_arg(ap, char *), fp); 138*5fbb8099SNobutomo Nakano s++; 139*5fbb8099SNobutomo Nakano } 140*5fbb8099SNobutomo Nakano va_end(ap); 141*5fbb8099SNobutomo Nakano } 142*5fbb8099SNobutomo Nakano 143*5fbb8099SNobutomo Nakano /* 144*5fbb8099SNobutomo Nakano * Step through a file discovering and recording pairs of data and hole 145*5fbb8099SNobutomo Nakano * offsets. Returns a linked list of data/hole offset pairs of a file. 146*5fbb8099SNobutomo Nakano * If there is no holes found, NULL is returned. 147*5fbb8099SNobutomo Nakano * 148*5fbb8099SNobutomo Nakano * Note: According to lseek(2), only filesystems which support 149*5fbb8099SNobutomo Nakano * fpathconf(_PC_MIN_HOLE_SIZE) support SEEK_HOLE. For filesystems 150*5fbb8099SNobutomo Nakano * that do not supply information about holes, the file will be 151*5fbb8099SNobutomo Nakano * represented as one entire data region. 152*5fbb8099SNobutomo Nakano */ 153*5fbb8099SNobutomo Nakano static holes_list_t * 154*5fbb8099SNobutomo Nakano get_holes_list(int fd, off_t filesz, size_t *countp) 155*5fbb8099SNobutomo Nakano { 156*5fbb8099SNobutomo Nakano off_t data, hole; 157*5fbb8099SNobutomo Nakano holes_list_t *hlh, *hl, **hlp; 158*5fbb8099SNobutomo Nakano size_t cnt; 159*5fbb8099SNobutomo Nakano 160*5fbb8099SNobutomo Nakano if (filesz == 0 || fpathconf(fd, _PC_MIN_HOLE_SIZE) < 0) 161*5fbb8099SNobutomo Nakano return (NULL); 162*5fbb8099SNobutomo Nakano 163*5fbb8099SNobutomo Nakano cnt = 0; 164*5fbb8099SNobutomo Nakano hole = 0; 165*5fbb8099SNobutomo Nakano hlh = NULL; 166*5fbb8099SNobutomo Nakano hlp = &hlh; 167*5fbb8099SNobutomo Nakano 168*5fbb8099SNobutomo Nakano while (hole < filesz) { 169*5fbb8099SNobutomo Nakano if ((data = lseek(fd, hole, SEEK_DATA)) == -1) { 170*5fbb8099SNobutomo Nakano /* no more data till the end of file */ 171*5fbb8099SNobutomo Nakano if (errno == ENXIO) { 172*5fbb8099SNobutomo Nakano data = filesz; 173*5fbb8099SNobutomo Nakano } else { 174*5fbb8099SNobutomo Nakano /* assume data starts from the * beginning */ 175*5fbb8099SNobutomo Nakano data = 0; 176*5fbb8099SNobutomo Nakano } 177*5fbb8099SNobutomo Nakano } 178*5fbb8099SNobutomo Nakano if ((hole = lseek(fd, data, SEEK_HOLE)) == -1) { 179*5fbb8099SNobutomo Nakano /* assume that data ends at the end of file */ 180*5fbb8099SNobutomo Nakano hole = filesz; 181*5fbb8099SNobutomo Nakano } 182*5fbb8099SNobutomo Nakano if (data == 0 && hole == filesz) { 183*5fbb8099SNobutomo Nakano /* no holes */ 184*5fbb8099SNobutomo Nakano break; 185*5fbb8099SNobutomo Nakano } 186*5fbb8099SNobutomo Nakano hl = e_zalloc(E_EXIT, sizeof (holes_list_t)); 187*5fbb8099SNobutomo Nakano hl->hl_next = NULL; 188*5fbb8099SNobutomo Nakano 189*5fbb8099SNobutomo Nakano /* set data and hole */ 190*5fbb8099SNobutomo Nakano hl->hl_data = data; 191*5fbb8099SNobutomo Nakano hl->hl_hole = hole; 192*5fbb8099SNobutomo Nakano 193*5fbb8099SNobutomo Nakano *hlp = hl; 194*5fbb8099SNobutomo Nakano hlp = &hl->hl_next; 195*5fbb8099SNobutomo Nakano cnt++; 196*5fbb8099SNobutomo Nakano } 197*5fbb8099SNobutomo Nakano if (countp != NULL) 198*5fbb8099SNobutomo Nakano *countp = cnt; 199*5fbb8099SNobutomo Nakano 200*5fbb8099SNobutomo Nakano /* 201*5fbb8099SNobutomo Nakano * reset to the beginning, otherwise subsequent read calls would 202*5fbb8099SNobutomo Nakano * get EOF 203*5fbb8099SNobutomo Nakano */ 204*5fbb8099SNobutomo Nakano (void) lseek(fd, 0, SEEK_SET); 205*5fbb8099SNobutomo Nakano 206*5fbb8099SNobutomo Nakano return (hlh); 207*5fbb8099SNobutomo Nakano } 208*5fbb8099SNobutomo Nakano 209*5fbb8099SNobutomo Nakano /* 210*5fbb8099SNobutomo Nakano * Calculate the real data size in the sparse file. 211*5fbb8099SNobutomo Nakano */ 212*5fbb8099SNobutomo Nakano static off_t 213*5fbb8099SNobutomo Nakano get_compressed_filesz(holes_list_t *hlh) 214*5fbb8099SNobutomo Nakano { 215*5fbb8099SNobutomo Nakano holes_list_t *hl; 216*5fbb8099SNobutomo Nakano off_t size; 217*5fbb8099SNobutomo Nakano 218*5fbb8099SNobutomo Nakano size = 0; 219*5fbb8099SNobutomo Nakano for (hl = hlh; hl != NULL; hl = hl->hl_next) { 220*5fbb8099SNobutomo Nakano size += (hl->hl_hole - hl->hl_data); 221*5fbb8099SNobutomo Nakano } 222*5fbb8099SNobutomo Nakano return (size); 223*5fbb8099SNobutomo Nakano } 224*5fbb8099SNobutomo Nakano 225*5fbb8099SNobutomo Nakano /* 226*5fbb8099SNobutomo Nakano * Convert val to digit string and put it in str. The next address 227*5fbb8099SNobutomo Nakano * of the last digit is returned. 228*5fbb8099SNobutomo Nakano */ 229*5fbb8099SNobutomo Nakano static char * 230*5fbb8099SNobutomo Nakano put_value(off_t val, char *str) 231*5fbb8099SNobutomo Nakano { 232*5fbb8099SNobutomo Nakano size_t len; 233*5fbb8099SNobutomo Nakano char *digp, dbuf[ULL_MAX_SIZE + 1]; 234*5fbb8099SNobutomo Nakano 235*5fbb8099SNobutomo Nakano dbuf[ULL_MAX_SIZE] = '\0'; 236*5fbb8099SNobutomo Nakano digp = ulltostr((u_longlong_t)val, &dbuf[ULL_MAX_SIZE]); 237*5fbb8099SNobutomo Nakano len = &dbuf[ULL_MAX_SIZE] - digp; 238*5fbb8099SNobutomo Nakano (void) memcpy(str, digp, len); 239*5fbb8099SNobutomo Nakano 240*5fbb8099SNobutomo Nakano return (str + len); 241*5fbb8099SNobutomo Nakano } 242*5fbb8099SNobutomo Nakano 243*5fbb8099SNobutomo Nakano /* 244*5fbb8099SNobutomo Nakano * Put data/hole offset pair into string in the following 245*5fbb8099SNobutomo Nakano * sequence. 246*5fbb8099SNobutomo Nakano * <data> <sp> <hole> <sp> 247*5fbb8099SNobutomo Nakano */ 248*5fbb8099SNobutomo Nakano static void 249*5fbb8099SNobutomo Nakano store_sparse_string(holes_list_t *hlh, char *str, size_t *szp) 250*5fbb8099SNobutomo Nakano { 251*5fbb8099SNobutomo Nakano holes_list_t *hl; 252*5fbb8099SNobutomo Nakano char *p; 253*5fbb8099SNobutomo Nakano 254*5fbb8099SNobutomo Nakano p = str; 255*5fbb8099SNobutomo Nakano for (hl = hlh; hl != NULL; hl = hl->hl_next) { 256*5fbb8099SNobutomo Nakano p = put_value(hl->hl_data, p); 257*5fbb8099SNobutomo Nakano *p++ = ' '; 258*5fbb8099SNobutomo Nakano p = put_value(hl->hl_hole, p); 259*5fbb8099SNobutomo Nakano *p++ = ' '; 260*5fbb8099SNobutomo Nakano } 261*5fbb8099SNobutomo Nakano *--p = '\0'; 262*5fbb8099SNobutomo Nakano if (szp != NULL) 263*5fbb8099SNobutomo Nakano *szp = p - str; 264*5fbb8099SNobutomo Nakano } 265*5fbb8099SNobutomo Nakano 266*5fbb8099SNobutomo Nakano /* 267*5fbb8099SNobutomo Nakano * Convert decimal str into unsigned long long value. The end pointer 268*5fbb8099SNobutomo Nakano * is returned. 269*5fbb8099SNobutomo Nakano */ 270*5fbb8099SNobutomo Nakano static const char * 271*5fbb8099SNobutomo Nakano get_ull_tok(const char *str, uint64_t *ulp) 272*5fbb8099SNobutomo Nakano { 273*5fbb8099SNobutomo Nakano uint64_t ul; 274*5fbb8099SNobutomo Nakano char *np; 275*5fbb8099SNobutomo Nakano 276*5fbb8099SNobutomo Nakano while (isspace(*str)) 277*5fbb8099SNobutomo Nakano str++; 278*5fbb8099SNobutomo Nakano if (!isdigit(*str)) 279*5fbb8099SNobutomo Nakano return (NULL); 280*5fbb8099SNobutomo Nakano 281*5fbb8099SNobutomo Nakano errno = 0; 282*5fbb8099SNobutomo Nakano ul = strtoull(str, &np, 10); 283*5fbb8099SNobutomo Nakano if (ul == ULLONG_MAX && errno == ERANGE) 284*5fbb8099SNobutomo Nakano return (NULL); /* invalid value */ 285*5fbb8099SNobutomo Nakano if (*np != ' ' && *np != '\0') 286*5fbb8099SNobutomo Nakano return (NULL); /* invalid input */ 287*5fbb8099SNobutomo Nakano 288*5fbb8099SNobutomo Nakano *ulp = ul; 289*5fbb8099SNobutomo Nakano return (np); 290*5fbb8099SNobutomo Nakano } 291*5fbb8099SNobutomo Nakano 292*5fbb8099SNobutomo Nakano static void 293*5fbb8099SNobutomo Nakano free_holesdata(holes_info_t *hi) 294*5fbb8099SNobutomo Nakano { 295*5fbb8099SNobutomo Nakano holes_list_t *hl, *nhl; 296*5fbb8099SNobutomo Nakano 297*5fbb8099SNobutomo Nakano for (hl = hi->holes_list; hl != NULL; hl = nhl) { 298*5fbb8099SNobutomo Nakano nhl = hl->hl_next; 299*5fbb8099SNobutomo Nakano free(hl); 300*5fbb8099SNobutomo Nakano } 301*5fbb8099SNobutomo Nakano hi->holes_list = NULL; 302*5fbb8099SNobutomo Nakano 303*5fbb8099SNobutomo Nakano if (hi->holesdata != NULL) 304*5fbb8099SNobutomo Nakano free(hi->holesdata); 305*5fbb8099SNobutomo Nakano hi->holesdata = NULL; 306*5fbb8099SNobutomo Nakano } 307*5fbb8099SNobutomo Nakano 308*5fbb8099SNobutomo Nakano /* 309*5fbb8099SNobutomo Nakano * When a hole is detected, non NULL holes_info pointer is returned. 310*5fbb8099SNobutomo Nakano * If we are in copy-out mode, holes_list is converted to string (holesdata) 311*5fbb8099SNobutomo Nakano * which will be prepended to file contents. The holesdata is a character 312*5fbb8099SNobutomo Nakano * string and in the format of: 313*5fbb8099SNobutomo Nakano * 314*5fbb8099SNobutomo Nakano * <data size(%10u)><SP><file size(%llu)><SP> 315*5fbb8099SNobutomo Nakano * <SP><data off><SP><hole off><SP><data off><SP><hole off> ... 316*5fbb8099SNobutomo Nakano * 317*5fbb8099SNobutomo Nakano * This string is parsed by parse_holesholes() in copy-in mode to restore 318*5fbb8099SNobutomo Nakano * the sparse info. 319*5fbb8099SNobutomo Nakano */ 320*5fbb8099SNobutomo Nakano holes_info_t * 321*5fbb8099SNobutomo Nakano get_holes_info(int fd, off_t filesz, boolean_t pass_mode) 322*5fbb8099SNobutomo Nakano { 323*5fbb8099SNobutomo Nakano holes_info_t *hi; 324*5fbb8099SNobutomo Nakano holes_list_t *hl; 325*5fbb8099SNobutomo Nakano char *str, hstr[MIN_HOLES_HDRSIZE + 1]; 326*5fbb8099SNobutomo Nakano size_t ninfo, len; 327*5fbb8099SNobutomo Nakano 328*5fbb8099SNobutomo Nakano if ((hl = get_holes_list(fd, filesz, &ninfo)) == NULL) 329*5fbb8099SNobutomo Nakano return (NULL); 330*5fbb8099SNobutomo Nakano 331*5fbb8099SNobutomo Nakano hi = e_zalloc(E_EXIT, sizeof (holes_info_t)); 332*5fbb8099SNobutomo Nakano hi->holes_list = hl; 333*5fbb8099SNobutomo Nakano 334*5fbb8099SNobutomo Nakano if (!pass_mode) { 335*5fbb8099SNobutomo Nakano str = e_zalloc(E_EXIT, 336*5fbb8099SNobutomo Nakano MIN_HOLES_HDRSIZE + ninfo * (ULL_MAX_SIZE * 2)); 337*5fbb8099SNobutomo Nakano /* 338*5fbb8099SNobutomo Nakano * Convert into string data, and place it to after 339*5fbb8099SNobutomo Nakano * the first 2 fixed entries. 340*5fbb8099SNobutomo Nakano */ 341*5fbb8099SNobutomo Nakano store_sparse_string(hl, str + MIN_HOLES_HDRSIZE, &len); 342*5fbb8099SNobutomo Nakano 343*5fbb8099SNobutomo Nakano /* 344*5fbb8099SNobutomo Nakano * Add the first two fixed entries. The size of holesdata 345*5fbb8099SNobutomo Nakano * includes '\0' at the end of data 346*5fbb8099SNobutomo Nakano */ 347*5fbb8099SNobutomo Nakano (void) sprintf(hstr, "%10lu %20llu ", 348*5fbb8099SNobutomo Nakano (ulong_t)MIN_HOLES_HDRSIZE + len + 1, filesz); 349*5fbb8099SNobutomo Nakano (void) memcpy(str, hstr, MIN_HOLES_HDRSIZE); 350*5fbb8099SNobutomo Nakano 351*5fbb8099SNobutomo Nakano /* calc real file size without holes */ 352*5fbb8099SNobutomo Nakano hi->data_size = get_compressed_filesz(hl); 353*5fbb8099SNobutomo Nakano hi->holesdata = str; 354*5fbb8099SNobutomo Nakano hi->holesdata_sz = MIN_HOLES_HDRSIZE + len + 1; 355*5fbb8099SNobutomo Nakano } 356*5fbb8099SNobutomo Nakano return (hi); 357*5fbb8099SNobutomo Nakano } 358*5fbb8099SNobutomo Nakano 359*5fbb8099SNobutomo Nakano /* 360*5fbb8099SNobutomo Nakano * The holesdata information is in the following format: 361*5fbb8099SNobutomo Nakano * <data size(%10u)><SP><file size(%llu)><SP> 362*5fbb8099SNobutomo Nakano * <SP><data off><SP><hole off><SP><data off><SP><hole off> ... 363*5fbb8099SNobutomo Nakano * read_holes_header() allocates holes_info_t, and read the first 2 364*5fbb8099SNobutomo Nakano * entries (data size and file size). The rest of holesdata is 365*5fbb8099SNobutomo Nakano * read by parse_holesdata(). 366*5fbb8099SNobutomo Nakano */ 367*5fbb8099SNobutomo Nakano holes_info_t * 368*5fbb8099SNobutomo Nakano read_holes_header(const char *str, off_t filesz) 369*5fbb8099SNobutomo Nakano { 370*5fbb8099SNobutomo Nakano holes_info_t *hi; 371*5fbb8099SNobutomo Nakano uint64_t ull; 372*5fbb8099SNobutomo Nakano 373*5fbb8099SNobutomo Nakano hi = e_zalloc(E_EXIT, sizeof (holes_info_t)); 374*5fbb8099SNobutomo Nakano 375*5fbb8099SNobutomo Nakano /* read prepended holes data size */ 376*5fbb8099SNobutomo Nakano if ((str = get_ull_tok(str, &ull)) == NULL || *str != ' ') { 377*5fbb8099SNobutomo Nakano bad: 378*5fbb8099SNobutomo Nakano free(hi); 379*5fbb8099SNobutomo Nakano return (NULL); 380*5fbb8099SNobutomo Nakano } 381*5fbb8099SNobutomo Nakano hi->holesdata_sz = (size_t)ull; 382*5fbb8099SNobutomo Nakano 383*5fbb8099SNobutomo Nakano /* read original(expanded) file size */ 384*5fbb8099SNobutomo Nakano if (get_ull_tok(str, &ull) == NULL) 385*5fbb8099SNobutomo Nakano goto bad; 386*5fbb8099SNobutomo Nakano hi->orig_size = (off_t)ull; 387*5fbb8099SNobutomo Nakano 388*5fbb8099SNobutomo Nakano /* sanity check */ 389*5fbb8099SNobutomo Nakano if (hi->holesdata_sz > filesz || 390*5fbb8099SNobutomo Nakano hi->holesdata_sz <= MIN_HOLES_HDRSIZE) { 391*5fbb8099SNobutomo Nakano goto bad; 392*5fbb8099SNobutomo Nakano } 393*5fbb8099SNobutomo Nakano return (hi); 394*5fbb8099SNobutomo Nakano } 395*5fbb8099SNobutomo Nakano 396*5fbb8099SNobutomo Nakano int 397*5fbb8099SNobutomo Nakano parse_holesdata(holes_info_t *hi, const char *str) 398*5fbb8099SNobutomo Nakano { 399*5fbb8099SNobutomo Nakano holes_list_t *hl, **hlp; 400*5fbb8099SNobutomo Nakano uint64_t ull; 401*5fbb8099SNobutomo Nakano off_t loff; 402*5fbb8099SNobutomo Nakano 403*5fbb8099SNobutomo Nakano /* create hole list */ 404*5fbb8099SNobutomo Nakano hlp = &hi->holes_list; 405*5fbb8099SNobutomo Nakano while (*str != '\0') { 406*5fbb8099SNobutomo Nakano hl = e_zalloc(E_EXIT, sizeof (holes_list_t)); 407*5fbb8099SNobutomo Nakano /* link list */ 408*5fbb8099SNobutomo Nakano hl->hl_next = NULL; 409*5fbb8099SNobutomo Nakano *hlp = hl; 410*5fbb8099SNobutomo Nakano hlp = &hl->hl_next; 411*5fbb8099SNobutomo Nakano 412*5fbb8099SNobutomo Nakano /* read the string token for data */ 413*5fbb8099SNobutomo Nakano if ((str = get_ull_tok(str, &ull)) == NULL) 414*5fbb8099SNobutomo Nakano goto bad; 415*5fbb8099SNobutomo Nakano hl->hl_data = (off_t)ull; 416*5fbb8099SNobutomo Nakano 417*5fbb8099SNobutomo Nakano /* there must be single blank space in between */ 418*5fbb8099SNobutomo Nakano if (*str != ' ') 419*5fbb8099SNobutomo Nakano goto bad; 420*5fbb8099SNobutomo Nakano 421*5fbb8099SNobutomo Nakano /* read the string token for hole */ 422*5fbb8099SNobutomo Nakano if ((str = get_ull_tok(str, &ull)) == NULL) 423*5fbb8099SNobutomo Nakano goto bad; 424*5fbb8099SNobutomo Nakano hl->hl_hole = (off_t)ull; 425*5fbb8099SNobutomo Nakano } 426*5fbb8099SNobutomo Nakano 427*5fbb8099SNobutomo Nakano /* check to see if offset is in ascending order */ 428*5fbb8099SNobutomo Nakano loff = -1; 429*5fbb8099SNobutomo Nakano for (hl = hi->holes_list; hl != NULL; hl = hl->hl_next) { 430*5fbb8099SNobutomo Nakano if (loff >= hl->hl_data) 431*5fbb8099SNobutomo Nakano goto bad; 432*5fbb8099SNobutomo Nakano loff = hl->hl_data; 433*5fbb8099SNobutomo Nakano /* data and hole can be equal */ 434*5fbb8099SNobutomo Nakano if (loff > hl->hl_hole) 435*5fbb8099SNobutomo Nakano goto bad; 436*5fbb8099SNobutomo Nakano loff = hl->hl_hole; 437*5fbb8099SNobutomo Nakano } 438*5fbb8099SNobutomo Nakano /* The last hole offset should match original file size */ 439*5fbb8099SNobutomo Nakano if (hi->orig_size != loff) { 440*5fbb8099SNobutomo Nakano bad: 441*5fbb8099SNobutomo Nakano free_holesdata(hi); 442*5fbb8099SNobutomo Nakano return (1); 443*5fbb8099SNobutomo Nakano } 444*5fbb8099SNobutomo Nakano 445*5fbb8099SNobutomo Nakano hi->data_size = get_compressed_filesz(hi->holes_list); 446*5fbb8099SNobutomo Nakano 447*5fbb8099SNobutomo Nakano return (0); 448*5fbb8099SNobutomo Nakano } 449*5fbb8099SNobutomo Nakano 450*5fbb8099SNobutomo Nakano void 451*5fbb8099SNobutomo Nakano free_holes_info(holes_info_t *hi) 452*5fbb8099SNobutomo Nakano { 453*5fbb8099SNobutomo Nakano free_holesdata(hi); 454*5fbb8099SNobutomo Nakano free(hi); 455*5fbb8099SNobutomo Nakano } 456