12118f387SNathan Whitehorn /*- 22118f387SNathan Whitehorn * Copyright (c) 2011 Nathan Whitehorn 32118f387SNathan Whitehorn * All rights reserved. 42118f387SNathan Whitehorn * 52118f387SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 62118f387SNathan Whitehorn * modification, are permitted provided that the following conditions 72118f387SNathan Whitehorn * are met: 82118f387SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 92118f387SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 102118f387SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 112118f387SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 122118f387SNathan Whitehorn * documentation and/or other materials provided with the distribution. 132118f387SNathan Whitehorn * 142118f387SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 152118f387SNathan Whitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 162118f387SNathan Whitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 172118f387SNathan Whitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 182118f387SNathan Whitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 192118f387SNathan Whitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 202118f387SNathan Whitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 212118f387SNathan Whitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 222118f387SNathan Whitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 232118f387SNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 242118f387SNathan Whitehorn * SUCH DAMAGE. 252118f387SNathan Whitehorn * 262118f387SNathan Whitehorn * $FreeBSD$ 272118f387SNathan Whitehorn */ 282118f387SNathan Whitehorn 292118f387SNathan Whitehorn #include <stdio.h> 302118f387SNathan Whitehorn #include <errno.h> 312118f387SNathan Whitehorn #include <limits.h> 322118f387SNathan Whitehorn #include <archive.h> 332118f387SNathan Whitehorn #include <dialog.h> 342118f387SNathan Whitehorn 352118f387SNathan Whitehorn static int extract_files(int nfiles, const char **files); 362118f387SNathan Whitehorn 372118f387SNathan Whitehorn int 382118f387SNathan Whitehorn main(void) 392118f387SNathan Whitehorn { 402118f387SNathan Whitehorn char *diststring = strdup(getenv("DISTRIBUTIONS")); 412118f387SNathan Whitehorn const char **dists; 422118f387SNathan Whitehorn int i, retval, ndists = 0; 432118f387SNathan Whitehorn for (i = 0; diststring[i] != 0; i++) 442118f387SNathan Whitehorn if (isspace(diststring[i]) && !isspace(diststring[i+1])) 452118f387SNathan Whitehorn ndists++; 462118f387SNathan Whitehorn ndists++; /* Last one */ 472118f387SNathan Whitehorn 482118f387SNathan Whitehorn dists = calloc(ndists, sizeof(const char *)); 49*57bda1b6SNathan Whitehorn if (dists == NULL) { 50*57bda1b6SNathan Whitehorn fprintf(stderr, "Out of memory!\n"); 51*57bda1b6SNathan Whitehorn return (1); 52*57bda1b6SNathan Whitehorn } 53*57bda1b6SNathan Whitehorn 542118f387SNathan Whitehorn for (i = 0; i < ndists; i++) 552118f387SNathan Whitehorn dists[i] = strsep(&diststring, " \t"); 562118f387SNathan Whitehorn 57*57bda1b6SNathan Whitehorn init_dialog(stdin, stdout); 58*57bda1b6SNathan Whitehorn dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer"); 59*57bda1b6SNathan Whitehorn dlg_put_backtitle(); 60*57bda1b6SNathan Whitehorn 61*57bda1b6SNathan Whitehorn if (chdir(getenv("BSDINSTALL_CHROOT")) != 0) { 62*57bda1b6SNathan Whitehorn char error[512]; 63*57bda1b6SNathan Whitehorn sprintf(error, "Could could change to directory %s: %s\n", 64*57bda1b6SNathan Whitehorn getenv("BSDINSTALL_DISTDIR"), strerror(errno)); 65*57bda1b6SNathan Whitehorn dialog_msgbox("Error", error, 0, 0, TRUE); 66*57bda1b6SNathan Whitehorn end_dialog(); 67*57bda1b6SNathan Whitehorn return (1); 68*57bda1b6SNathan Whitehorn } 69*57bda1b6SNathan Whitehorn 702118f387SNathan Whitehorn retval = extract_files(ndists, dists); 712118f387SNathan Whitehorn 72*57bda1b6SNathan Whitehorn end_dialog(); 73*57bda1b6SNathan Whitehorn 742118f387SNathan Whitehorn free(diststring); 752118f387SNathan Whitehorn free(dists); 762118f387SNathan Whitehorn 772118f387SNathan Whitehorn return (retval); 782118f387SNathan Whitehorn } 792118f387SNathan Whitehorn 802118f387SNathan Whitehorn static int 812118f387SNathan Whitehorn extract_files(int nfiles, const char **files) 822118f387SNathan Whitehorn { 832118f387SNathan Whitehorn const char *items[nfiles*2]; 842118f387SNathan Whitehorn char path[PATH_MAX]; 852118f387SNathan Whitehorn int archive_files[nfiles]; 862118f387SNathan Whitehorn int total_files, current_files, archive_file; 872118f387SNathan Whitehorn struct archive *archive; 882118f387SNathan Whitehorn struct archive_entry *entry; 892118f387SNathan Whitehorn char errormsg[512]; 902118f387SNathan Whitehorn char status[8]; 912118f387SNathan Whitehorn int i, err, progress, last_progress; 922118f387SNathan Whitehorn 932118f387SNathan Whitehorn err = 0; 942118f387SNathan Whitehorn progress = 0; 952118f387SNathan Whitehorn 962118f387SNathan Whitehorn /* Make the transfer list for dialog */ 972118f387SNathan Whitehorn for (i = 0; i < nfiles; i++) { 982118f387SNathan Whitehorn items[i*2] = strrchr(files[i], '/'); 992118f387SNathan Whitehorn if (items[i*2] != NULL) 1002118f387SNathan Whitehorn items[i*2]++; 1012118f387SNathan Whitehorn else 1022118f387SNathan Whitehorn items[i*2] = files[i]; 1032118f387SNathan Whitehorn items[i*2 + 1] = "Pending"; 1042118f387SNathan Whitehorn } 1052118f387SNathan Whitehorn 1062118f387SNathan Whitehorn dialog_msgbox("", 1072118f387SNathan Whitehorn "Checking distribution archives.\nPlease wait...", 0, 0, FALSE); 1082118f387SNathan Whitehorn 1092118f387SNathan Whitehorn /* Open all the archives */ 1102118f387SNathan Whitehorn total_files = 0; 1112118f387SNathan Whitehorn for (i = 0; i < nfiles; i++) { 1122118f387SNathan Whitehorn archive = archive_read_new(); 1132118f387SNathan Whitehorn archive_read_support_format_all(archive); 1142118f387SNathan Whitehorn archive_read_support_compression_all(archive); 1152118f387SNathan Whitehorn sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), files[i]); 1162118f387SNathan Whitehorn err = archive_read_open_filename(archive, path, 4096); 1172118f387SNathan Whitehorn if (err != ARCHIVE_OK) { 1182118f387SNathan Whitehorn snprintf(errormsg, sizeof(errormsg), 1192118f387SNathan Whitehorn "Error while extracting %s: %s\n", items[i*2], 1202118f387SNathan Whitehorn archive_error_string(archive)); 1212118f387SNathan Whitehorn items[i*2 + 1] = "Failed"; 1222118f387SNathan Whitehorn dialog_msgbox("Extract Error", errormsg, 0, 0, 1232118f387SNathan Whitehorn TRUE); 124*57bda1b6SNathan Whitehorn return (err); 1252118f387SNathan Whitehorn } 1262118f387SNathan Whitehorn archive_files[i] = 0; 1272118f387SNathan Whitehorn while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) 1282118f387SNathan Whitehorn archive_files[i]++; 1292118f387SNathan Whitehorn total_files += archive_files[i]; 1302118f387SNathan Whitehorn archive_read_free(archive); 1312118f387SNathan Whitehorn } 1322118f387SNathan Whitehorn 1332118f387SNathan Whitehorn current_files = 0; 1342118f387SNathan Whitehorn 1352118f387SNathan Whitehorn for (i = 0; i < nfiles; i++) { 1362118f387SNathan Whitehorn archive = archive_read_new(); 1372118f387SNathan Whitehorn archive_read_support_format_all(archive); 1382118f387SNathan Whitehorn archive_read_support_compression_all(archive); 1392118f387SNathan Whitehorn sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), files[i]); 1402118f387SNathan Whitehorn err = archive_read_open_filename(archive, path, 4096); 1412118f387SNathan Whitehorn 1422118f387SNathan Whitehorn items[i*2 + 1] = "In Progress"; 1432118f387SNathan Whitehorn archive_file = 0; 1442118f387SNathan Whitehorn 1452118f387SNathan Whitehorn while ((err = archive_read_next_header(archive, &entry)) == 1462118f387SNathan Whitehorn ARCHIVE_OK) { 1472118f387SNathan Whitehorn last_progress = progress; 1482118f387SNathan Whitehorn progress = (current_files*100)/total_files; 1492118f387SNathan Whitehorn 1502118f387SNathan Whitehorn sprintf(status, "-%d", 1512118f387SNathan Whitehorn (archive_file*100)/archive_files[i]); 1522118f387SNathan Whitehorn items[i*2 + 1] = status; 1532118f387SNathan Whitehorn 1542118f387SNathan Whitehorn if (progress > last_progress) 1552118f387SNathan Whitehorn dialog_mixedgauge("Archive Extraction", 1562118f387SNathan Whitehorn "Extracting distribution files...", 0, 0, 1572118f387SNathan Whitehorn progress, nfiles, 1582118f387SNathan Whitehorn __DECONST(char **, items)); 1592118f387SNathan Whitehorn 1602118f387SNathan Whitehorn err = archive_read_extract(archive, entry, 1612118f387SNathan Whitehorn ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER | 1622118f387SNathan Whitehorn ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | 1632118f387SNathan Whitehorn ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS); 1642118f387SNathan Whitehorn 1652118f387SNathan Whitehorn if (err != ARCHIVE_OK) 1662118f387SNathan Whitehorn break; 1672118f387SNathan Whitehorn 1682118f387SNathan Whitehorn archive_file++; 1692118f387SNathan Whitehorn current_files++; 1702118f387SNathan Whitehorn } 1712118f387SNathan Whitehorn 1722118f387SNathan Whitehorn items[i*2 + 1] = "Done"; 1732118f387SNathan Whitehorn 1742118f387SNathan Whitehorn if (err != ARCHIVE_EOF) { 1752118f387SNathan Whitehorn snprintf(errormsg, sizeof(errormsg), 1762118f387SNathan Whitehorn "Error while extracting %s: %s\n", items[i*2], 1772118f387SNathan Whitehorn archive_error_string(archive)); 1782118f387SNathan Whitehorn items[i*2 + 1] = "Failed"; 1792118f387SNathan Whitehorn dialog_msgbox("Extract Error", errormsg, 0, 0, 1802118f387SNathan Whitehorn TRUE); 181*57bda1b6SNathan Whitehorn return (err); 1822118f387SNathan Whitehorn } 1832118f387SNathan Whitehorn 1842118f387SNathan Whitehorn archive_read_free(archive); 1852118f387SNathan Whitehorn } 1862118f387SNathan Whitehorn 187*57bda1b6SNathan Whitehorn return (0); 1882118f387SNathan Whitehorn } 189