distextract.c revision 218915
1218799Snwhitehorn/*- 2218799Snwhitehorn * Copyright (c) 2011 Nathan Whitehorn 3218799Snwhitehorn * All rights reserved. 4218799Snwhitehorn * 5218799Snwhitehorn * Redistribution and use in source and binary forms, with or without 6218799Snwhitehorn * modification, are permitted provided that the following conditions 7218799Snwhitehorn * are met: 8218799Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9218799Snwhitehorn * notice, this list of conditions and the following disclaimer. 10218799Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11218799Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12218799Snwhitehorn * documentation and/or other materials provided with the distribution. 13218799Snwhitehorn * 14218799Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15218799Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16218799Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17218799Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18218799Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19218799Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20218799Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21218799Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22218799Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23218799Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24218799Snwhitehorn * SUCH DAMAGE. 25218799Snwhitehorn * 26218799Snwhitehorn * $FreeBSD: head/usr.sbin/bsdinstall/distextract/distextract.c 218915 2011-02-21 14:28:31Z nwhitehorn $ 27218799Snwhitehorn */ 28218799Snwhitehorn 29218799Snwhitehorn#include <stdio.h> 30218799Snwhitehorn#include <errno.h> 31218799Snwhitehorn#include <limits.h> 32218799Snwhitehorn#include <archive.h> 33218799Snwhitehorn#include <dialog.h> 34218799Snwhitehorn 35218799Snwhitehornstatic int extract_files(int nfiles, const char **files); 36218799Snwhitehorn 37218799Snwhitehornint 38218799Snwhitehornmain(void) 39218799Snwhitehorn{ 40218799Snwhitehorn char *diststring = strdup(getenv("DISTRIBUTIONS")); 41218799Snwhitehorn const char **dists; 42218799Snwhitehorn int i, retval, ndists = 0; 43218799Snwhitehorn for (i = 0; diststring[i] != 0; i++) 44218799Snwhitehorn if (isspace(diststring[i]) && !isspace(diststring[i+1])) 45218799Snwhitehorn ndists++; 46218799Snwhitehorn ndists++; /* Last one */ 47218799Snwhitehorn 48218799Snwhitehorn dists = calloc(ndists, sizeof(const char *)); 49218915Snwhitehorn if (dists == NULL) { 50218915Snwhitehorn fprintf(stderr, "Out of memory!\n"); 51218915Snwhitehorn return (1); 52218915Snwhitehorn } 53218915Snwhitehorn 54218799Snwhitehorn for (i = 0; i < ndists; i++) 55218799Snwhitehorn dists[i] = strsep(&diststring, " \t"); 56218799Snwhitehorn 57218915Snwhitehorn init_dialog(stdin, stdout); 58218915Snwhitehorn dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer"); 59218915Snwhitehorn dlg_put_backtitle(); 60218915Snwhitehorn 61218915Snwhitehorn if (chdir(getenv("BSDINSTALL_CHROOT")) != 0) { 62218915Snwhitehorn char error[512]; 63218915Snwhitehorn sprintf(error, "Could could change to directory %s: %s\n", 64218915Snwhitehorn getenv("BSDINSTALL_DISTDIR"), strerror(errno)); 65218915Snwhitehorn dialog_msgbox("Error", error, 0, 0, TRUE); 66218915Snwhitehorn end_dialog(); 67218915Snwhitehorn return (1); 68218915Snwhitehorn } 69218915Snwhitehorn 70218799Snwhitehorn retval = extract_files(ndists, dists); 71218799Snwhitehorn 72218915Snwhitehorn end_dialog(); 73218915Snwhitehorn 74218799Snwhitehorn free(diststring); 75218799Snwhitehorn free(dists); 76218799Snwhitehorn 77218799Snwhitehorn return (retval); 78218799Snwhitehorn} 79218799Snwhitehorn 80218799Snwhitehornstatic int 81218799Snwhitehornextract_files(int nfiles, const char **files) 82218799Snwhitehorn{ 83218799Snwhitehorn const char *items[nfiles*2]; 84218799Snwhitehorn char path[PATH_MAX]; 85218799Snwhitehorn int archive_files[nfiles]; 86218799Snwhitehorn int total_files, current_files, archive_file; 87218799Snwhitehorn struct archive *archive; 88218799Snwhitehorn struct archive_entry *entry; 89218799Snwhitehorn char errormsg[512]; 90218799Snwhitehorn char status[8]; 91218799Snwhitehorn int i, err, progress, last_progress; 92218799Snwhitehorn 93218799Snwhitehorn err = 0; 94218799Snwhitehorn progress = 0; 95218799Snwhitehorn 96218799Snwhitehorn /* Make the transfer list for dialog */ 97218799Snwhitehorn for (i = 0; i < nfiles; i++) { 98218799Snwhitehorn items[i*2] = strrchr(files[i], '/'); 99218799Snwhitehorn if (items[i*2] != NULL) 100218799Snwhitehorn items[i*2]++; 101218799Snwhitehorn else 102218799Snwhitehorn items[i*2] = files[i]; 103218799Snwhitehorn items[i*2 + 1] = "Pending"; 104218799Snwhitehorn } 105218799Snwhitehorn 106218799Snwhitehorn dialog_msgbox("", 107218799Snwhitehorn "Checking distribution archives.\nPlease wait...", 0, 0, FALSE); 108218799Snwhitehorn 109218799Snwhitehorn /* Open all the archives */ 110218799Snwhitehorn total_files = 0; 111218799Snwhitehorn for (i = 0; i < nfiles; i++) { 112218799Snwhitehorn archive = archive_read_new(); 113218799Snwhitehorn archive_read_support_format_all(archive); 114218799Snwhitehorn archive_read_support_compression_all(archive); 115218799Snwhitehorn sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), files[i]); 116218799Snwhitehorn err = archive_read_open_filename(archive, path, 4096); 117218799Snwhitehorn if (err != ARCHIVE_OK) { 118218799Snwhitehorn snprintf(errormsg, sizeof(errormsg), 119218799Snwhitehorn "Error while extracting %s: %s\n", items[i*2], 120218799Snwhitehorn archive_error_string(archive)); 121218799Snwhitehorn items[i*2 + 1] = "Failed"; 122218799Snwhitehorn dialog_msgbox("Extract Error", errormsg, 0, 0, 123218799Snwhitehorn TRUE); 124218915Snwhitehorn return (err); 125218799Snwhitehorn } 126218799Snwhitehorn archive_files[i] = 0; 127218799Snwhitehorn while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) 128218799Snwhitehorn archive_files[i]++; 129218799Snwhitehorn total_files += archive_files[i]; 130218799Snwhitehorn archive_read_free(archive); 131218799Snwhitehorn } 132218799Snwhitehorn 133218799Snwhitehorn current_files = 0; 134218799Snwhitehorn 135218799Snwhitehorn for (i = 0; i < nfiles; i++) { 136218799Snwhitehorn archive = archive_read_new(); 137218799Snwhitehorn archive_read_support_format_all(archive); 138218799Snwhitehorn archive_read_support_compression_all(archive); 139218799Snwhitehorn sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), files[i]); 140218799Snwhitehorn err = archive_read_open_filename(archive, path, 4096); 141218799Snwhitehorn 142218799Snwhitehorn items[i*2 + 1] = "In Progress"; 143218799Snwhitehorn archive_file = 0; 144218799Snwhitehorn 145218799Snwhitehorn while ((err = archive_read_next_header(archive, &entry)) == 146218799Snwhitehorn ARCHIVE_OK) { 147218799Snwhitehorn last_progress = progress; 148218799Snwhitehorn progress = (current_files*100)/total_files; 149218799Snwhitehorn 150218799Snwhitehorn sprintf(status, "-%d", 151218799Snwhitehorn (archive_file*100)/archive_files[i]); 152218799Snwhitehorn items[i*2 + 1] = status; 153218799Snwhitehorn 154218799Snwhitehorn if (progress > last_progress) 155218799Snwhitehorn dialog_mixedgauge("Archive Extraction", 156218799Snwhitehorn "Extracting distribution files...", 0, 0, 157218799Snwhitehorn progress, nfiles, 158218799Snwhitehorn __DECONST(char **, items)); 159218799Snwhitehorn 160218799Snwhitehorn err = archive_read_extract(archive, entry, 161218799Snwhitehorn ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER | 162218799Snwhitehorn ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | 163218799Snwhitehorn ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS); 164218799Snwhitehorn 165218799Snwhitehorn if (err != ARCHIVE_OK) 166218799Snwhitehorn break; 167218799Snwhitehorn 168218799Snwhitehorn archive_file++; 169218799Snwhitehorn current_files++; 170218799Snwhitehorn } 171218799Snwhitehorn 172218799Snwhitehorn items[i*2 + 1] = "Done"; 173218799Snwhitehorn 174218799Snwhitehorn if (err != ARCHIVE_EOF) { 175218799Snwhitehorn snprintf(errormsg, sizeof(errormsg), 176218799Snwhitehorn "Error while extracting %s: %s\n", items[i*2], 177218799Snwhitehorn archive_error_string(archive)); 178218799Snwhitehorn items[i*2 + 1] = "Failed"; 179218799Snwhitehorn dialog_msgbox("Extract Error", errormsg, 0, 0, 180218799Snwhitehorn TRUE); 181218915Snwhitehorn return (err); 182218799Snwhitehorn } 183218799Snwhitehorn 184218799Snwhitehorn archive_read_free(archive); 185218799Snwhitehorn } 186218799Snwhitehorn 187218915Snwhitehorn return (0); 188218799Snwhitehorn} 189