5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * CDDL HEADER START
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * The contents of this file are subject to the terms of the
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Common Development and Distribution License (the "License").
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * You may not use this file except in compliance with the License.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * or http://www.opensolaris.org/os/licensing.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * See the License for the specific language governing permissions
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * and limitations under the License.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * When distributing Covered Code, include this CDDL HEADER in each
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * If applicable, add the following below this CDDL HEADER, with the
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * fields enclosed by brackets "[]" replaced with your own identifying
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * information: Portions Copyright [yyyy] [name of copyright owner]
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * CDDL HEADER END
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Use is subject to license terms.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/* All Rights Reserved */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Portions of this source code were derived from Berkeley 4.3 BSD
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * under license from the Regents of the University of California.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <stdio.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <stdlib.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <stdarg.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <string.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <sys/stat.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <unistd.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <ctype.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <limits.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <errno.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include <fcntl.h>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano#include "cpio.h"
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Allocation wrappers. Used to centralize error handling for
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * failed allocations.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostatic void *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoe_alloc_fail(int flag)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (flag == E_EXIT)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano msg(EXTN, "Out of memory");
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (NULL);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Note: unlike the other e_*lloc functions, e_realloc does not zero out the
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * additional memory it returns. Ensure that you do not trust its contents
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * when you call it.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanovoid *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoe_realloc(int flag, void *old, size_t newsize)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano void *ret = realloc(old, newsize);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (ret == NULL) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (e_alloc_fail(flag));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (ret);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanochar *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoe_strdup(int flag, const char *arg)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano char *ret = strdup(arg);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (ret == NULL) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (e_alloc_fail(flag));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (ret);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanovoid *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoe_valloc(int flag, size_t size)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano void *ret = valloc(size);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (ret == NULL) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (e_alloc_fail(flag));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (ret);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanovoid *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoe_zalloc(int flag, size_t size)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano void *ret = malloc(size);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (ret == NULL) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (e_alloc_fail(flag));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) memset(ret, 0, size);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (ret);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Simple printf() which only support "%s" conversion.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * We need secure version of printf since format string can be supplied
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * from gettext().
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanovoid
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostr_fprintf(FILE *fp, const char *fmt, ...)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano const char *s = fmt;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano va_list ap;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano va_start(ap, fmt);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano while (*s != '\0') {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (*s != '%') {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) fputc(*s++, fp);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano continue;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano s++;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (*s != 's') {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) fputc(*(s - 1), fp);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) fputc(*s++, fp);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano continue;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) fputs(va_arg(ap, char *), fp);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano s++;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano va_end(ap);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Step through a file discovering and recording pairs of data and hole
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * offsets. Returns a linked list of data/hole offset pairs of a file.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * If there is no holes found, NULL is returned.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Note: According to lseek(2), only filesystems which support
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * fpathconf(_PC_MIN_HOLE_SIZE) support SEEK_HOLE. For filesystems
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * that do not supply information about holes, the file will be
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * represented as one entire data region.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostatic holes_list_t *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoget_holes_list(int fd, off_t filesz, size_t *countp)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano off_t data, hole;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_list_t *hlh, *hl, **hlp;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano size_t cnt;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (filesz == 0 || fpathconf(fd, _PC_MIN_HOLE_SIZE) < 0)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (NULL);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano cnt = 0;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hole = 0;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hlh = NULL;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hlp = &hlh;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano while (hole < filesz) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if ((data = lseek(fd, hole, SEEK_DATA)) == -1) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* no more data till the end of file */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (errno == ENXIO) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano data = filesz;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano } else {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* assume data starts from the * beginning */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano data = 0;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if ((hole = lseek(fd, data, SEEK_HOLE)) == -1) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* assume that data ends at the end of file */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hole = filesz;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (data == 0 && hole == filesz) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* no holes */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano break;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl = e_zalloc(E_EXIT, sizeof (holes_list_t));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl->hl_next = NULL;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* set data and hole */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl->hl_data = data;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl->hl_hole = hole;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *hlp = hl;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hlp = &hl->hl_next;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano cnt++;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (countp != NULL)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *countp = cnt;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * reset to the beginning, otherwise subsequent read calls would
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * get EOF
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) lseek(fd, 0, SEEK_SET);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (hlh);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Calculate the real data size in the sparse file.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostatic off_t
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoget_compressed_filesz(holes_list_t *hlh)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_list_t *hl;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano off_t size;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano size = 0;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano for (hl = hlh; hl != NULL; hl = hl->hl_next) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano size += (hl->hl_hole - hl->hl_data);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (size);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Convert val to digit string and put it in str. The next address
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * of the last digit is returned.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostatic char *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoput_value(off_t val, char *str)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano size_t len;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano char *digp, dbuf[ULL_MAX_SIZE + 1];
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano dbuf[ULL_MAX_SIZE] = '\0';
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano digp = ulltostr((u_longlong_t)val, &dbuf[ULL_MAX_SIZE]);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano len = &dbuf[ULL_MAX_SIZE] - digp;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) memcpy(str, digp, len);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (str + len);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Put data/hole offset pair into string in the following
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * sequence.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * <data> <sp> <hole> <sp>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostatic void
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostore_sparse_string(holes_list_t *hlh, char *str, size_t *szp)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_list_t *hl;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano char *p;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano p = str;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano for (hl = hlh; hl != NULL; hl = hl->hl_next) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano p = put_value(hl->hl_data, p);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *p++ = ' ';
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano p = put_value(hl->hl_hole, p);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *p++ = ' ';
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *--p = '\0';
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (szp != NULL)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *szp = p - str;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Convert decimal str into unsigned long long value. The end pointer
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * is returned.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostatic const char *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoget_ull_tok(const char *str, uint64_t *ulp)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano uint64_t ul;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano char *np;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano while (isspace(*str))
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano str++;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (!isdigit(*str))
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (NULL);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano errno = 0;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano ul = strtoull(str, &np, 10);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (ul == ULLONG_MAX && errno == ERANGE)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (NULL); /* invalid value */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (*np != ' ' && *np != '\0')
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (NULL); /* invalid input */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *ulp = ul;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (np);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanostatic void
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanofree_holesdata(holes_info_t *hi)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_list_t *hl, *nhl;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano for (hl = hi->holes_list; hl != NULL; hl = nhl) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano nhl = hl->hl_next;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano free(hl);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->holes_list = NULL;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (hi->holesdata != NULL)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano free(hi->holesdata);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->holesdata = NULL;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * When a hole is detected, non NULL holes_info pointer is returned.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * If we are in copy-out mode, holes_list is converted to string (holesdata)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * which will be prepended to file contents. The holesdata is a character
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * string and in the format of:
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * <data size(%10u)><SP><file size(%llu)><SP>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * <SP><data off><SP><hole off><SP><data off><SP><hole off> ...
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * This string is parsed by parse_holesholes() in copy-in mode to restore
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * the sparse info.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoholes_info_t *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoget_holes_info(int fd, off_t filesz, boolean_t pass_mode)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_info_t *hi;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_list_t *hl;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano char *str, hstr[MIN_HOLES_HDRSIZE + 1];
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano size_t ninfo, len;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if ((hl = get_holes_list(fd, filesz, &ninfo)) == NULL)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (NULL);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi = e_zalloc(E_EXIT, sizeof (holes_info_t));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->holes_list = hl;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (!pass_mode) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano str = e_zalloc(E_EXIT,
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano MIN_HOLES_HDRSIZE + ninfo * (ULL_MAX_SIZE * 2));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Convert into string data, and place it to after
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * the first 2 fixed entries.
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano store_sparse_string(hl, str + MIN_HOLES_HDRSIZE, &len);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * Add the first two fixed entries. The size of holesdata
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * includes '\0' at the end of data
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) sprintf(hstr, "%10lu %20llu ",
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (ulong_t)MIN_HOLES_HDRSIZE + len + 1, filesz);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano (void) memcpy(str, hstr, MIN_HOLES_HDRSIZE);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* calc real file size without holes */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->data_size = get_compressed_filesz(hl);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->holesdata = str;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->holesdata_sz = MIN_HOLES_HDRSIZE + len + 1;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (hi);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano/*
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * The holesdata information is in the following format:
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * <data size(%10u)><SP><file size(%llu)><SP>
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * <SP><data off><SP><hole off><SP><data off><SP><hole off> ...
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * read_holes_header() allocates holes_info_t, and read the first 2
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * entries (data size and file size). The rest of holesdata is
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano * read by parse_holesdata().
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoholes_info_t *
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoread_holes_header(const char *str, off_t filesz)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_info_t *hi;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano uint64_t ull;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi = e_zalloc(E_EXIT, sizeof (holes_info_t));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* read prepended holes data size */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if ((str = get_ull_tok(str, &ull)) == NULL || *str != ' ') {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanobad:
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano free(hi);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (NULL);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->holesdata_sz = (size_t)ull;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* read original(expanded) file size */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (get_ull_tok(str, &ull) == NULL)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano goto bad;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->orig_size = (off_t)ull;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* sanity check */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (hi->holesdata_sz > filesz ||
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->holesdata_sz <= MIN_HOLES_HDRSIZE) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano goto bad;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (hi);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoint
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanoparse_holesdata(holes_info_t *hi, const char *str)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano holes_list_t *hl, **hlp;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano uint64_t ull;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano off_t loff;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* create hole list */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hlp = &hi->holes_list;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano while (*str != '\0') {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl = e_zalloc(E_EXIT, sizeof (holes_list_t));
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* link list */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl->hl_next = NULL;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano *hlp = hl;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hlp = &hl->hl_next;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* read the string token for data */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if ((str = get_ull_tok(str, &ull)) == NULL)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano goto bad;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl->hl_data = (off_t)ull;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* there must be single blank space in between */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (*str != ' ')
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano goto bad;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* read the string token for hole */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if ((str = get_ull_tok(str, &ull)) == NULL)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano goto bad;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hl->hl_hole = (off_t)ull;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* check to see if offset is in ascending order */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano loff = -1;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano for (hl = hi->holes_list; hl != NULL; hl = hl->hl_next) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (loff >= hl->hl_data)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano goto bad;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano loff = hl->hl_data;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* data and hole can be equal */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (loff > hl->hl_hole)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano goto bad;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano loff = hl->hl_hole;
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano /* The last hole offset should match original file size */
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano if (hi->orig_size != loff) {
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanobad:
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano free_holesdata(hi);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (1);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano }
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano hi->data_size = get_compressed_filesz(hi->holes_list);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano return (0);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanovoid
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakanofree_holes_info(holes_info_t *hi)
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano{
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano free_holesdata(hi);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano free(hi);
5fbb8099f56d8d460ea0bd3efafc8211fafb75f2Nobutomo Nakano}