X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Finstaller%2Fhw.c;h=d74526050037e48a1458fa04403430b631903221;hb=e6f71226c51e4d89f33415760b86b5cda49c75fd;hp=3ec4d75e0e87f3666b81d6ccb63c2d6bdb6a670b;hpb=0c8b2d994e5756f104f015302dde782596f4d2b5;p=ipfire-2.x.git diff --git a/src/installer/hw.c b/src/installer/hw.c index 3ec4d75e0e..d745260500 100644 --- a/src/installer/hw.c +++ b/src/installer/hw.c @@ -26,13 +26,16 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include +#include #include #include @@ -81,11 +84,56 @@ static int strstartswith(const char* a, const char* b) { return (strncmp(a, b, strlen(b)) == 0); } +static char loop_device[STRING_SIZE]; + +static int setup_loop_device(const char* source, const char* device) { + int file_fd = open(source, O_RDWR); + if (file_fd < 0) + goto ERROR; + + int device_fd = -1; + if ((device_fd = open(device, O_RDWR)) < 0) + goto ERROR; + + if (ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) + goto ERROR; + + close(file_fd); + close(device_fd); + + return 0; + +ERROR: + if (file_fd >= 0) + close(file_fd); + + if (device_fd >= 0) { + ioctl(device_fd, LOOP_CLR_FD, 0); + close(device_fd); + } + + return -1; +} + int hw_mount(const char* source, const char* target, const char* fs, int flags) { + const char* loop_device = "/dev/loop0"; + // Create target if it does not exist if (access(target, X_OK) != 0) mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO); + struct stat st; + stat(source, &st); + + if (S_ISREG(st.st_mode)) { + int r = setup_loop_device(source, loop_device); + if (r == 0) { + source = loop_device; + } else { + return -1; + } + } + return mount(source, target, fs, flags, NULL); } @@ -292,7 +340,7 @@ void hw_free_disks(struct hw_disk** disks) { free(disks); } -unsigned int hw_count_disks(struct hw_disk** disks) { +unsigned int hw_count_disks(const struct hw_disk** disks) { unsigned int ret = 0; while (*disks++) @@ -305,7 +353,7 @@ struct hw_disk** hw_select_disks(struct hw_disk** disks, int* selection) { struct hw_disk** ret = hw_create_disks(); struct hw_disk** selected_disks = ret; - unsigned int num_disks = hw_count_disks(disks); + unsigned int num_disks = hw_count_disks((const struct hw_disk**)disks); for (unsigned int i = 0; i < num_disks; i++) { if (!selection || selection[i]) { @@ -322,6 +370,27 @@ struct hw_disk** hw_select_disks(struct hw_disk** disks, int* selection) { return ret; } +struct hw_disk** hw_select_first_disk(const struct hw_disk** disks) { + struct hw_disk** ret = hw_create_disks(); + struct hw_disk** selected_disks = ret; + + unsigned int num_disks = hw_count_disks(disks); + assert(num_disks > 0); + + for (unsigned int i = 0; i < num_disks; i++) { + struct hw_disk *disk = disks[i]; + disk->ref++; + + *selected_disks++ = disk; + break; + } + + // Set sentinel + *selected_disks = NULL; + + return ret; +} + static unsigned long long hw_swap_size(struct hw_destination* dest) { unsigned long long memory = hw_memory(); @@ -357,11 +426,26 @@ static unsigned long long hw_boot_size(struct hw_destination* dest) { return MB2BYTES(64); } -static int hw_calculate_partition_table(struct hw_destination* dest) { +static int hw_device_has_p_suffix(const struct hw_destination* dest) { + // All RAID devices have the p suffix. + if (dest->is_raid) + return 1; + + // Devices with a number at the end have the p suffix, too. + // e.g. mmcblk0, cciss0 + unsigned int last_char = strlen(dest->path) - 1; + if ((dest->path[last_char] >= '0') && (dest->path[last_char] <= '9')) + return 1; + + return 0; +} + +static int hw_calculate_partition_table(struct hw_destination* dest, int disable_swap) { char path[DEV_SIZE]; int part_idx = 1; - snprintf(path, sizeof(path), "%s%s", dest->path, (dest->is_raid) ? "p" : ""); + snprintf(path, sizeof(path), "%s%s", dest->path, + hw_device_has_p_suffix(dest) ? "p" : ""); dest->part_boot_idx = 0; // Determine the size of the target block device @@ -409,9 +493,14 @@ static int hw_calculate_partition_table(struct hw_destination* dest) { } dest->size_boot = hw_boot_size(dest); - dest->size_swap = hw_swap_size(dest); dest->size_root = hw_root_size(dest); + // Should we use swap? + if (disable_swap) + dest->size_swap = 0; + else + dest->size_swap = hw_swap_size(dest); + // Determine the size of the data partition. unsigned long long used_space = dest->size_bootldr + dest->size_boot + dest->size_swap + dest->size_root; @@ -456,7 +545,7 @@ static int hw_calculate_partition_table(struct hw_destination* dest) { return 0; } -struct hw_destination* hw_make_destination(int part_type, struct hw_disk** disks) { +struct hw_destination* hw_make_destination(int part_type, struct hw_disk** disks, int disable_swap) { struct hw_destination* dest = malloc(sizeof(*dest)); if (part_type == HW_PART_TYPE_NORMAL) { @@ -476,7 +565,7 @@ struct hw_destination* hw_make_destination(int part_type, struct hw_disk** disks // Is this a RAID device? dest->is_raid = (part_type > HW_PART_TYPE_NORMAL); - int r = hw_calculate_partition_table(dest); + int r = hw_calculate_partition_table(dest, disable_swap); if (r) return NULL; @@ -487,23 +576,13 @@ struct hw_destination* hw_make_destination(int part_type, struct hw_disk** disks } unsigned long long hw_memory() { - FILE* handle = NULL; - char line[STRING_SIZE]; - - unsigned long long memory = 0; + struct sysinfo si; - /* Calculate amount of memory in machine */ - if ((handle = fopen("/proc/meminfo", "r"))) { - while (fgets(line, sizeof(line), handle)) { - if (!sscanf (line, "MemTotal: %llu kB", &memory)) { - memory = 0; - } - } - - fclose(handle); - } + int r = sysinfo(&si); + if (r < 0) + return 0; - return memory * 1024; + return si.totalram; } static int hw_zero_out_device(const char* path, int bytes) { @@ -955,12 +1034,13 @@ static char* hw_get_uuid(const char* dev) { return uuid; } +#define FSTAB_FMT "UUID=%s %-8s %-4s %-10s %d %d\n" + int hw_write_fstab(struct hw_destination* dest) { FILE* f = fopen(DESTINATION_MOUNT_PATH "/etc/fstab", "w"); if (!f) return -1; - const char* fmt = "UUID=%s %-8s %-4s %-10s %d %d\n"; char* uuid = NULL; // boot @@ -968,7 +1048,7 @@ int hw_write_fstab(struct hw_destination* dest) { uuid = hw_get_uuid(dest->part_boot); if (uuid) { - fprintf(f, fmt, uuid, "/boot", "auto", "defaults", 1, 2); + fprintf(f, FSTAB_FMT, uuid, "/boot", "auto", "defaults", 1, 2); free(uuid); } } @@ -978,7 +1058,7 @@ int hw_write_fstab(struct hw_destination* dest) { uuid = hw_get_uuid(dest->part_swap); if (uuid) { - fprintf(f, fmt, uuid, "swap", "swap", "defaults,pri=1", 0, 0); + fprintf(f, FSTAB_FMT, uuid, "swap", "swap", "defaults,pri=1", 0, 0); free(uuid); } } @@ -986,7 +1066,7 @@ int hw_write_fstab(struct hw_destination* dest) { // root uuid = hw_get_uuid(dest->part_root); if (uuid) { - fprintf(f, fmt, uuid, "/", "auto", "defaults", 1, 1); + fprintf(f, FSTAB_FMT, uuid, "/", "auto", "defaults", 1, 1); free(uuid); } @@ -995,7 +1075,7 @@ int hw_write_fstab(struct hw_destination* dest) { uuid = hw_get_uuid(dest->part_data); if (uuid) { - fprintf(f, fmt, uuid, "/var", "auto", "defaults", 1, 1); + fprintf(f, FSTAB_FMT, uuid, "/var", "auto", "defaults", 1, 1); free(uuid); } } @@ -1010,3 +1090,31 @@ void hw_sync() { sync(); sync(); } + +int hw_start_networking(const char* output) { + return mysystem(output, "/usr/bin/start-networking.sh"); +} + +char* hw_find_backup_file(const char* output, const char* search_path) { + char path[STRING_SIZE]; + + snprintf(path, sizeof(path), "%s/backup.ipf", search_path); + int r = access(path, R_OK); + + if (r == 0) + return strdup(path); + + return NULL; +} + +int hw_restore_backup(const char* output, const char* backup_path, const char* destination) { + char command[STRING_SIZE]; + + snprintf(command, sizeof(command), "/bin/tar xzpf %s -C %s", backup_path, destination); + int rc = mysystem(output, command); + + if (rc) + return -1; + + return 0; +}