[debian-knoppix] ANNOUNCE: Tool for customizing Knoppix ISO-image before burning w/o remastering
Hi,
Due to high demand I am releasing my current development version of
the knoppix-customize tool. This version is still alpha and intended
for developers. License: GPL. Language ANSI-C.
Build:
make knoppix-customize
Documentation:
./knoppix-customize --help
Examples:
List files in the boot-floppy (you can specify a 1.44MB boot floppy or
the 700 MB ISO-Image):
knoppix-customize --image boot.img --action list
Copy the file syslinux.cfg from the floppy or iso-image to a local file:
knoppix-customize --image boot.img --action export_file --image_file syslinux.cfg --local_file syslinux.cfg
Now you may edit syslinux.cfg. Make sure the size doesn't change!
(Some editors may add newlines)
Copy the local file you just edited into the image:
knoppix-customize --image boot.img --action import_file --image_file syslinux.cfg --local_file syslinux.cfg
You may also exchange other files like the kbdmap or the boot message screen.
2002-10-23 Kester Habermann <kester@linuxtag.org>
--
Kester Habermann <kester@linuxtag.org> LinuxTag 2002
http://www.linuxtag.org/ Tel: +49.631.3109371 Fax: +49.631.3109372
/* ----------------------------------------------------------------------- *
*
* Copyright 2002 Kester Habermann - All Rights Reserved
* 2002-08-30 Kester Habermann <kester@linuxtag.org>
* Time-stamp: <2002-10-11 11:50:33 kester>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
* USA; either version 2 of the License, or (at your option) any later
* version; incorporated herein by reference.
*
* ----------------------------------------------------------------------- */
// TOOD:
// - test if sizes are ok
// - proper header for all error messages
// - copyright, version, author info
// - multi languages
// - renaming of files (to remember which kbd map is used)
// - clean up output for verbose
// - action to replace complete boot floppy image 8read blockwise)
// - shortcuts:
// * edit boot options for userdef and set userdef as defaults
// * set boot options for userdef
// * set default boot
// * change language (lang=xx + userdef default), keyboard-file, help-file
// - add URL for El-Torito and FAT-Specification
// BUGs
// - if given FAT name st longer than 8+3 chars it is truncated
// (should give error)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <libgen.h>
// Sector size for FAT12 and FAT16
#define FAT_SECTOR_SIZE 0x200
#define FLOPPY_BOOT_SECTOR (1* FAT_SECTOR_SIZE)
#define CD_SECTOR_SIZE 0x800
#define CD_BOOT_RECORD_VOLUME_DESCRIPTOR (1 * CD_SECTOR_SIZE)
#define CD_BOOT_CAT_BUFFER (1 * CD_SECTOR_SIZE)
// Boot-Disc Types
// Sides * Tracks * Sectors/Track * Bytes/Block
#define BOOT_IMG_BUFFER_1_2 (2 * 15 * 80 * 512)
#define BOOT_IMG_BUFFER_1_44 (2 * 18 * 80 * 512)
#define BOOT_IMG_BUFFER_2_88 (2 * 36 * 80 * 512)
#define FLOPPY_1_2 "1.2 MB diskette"
#define FLOPPY_1_44 "1.44 MB diskette"
#define FLOPPY_2_88 "2.88 MB diskette"
#define ISO_9660_IDENTIFIER "CD001"
#define CD_BOOT_SYSTEM_INDENTIFIER "EL TORITO SPECIFICATION"
#define MANUFACTOR_MAXLEN 24
#define FAT_FILENAME_LENGTH 11
#define FAT_ENTRY_SIZE 32
#define MAX_PATH_LEN 1024
// one directory entry
struct dir_entry_t {
unsigned char name[FAT_FILENAME_LENGTH + 1];
long pos;
long size;
};
// important data from boot floppy
struct boot_floppy_t {
long boot_img_offset;
size_t boot_img_size;
int FirstRootDirSecNum;
int BytesPerCluster;
struct dir_entry_t *fat_root_dir;
int fat_root_dir_size;
};
// Global variables
int opt_verbose = 0;
int find_boot_image(FILE *fh, struct stat stat_buf, struct boot_floppy_t *boot_floppy) {
unsigned char *floppy_boot_sector; // buffer for boot record volume descriptor
unsigned char *cd_boot_rvd; // buffer for boot record volume descriptor
unsigned char *cd_boot_cat; // buffer for boot catalog
char cd_manufactor[MANUFACTOR_MAXLEN];
long cd_boot_cat_ptr;
long cd_boot_img_ptr;
// allocate read_buffer for reading boot record volume descriptor
if ((cd_boot_rvd = malloc((size_t) (CD_BOOT_RECORD_VOLUME_DESCRIPTOR))) == NULL) {
fprintf(stderr, "Error mallocing CD boot record volume descriptor\n");
return 0;
}
// allocate read_buffer for reading boot catalog
if ((cd_boot_cat = malloc((size_t) (CD_BOOT_CAT_BUFFER))) == NULL) {
fprintf(stderr, "Error mallocing CD boot cat buffer\n");
return 0;
}
// allocate read_buffer for reading floppy boot sector
if ((floppy_boot_sector = malloc((size_t) (FLOPPY_BOOT_SECTOR))) == NULL) {
fprintf(stderr, "Error mallocing floppy boot sector buffer\n");
return 0;
}
// read first sectors of size FAT_SECTOR, to see if it's FAT
if (fread(((void *) floppy_boot_sector),
(size_t) FLOPPY_BOOT_SECTOR,
(size_t) 1,
fh) < 1) {
fprintf(stderr, "Error reading first sector from image\n");
return 0;
}
// Test whether image ist FAT, this is the case if someone chooses
// to only modify a boot disk and not the whole book image
// Search for FAT-Magic 0x55AA
if (floppy_boot_sector[0x1fe] == 0x55 && floppy_boot_sector[0x1ff] == 0xAA) {
if (opt_verbose) printf("Image is FAT, assuming floppy\n");
boot_floppy->boot_img_offset = 0;
// find out actual size of disk image
switch (stat_buf.st_size) {
case BOOT_IMG_BUFFER_1_2: if (opt_verbose) printf("Image is %s\n", FLOPPY_1_2);
boot_floppy->boot_img_size = BOOT_IMG_BUFFER_1_2;
break;
case BOOT_IMG_BUFFER_1_44: if (opt_verbose) printf("Image is %s\n", FLOPPY_1_44);
boot_floppy->boot_img_size = BOOT_IMG_BUFFER_1_44;
break;
case BOOT_IMG_BUFFER_2_88: if (opt_verbose) printf("Image is %s\n", FLOPPY_2_88);
boot_floppy->boot_img_size = BOOT_IMG_BUFFER_2_88;
break;
default: fprintf(stderr, "Invalid disk image size (%d)\n", stat_buf.st_size);
return 0;
break;
}
return 1;
}
//
// Read CD-Image
//
if (opt_verbose) printf("Image is not FAT, assuming ISO\n");
// read boot volume descriptor
if (fseek(fh, (long) (0x11 * CD_SECTOR_SIZE), SEEK_SET) != 0) {
fprintf(stderr, "Error seeking into file\n");
return 0;
}
if (fread(((void *) cd_boot_rvd),
(size_t) CD_BOOT_RECORD_VOLUME_DESCRIPTOR,
(size_t) 1,
fh) < 1) {
fprintf(stderr, "Error reading cd boot volume descriptor\n");
return 0;
}
if (cd_boot_rvd[0x00] != 0) {
fprintf(stderr, "Invalid CD Boot Record Indicator\n");
return 0;
}
if (strncmp(cd_boot_rvd + 0x01, ISO_9660_IDENTIFIER, (size_t) sizeof(ISO_9660_IDENTIFIER) != 0)) {
fprintf(stderr, "Not ISO 9660 image\n");
return 0;
}
if (strncmp(cd_boot_rvd + 0x07, CD_BOOT_SYSTEM_INDENTIFIER, (size_t) sizeof(CD_BOOT_SYSTEM_INDENTIFIER) != 0)) {
fprintf(stderr, "Not El Torito Bootable\n");
return 0;
}
cd_boot_cat_ptr = ( cd_boot_rvd[0x47 + 3] << 24 )
+ ( cd_boot_rvd[0x47 + 2] << 16 )
+ ( cd_boot_rvd[0x47 + 1] << 8 )
+ ( cd_boot_rvd[0x47 + 0] );
if (opt_verbose) printf("boot cat ptr: 0x%.8x x 0x800 (0x%.8x)\n", cd_boot_cat_ptr, CD_SECTOR_SIZE * cd_boot_cat_ptr);
// seek to boot catalog
fseek(fh, (long) CD_SECTOR_SIZE * cd_boot_cat_ptr, SEEK_SET);
if (!(fread(((void *) cd_boot_cat),
(size_t) CD_BOOT_CAT_BUFFER,
(size_t) 1,
fh))) {
fprintf(stderr, "Error reading CD boot cat\n");
return 0;
}
if (cd_boot_cat[0] != 01) {
fprintf(stderr, "Header ID, must be 01\n");
return 0;
}
switch(cd_boot_cat[1]) {
case 0: if (opt_verbose) printf("Platform 80x86\n");
break;
case 1: if (opt_verbose) printf("Platform Power PC\n");
break;
case 2: if (opt_verbose) printf("Platform MAC\n");
break;
default: fprintf(stderr, "Platform unknown\n");
return 0;
break;
}
strncpy(cd_manufactor, cd_boot_cat + 0x04, MANUFACTOR_MAXLEN);
if (opt_verbose) printf("Manufactor: %s\n", cd_manufactor);
switch (cd_boot_cat[0x20 + 0x00]) {
case 0x00: fprintf(stderr, "CD Not Bootable!\n");
return 0;
break;
case 0x88: if (opt_verbose) printf("CD Bootable!\n");
break;
default: fprintf(stderr, "Invalid Boot Indicator on CD\n");
return 0;
break;
}
if (opt_verbose) printf("Boot media type on CD: ");
switch (cd_boot_cat[0x20 + 0x01]) {
case 0x00: fprintf(stderr, "No emulation (can't handle this)\n");
return 0;
break;
case 0x01: if (opt_verbose) printf("%s\n", FLOPPY_1_2);
boot_floppy->boot_img_size = BOOT_IMG_BUFFER_1_2;
break;
case 0x02: if (opt_verbose) printf("%s\n", FLOPPY_1_44);
boot_floppy->boot_img_size = BOOT_IMG_BUFFER_1_44;
break;
case 0x03: if (opt_verbose) printf("%s\n", FLOPPY_2_88);
boot_floppy->boot_img_size = BOOT_IMG_BUFFER_2_88;
break;
case 0x04: fprintf(stderr, "Harddisk (can't handle this)\n");
return 0;
break;
default: fprintf(stderr, "Invalid Boot media type\n");
return 0;
break;
}
cd_boot_img_ptr = ( cd_boot_cat[0x20 + 0x08 + 3] << 24 )
+ ( cd_boot_cat[0x20 + 0x08 + 2] << 16 )
+ ( cd_boot_cat[0x20 + 0x08 + 1] << 8 )
+ ( cd_boot_cat[0x20 + 0x08 + 0] );
boot_floppy->boot_img_offset = CD_SECTOR_SIZE * cd_boot_img_ptr;
if (opt_verbose) printf("boot img ptr: 0x%.8x x 0x800 (0x%.8x)\n", cd_boot_img_ptr, boot_floppy->boot_img_offset);
return 1;
}
int get_fat_root_dir (FILE *fh, struct boot_floppy_t *boot_floppy) {
FILE *fh2;
unsigned char *boot_img; // buffer for boot image
unsigned char *floppy_boot_sector; // buffer for boot record volume descriptor
unsigned int BPB_BytsPerSec;
unsigned char BPB_SecPerClus;
unsigned int BPB_RsvdSecCnt;
unsigned char BPB_NumFATs;
unsigned int BPB_FATSz16;
unsigned char *fat_root_dir_buffer;
int fat_root_dir_buffer_size;
int i, j;
//
// Read Floppy-Image
//
// allocate read_buffer for reading boot image
if ((boot_img = malloc(boot_floppy->boot_img_size)) == NULL) {
fprintf(stderr, "Error mallocing CD boot img buffer\n");
return 0;
}
if (opt_verbose) printf("\nReading boot image ...\n");
// seek to boot image
fseek(fh, boot_floppy->boot_img_offset, SEEK_SET);
// allocate read_buffer for reading floppy boot sector
if ((floppy_boot_sector = malloc((size_t) (FLOPPY_BOOT_SECTOR))) == NULL) {
fprintf(stderr, "Error mallocing floppy boot sector buffer\n");
return 0;
}
// read first floppy boot sector
if (fread(((void *) floppy_boot_sector),
(size_t) FLOPPY_BOOT_SECTOR,
(size_t) 1,
fh) < 1) {
fprintf(stderr, "Error reading boot sector from image\n");
return 0;
}
BPB_BytsPerSec = ( floppy_boot_sector[12] << 8 )
+ ( floppy_boot_sector[11] );
BPB_SecPerClus = floppy_boot_sector[13];
boot_floppy->BytesPerCluster = BPB_SecPerClus * BPB_BytsPerSec;
BPB_RsvdSecCnt = ( floppy_boot_sector[15] << 8 )
+ ( floppy_boot_sector[14] );
BPB_NumFATs = floppy_boot_sector[16];
BPB_FATSz16 = ( floppy_boot_sector[23] << 8 )
+ ( floppy_boot_sector[22] );
fat_root_dir_buffer_size = BPB_NumFATs * BPB_BytsPerSec;
boot_floppy->FirstRootDirSecNum = BPB_RsvdSecCnt + (BPB_NumFATs * BPB_FATSz16);
if (opt_verbose) printf("BPB_BytsPerSec: %d\n", BPB_BytsPerSec);
if (opt_verbose) printf("BPB_SecPerClus: %d\n", BPB_SecPerClus);
if (opt_verbose) printf("BPB_RsvdSecCnt: %d\n", BPB_RsvdSecCnt);
if (opt_verbose) printf("BPB_NumFATs: %d\n", BPB_NumFATs);
if (opt_verbose) printf("BPB_FATSz16: %d\n", BPB_FATSz16);
if (opt_verbose) printf("\n");
if (opt_verbose) printf("FAT Root Dir Buffer Size: %d\n", fat_root_dir_buffer_size);
if (opt_verbose) printf("FirstRootDirSecNum: %d\n", boot_floppy->FirstRootDirSecNum);
if (opt_verbose) printf("\n");
// allocate buffer for FAT root dir
if ((fat_root_dir_buffer = malloc((size_t) (fat_root_dir_buffer_size))) == NULL) {
fprintf(stderr, "Error mallocing for FAT root-Rootdir\n");
return 0;
}
// seek to FirstRootDirSecNum
if (fseek(fh, boot_floppy->boot_img_offset + (long) (boot_floppy->FirstRootDirSecNum * BPB_BytsPerSec), SEEK_SET) != 0) {
fprintf(stderr, "Error seeking into file\n");
return 0;
}
// read FirstRootDirSecNum
if (fread(((void *) fat_root_dir_buffer),
(size_t) fat_root_dir_buffer_size,
(size_t) 1,
fh) < 1) {
fprintf(stderr, "Error fat root dir\n");
return 0;
}
// Count directory entries
boot_floppy->fat_root_dir_size = 0;
for (i = 0; i <= fat_root_dir_buffer_size - FAT_ENTRY_SIZE; i += FAT_ENTRY_SIZE) {
// empty entry
if (fat_root_dir_buffer[i] == 0xE5)
continue;
// no more entries
if (fat_root_dir_buffer[i] == 0x00)
break;
boot_floppy->fat_root_dir_size++;
}
if (opt_verbose) printf("FAT root dir size: %d\n", boot_floppy->fat_root_dir_size);
// allocate buffer for FAT root dir
if ((boot_floppy->fat_root_dir = malloc((size_t) (boot_floppy->fat_root_dir_size * FAT_ENTRY_SIZE))) == NULL) {
fprintf(stderr, "Error mallocing for FAT root-Rootdir\n");
return 0;
}
j = 0;
for (i = 0; i <= fat_root_dir_buffer_size - FAT_ENTRY_SIZE; i += FAT_ENTRY_SIZE) {
// empty entry
if (fat_root_dir_buffer[i] == 0xE5)
continue;
// no more entries
if (fat_root_dir_buffer[i] == 0x00)
break;
strncpy(boot_floppy->fat_root_dir[j].name, fat_root_dir_buffer + i, (size_t) FAT_FILENAME_LENGTH);
boot_floppy->fat_root_dir[j].name[FAT_FILENAME_LENGTH] = '\0';
boot_floppy->fat_root_dir[j].pos = ( fat_root_dir_buffer[i + 21] << 24 )
+ ( fat_root_dir_buffer[i + 20] << 16 )
+ ( fat_root_dir_buffer[i + 27] << 8 )
+ ( fat_root_dir_buffer[i + 26] );
boot_floppy->fat_root_dir[j].size = ( fat_root_dir_buffer[i + 31] << 24 )
+ ( fat_root_dir_buffer[i + 30] << 16 )
+ ( fat_root_dir_buffer[i + 29] << 8 )
+ ( fat_root_dir_buffer[i + 28] );
j++;
}
free(fat_root_dir_buffer);
return 1;
}
// convert file name to fat file name
void filename2fat(unsigned char *dst, const unsigned char *src) {
int i, j, dot_pos;
// convert searched filename to fat filename
// - uppercase
// - remove dot
// - fill gap and end with spaces
j = 0;
for (i = 0; i <= strlen(src) - 1; i++) {
if (src[i] == '.') {
while(j <= FAT_FILENAME_LENGTH - 4) {
dst[j] = ' ';
j++;
}
} else {
dst[j] = toupper(src[i]);
j++;
}
}
while(j <= FAT_FILENAME_LENGTH - 1) {
dst[j] = ' ';
j++;
}
dst[FAT_FILENAME_LENGTH] = '\0';
}
void fat2filename(unsigned char *dst, const unsigned char *src) {
int i, j;
for (i = 0; i <= strlen(src); i++) {
if (src[i] == ' ' || src[i] == '\0' || i >= FAT_FILENAME_LENGTH - 3)
break;
dst[i] = tolower(src[i]);
}
j = FAT_FILENAME_LENGTH - 3;
if (src[j] != ' ' && src[j] != '\0') {
dst[i++] = '.';
for (; j <= strlen(src); j++) {
if (src[j] == ' ' || src[j] == '\0' || j >= FAT_FILENAME_LENGTH)
break;
dst[i++] = tolower(src[j]);
}
}
dst[i] = '\0';
}
int file_exists_in_image(const unsigned char *fname, struct boot_floppy_t *boot_floppy) {
int i;
int found = 0;
unsigned char fatname[FAT_FILENAME_LENGTH + 2];
filename2fat(fatname, fname);
for (i = 0; i <= boot_floppy->fat_root_dir_size - 1; i++) {
if (strncmp(boot_floppy->fat_root_dir[i].name, fatname, FAT_FILENAME_LENGTH) == 0) {
found = 1;
break;
}
}
return found;
}
void show_root_dir(struct boot_floppy_t *boot_floppy) {
int i;
for (i = 0; i <= boot_floppy->fat_root_dir_size - 1; i++) {
if (opt_verbose) printf("File: '%s' Pos: %8d, Size: %8d\n", boot_floppy->fat_root_dir[i].name,
boot_floppy->fat_root_dir[i].pos,
boot_floppy->fat_root_dir[i].size);
}
}
void list_files(struct boot_floppy_t *boot_floppy) {
int i;
unsigned char fname[FAT_FILENAME_LENGTH + 2];
for (i = 0; i <= boot_floppy->fat_root_dir_size - 1; i++) {
fat2filename(fname, boot_floppy->fat_root_dir[i].name);
printf("%s\n", fname);
}
}
struct dir_entry_t get_dir_entry(const unsigned char *fname, struct boot_floppy_t *boot_floppy) {
unsigned char fat_name[FAT_FILENAME_LENGTH + 2];
int i;
struct dir_entry_t dir_entry;
filename2fat(fat_name, fname);
for (i = 0; i <= boot_floppy->fat_root_dir_size - 1; i++) {
if (strncmp(boot_floppy->fat_root_dir[i].name, fat_name, FAT_FILENAME_LENGTH) == 0) {
strncpy(dir_entry.name, boot_floppy->fat_root_dir[i].name, FAT_FILENAME_LENGTH);
dir_entry.pos = boot_floppy->fat_root_dir[i].pos;
dir_entry.size = boot_floppy->fat_root_dir[i].size;
break;
}
}
if (opt_verbose) printf("File: [%s], Pos: %d, Size: %d\n", fname, dir_entry.pos, dir_entry.size);
return dir_entry;
}
int read_file(FILE *fh, struct boot_floppy_t *boot_floppy, struct dir_entry_t dir_entry, unsigned char *buffer) {
int i;
// seek to file
if (fseek(fh,
(long) (boot_floppy->boot_img_offset + (dir_entry.pos + boot_floppy->FirstRootDirSecNum - 1) * boot_floppy->BytesPerCluster),
SEEK_SET) != 0) {
fprintf(stderr, "Error seeking into file\n");
return 0;
}
// read file into buffer
if (fread(((void *) buffer),
(size_t) dir_entry.size,
(size_t) 1,
fh) < 1) {
fprintf(stderr, "Error reading file\n");
return 0;
}
return 1;
}
int write_file(FILE *fh, struct boot_floppy_t *boot_floppy, struct dir_entry_t dir_entry, unsigned char *buffer) {
int i;
// seek to file
if (fseek(fh,
(long) (boot_floppy->boot_img_offset + (dir_entry.pos + boot_floppy->FirstRootDirSecNum - 1) * boot_floppy->BytesPerCluster),
SEEK_SET) != 0) {
fprintf(stderr, "Error seeking into file\n");
return 0;
}
// read file into buffer
if (fwrite(((void *) buffer),
(size_t) dir_entry.size,
(size_t) 1,
fh) < 1) {
fprintf(stderr, "Error writing file\n");
return 0;
}
return 1;
}
void show_buffer(unsigned char *buffer, long size) {
int i;
if (opt_verbose) printf("File-Contents:\n");
if (opt_verbose) printf("---------------->\n");
for (i = 0; i <= size - 1; i++)
if (opt_verbose) printf("%c", buffer[i]);
if (opt_verbose) printf("<----------------\n");
}
int output_buffer(FILE *fh, unsigned char *buffer, long size) {
if (fwrite(((void *) buffer),
(size_t) size,
(size_t) 1,
fh) < 1) {
fprintf(stderr, "Error outputting file\n");
}
return 1;
}
int export_to_local_file (FILE *fh, struct boot_floppy_t *boot_floppy, const unsigned char *image_file, const unsigned char *local_file) {
FILE *fh2;
unsigned char *buffer;
struct dir_entry_t dir_entry;
dir_entry = get_dir_entry(image_file, boot_floppy);
// allocate read_buffer for reading file
if ((buffer = malloc((size_t) (dir_entry.size))) == NULL) {
fprintf(stderr, "Error mallocing buffer for reading file\n");
return 0;
}
if (read_file(fh, boot_floppy, dir_entry, buffer) == 0) {
fprintf(stderr, "Error reading file. Aborting\n");
return 0;
}
if ((fh2 = fopen(local_file, "w")) == NULL) {
fprintf(stderr, "Error writing file '%s'\n", local_file);
return 0;
}
if(output_buffer(fh2, buffer, dir_entry.size) == 0) {
fprintf(stderr, "Error outputting buffer. Aborting\n");
fclose(fh2);
return 0;
}
fclose(fh2);
free(buffer);
return 1;
}
int import_from_local_file(FILE *fh, struct boot_floppy_t *boot_floppy, const unsigned char *image_file, const unsigned char *local_file) {
FILE *fh2;
unsigned char *buffer;
struct dir_entry_t dir_entry;
dir_entry = get_dir_entry(image_file, boot_floppy);
// allocate read_buffer for reading file
if ((buffer = malloc((size_t) (dir_entry.size))) == NULL) {
fprintf(stderr, "Error mallocing buffer for reading file\n");
return 0;
}
if ((fh2 = fopen(local_file, "r")) == NULL) {
fprintf(stderr, "Error reading file '%s'\n", local_file);
return 0;
}
// read local file into buffer
if (fread(((void *) buffer),
(size_t) dir_entry.size,
(size_t) 1,
fh2) < 1) {
fprintf(stderr, "Error reading local file\n");
return 0;
}
if (write_file(fh, boot_floppy, dir_entry, buffer) == 0) {
fprintf(stderr, "Error writing file. Aborting\n");
return 0;
}
fclose(fh2);
free(buffer);
return 1;
}
void show_help(char *name) {
fprintf(stderr, "Usage: %s [OPTION]\n", name);
fprintf(stderr, " --action ACTION action to perform. Mandatory!\n");
fprintf(stderr, " list list files in boot image\n");
fprintf(stderr, " export_file export file from image to localfile\n");
fprintf(stderr, " import_file import local file into image\n");
fprintf(stderr, "\n");
fprintf(stderr, " --image KNOPPIX-Image-File the Knoppix image to customize. Mandatory!\n");
fprintf(stderr, "\n");
fprintf(stderr, " --local_file filename file on local filesystem.\n");
fprintf(stderr, " Mandatory with --action export_file and import_file\n");
fprintf(stderr, "\n");
fprintf(stderr, " --image_file filename file in the image'\n");
fprintf(stderr, " Mandatory with --action export_file and import_file\n");
fprintf(stderr, "\n");
fprintf(stderr, " --verbose be verbose\n");
fprintf(stderr, "\n");
fprintf(stderr, " --help this help\n");
}
int main(int argc, char **argv) {
char *knoppix_image_filename;
struct stat stat_buf, stat_buf2;
FILE *fh, *fh2;
struct boot_floppy_t boot_floppy;
int c;
int opt_help = 0;
int opt_local_file = 0;
int opt_image_file = 0;
int opt_image = 0;
int opt_action = 0;
int cmd_list = 0;
int cmd_export_file = 0;
int cmd_import_file = 0;
char local_filename[MAX_PATH_LEN];
char image_filename[FAT_FILENAME_LENGTH + 2];
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"help", 0, 0, 0},
{"verbose", 0, 0, 0},
{"action", 1, 0, 0},
{"local_file", 1, 0, 0},
{"image_file", 1, 0, 0},
{"image", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "", long_options, &option_index);
if (c == -1)
break;
if (c == 0) {
if (strncmp(long_options[option_index].name, "help", 4) == 0) {
opt_help = 1;
continue;
}
if (strncmp(long_options[option_index].name, "verbose", 7) == 0) {
opt_verbose = 1;
continue;
}
if (strncmp(long_options[option_index].name, "local_file", 10) == 0) {
opt_local_file = 1;
strncpy(local_filename, optarg, MAX_PATH_LEN);
continue;
}
if (strncmp(long_options[option_index].name, "image_file", 10) == 0) {
opt_image_file = 1;
strncpy(image_filename, optarg, FAT_FILENAME_LENGTH + 1);
continue;
}
if (strncmp(long_options[option_index].name, "image", 5) == 0) {
opt_image = 1;
strncpy(knoppix_image_filename, optarg, FAT_FILENAME_LENGTH + 1);
continue;
}
if (strncmp(long_options[option_index].name, "action", 6) == 0) {
opt_action = 1;
if (strncmp(optarg, "list", 4) == 0)
cmd_list = 1;
else if (strncmp(optarg, "export_file", 10) == 0)
cmd_export_file = 1;
else if (strncmp(optarg, "import_file", 10) == 0)
cmd_import_file = 1;
continue;
}
}
}
// there should be no further arguments
if (optind < argc) {
fprintf(stderr, "Usage: %s [OPTION]\n", argv[0]);
fprintf(stderr, " Unknown arguments: ");
while (optind < argc)
fprintf(stderr, "%s ", argv[optind++]);
fprintf(stderr, "\n");
fprintf(stderr, " try --help for more information\n");
exit(1);
}
// show help
if (opt_help) {
show_help(basename(argv[0]));
exit(0);
}
// --image and --action are mandatory
if (! opt_image || ! opt_action) {
fprintf(stderr, "Usage: %s [OPTION]\n", argv[0]);
fprintf(stderr, " --image and --action are mandatory\n");
fprintf(stderr, " try --help for more information\n");
exit(1);
}
// --local_file and image_file are mandatory for --export_file and --import_file
if ((cmd_export_file || cmd_import_file) && ! (opt_local_file && opt_image_file)) {
fprintf(stderr, "Usage: %s [OPTION]\n", argv[0]);
fprintf(stderr, " --local_file and --image_file are mandatory with\n");
fprintf(stderr, " --action export_file and --action import_file\n");
fprintf(stderr, " try --help for more information\n");
exit(1);
}
// test if image exists
if (stat(knoppix_image_filename, &stat_buf) != 0) {
fprintf(stderr, "Error: Could not stat image file '%s'\n", knoppix_image_filename);
exit(2);
}
// test if local_file exists
if (cmd_import_file && (stat(local_filename, &stat_buf2) != 0)) {
fprintf(stderr, "Error: Could not stat local file '%s'\n", local_filename);
exit(2);
}
// open the image file for reading and writing
if (cmd_import_file) {
if ((fh = fopen(knoppix_image_filename, "r+")) == NULL) {
fprintf(stderr, "Error opening image '%s' for read/write\n", knoppix_image_filename);
exit(2);
}
} else {
if ((fh = fopen(knoppix_image_filename, "r")) == NULL) {
fprintf(stderr, "Error opening image '%s' for read\n", knoppix_image_filename);
exit(2);
}
}
// find out if it's ISO or Floppy-image, in ISO find the floppy image
if (find_boot_image(fh, stat_buf, &boot_floppy) == 0) {
fprintf(stderr, "Error reading image. Aborting\n");
fclose(fh);
exit(3);
}
// Get the boot floppy's root directory
if (get_fat_root_dir(fh, &boot_floppy) == 0) {
fprintf(stderr, "Error parsing boot image. Aborting\n");
fclose(fh);
exit(3);
}
if (opt_verbose)
show_root_dir(&boot_floppy);
// test if image_file exists
// can only test this after reading the image
if ((cmd_import_file || cmd_export_file) && !file_exists_in_image(image_filename, &boot_floppy)) {
fprintf(stderr, "Error: image_file '%s' not in image\n", image_filename);
exit(2);
}
// list files on boot floppy
if (cmd_list)
list_files(&boot_floppy);
// export file from image to filesystem
if (cmd_export_file)
if(export_to_local_file(fh, &boot_floppy, image_filename, local_filename) == 0) {
fprintf(stderr, "Error exporting file to local file. Aborting\n");
fclose(fh);
exit(3);
}
// import file from filesystem into image
if (cmd_import_file)
if(import_from_local_file(fh, &boot_floppy, image_filename, local_filename) == 0) {
fprintf(stderr, "Error importing file from local file and writing zo image. Aborting\n");
fclose(fh);
exit(3);
}
fclose(fh);
exit(0);
}
Reply to: