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