diff --git a/modules/rosapps/applications/devutils/cdmake/CMakeLists.txt b/modules/rosapps/applications/devutils/cdmake/CMakeLists.txt deleted file mode 100644 index caaeb070884..00000000000 --- a/modules/rosapps/applications/devutils/cdmake/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ - -add_host_tool(cdmake cdmake.c dirhash.c llmsort.c) diff --git a/modules/rosapps/applications/devutils/cdmake/cdmake.c b/modules/rosapps/applications/devutils/cdmake/cdmake.c deleted file mode 100644 index dd05ed51ec6..00000000000 --- a/modules/rosapps/applications/devutils/cdmake/cdmake.c +++ /dev/null @@ -1,2446 +0,0 @@ -/* - * CD-ROM Maker - * by Philip J. Erdelsky - * pje@acm.org - * http://alumnus.caltech.edu/~pje/ - * - * http://alumnus.caltech.edu/~pje/cdmake.txt - * - * According to his website, this file was released into the public domain - * by Philip J. Erdelsky. - */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS CD-ROM Maker - * FILE: tools/cdmake/cdmake.c - * PURPOSE: CD-ROM Premastering Utility - * PROGRAMMERS: Eric Kohl - * Casper S. Hornstrup - * Filip Navara - * Magnus Olsen - * Hermes Belusca-Maito - * - * HISTORY: - * - * ElTorito-Support - * by Eric Kohl - * - * Linux port - * by Casper S. Hornstrup - * chorns@users.sourceforge.net - * - * Joliet support - * by Filip Navara - * xnavara@volny.cz - * Limitations: - * - No Joliet file name validations - * - Very bad ISO file name generation - * - * Convert long filename to ISO9660 file name by Magnus Olsen - * magnus@greatlord.com - */ - -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# include -# include -# include -# ifdef _MSC_VER -# define R_OK 4 -# endif -#else -# if defined(__FreeBSD__) || defined(__APPLE__) -# include -# else -# include -# endif // __FreeBSD__ -# include -# include -# include -# include -# define TRUE 1 -# define FALSE 0 -#endif // _WIN32 -#include -#include -#include "config.h" -#include "dirhash.h" - -// FIXME! FIXME! Do it in a portable way!! -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; -typedef int BOOL; - -// file system parameters - -#define MAX_LEVEL 8 -#define MAX_NAME_LENGTH 64 -#define MAX_CDNAME_LENGTH 8 -#define MAX_EXTENSION_LENGTH 10 -#define MAX_CDEXTENSION_LENGTH 3 -#define SECTOR_SIZE 2048 -#define BUFFER_SIZE (8 * SECTOR_SIZE) - -#define HIDDEN_FLAG 1 -#define DIRECTORY_FLAG 2 - - -struct cd_image -{ - FILE *file; - DWORD sector; // sector to receive next byte - int offset; // offset of next byte in sector - int count; // number of bytes in buffer - char filespecs[128]; - BYTE *buffer; -}; - -typedef struct _boot_validation_header -{ - BYTE header_id; - BYTE platform_id; -} BOOT_VALIDATION_HEADER, *PBOOT_VALIDATION_HEADER; - -typedef struct boot_entry -{ - struct boot_entry *next_entry; - BYTE boot_id; - BYTE boot_emu_type; - WORD load_segment; - BYTE system_type; - WORD sector_count; // boot_image_size - DWORD load_rba; // boot_image_sector - // BYTE unused[20]; - char bootimage[512]; -} BOOT_ENTRY, *PBOOT_ENTRY; - -typedef struct boot_header -{ - struct boot_header *next_header; - BYTE header_id; - BYTE platform_id; - WORD num_entries; - // char id_string[28]; - PBOOT_ENTRY entry_list; -} BOOT_HEADER, *PBOOT_HEADER; - -typedef struct date_and_time -{ - BYTE second; - BYTE minute; - BYTE hour; - BYTE day; - BYTE month; - WORD year; -} DATE_AND_TIME, *PDATE_AND_TIME; - -typedef struct directory_record -{ - struct directory_record *next_in_directory; - struct directory_record *next_in_path_table; /* directory record only */ - struct directory_record *next_in_memory; - struct directory_record *first_record; /* directory record only */ - struct directory_record *parent; - BYTE flags; - char name[MAX_NAME_LENGTH+1]; - char name_on_cd[MAX_CDNAME_LENGTH+1]; - char extension[MAX_EXTENSION_LENGTH+1]; - char extension_on_cd[MAX_CDEXTENSION_LENGTH+1]; - char *joliet_name; - const char *orig_name; - DATE_AND_TIME date_and_time; - DWORD sector; - DWORD size; - DWORD joliet_sector; - DWORD joliet_size; - unsigned level; /* directory record only */ - WORD path_table_index; /* directory record only */ -} DIR_RECORD, *PDIR_RECORD; - -typedef enum directory_record_type -{ - DOT_RECORD, - DOT_DOT_RECORD, - SUBDIRECTORY_RECORD, - FILE_RECORD -} DIR_RECORD_TYPE, *PDIR_RECORD_TYPE; - - -PDIR_RECORD sort_linked_list(PDIR_RECORD, - unsigned, int (*)(PDIR_RECORD, PDIR_RECORD)); - - -static char DIRECTORY_TIMESTAMP[] = "~Y$'KOR$.3K&"; - -static struct cd_image cd; -DIR_RECORD root; - -char volume_label[32]; -char source[512]; -char *end_source; - -enum {QUIET, NORMAL, VERBOSE} verbosity; -BOOL show_progress; - -BOOL scan_files_only = FALSE; -// BOOL compute_crc = FALSE; - -/* - * ISO 9660 information - */ -DWORD size_limit; -BOOL accept_punctuation_marks; - -DWORD total_sectors; -DWORD path_table_size; -DWORD little_endian_path_table_sector; -DWORD big_endian_path_table_sector; - - -/* - * Stats - */ -DWORD number_of_files; -DWORD bytes_in_files; -DWORD unused_bytes_at_ends_of_files; -DWORD number_of_directories; -DWORD bytes_in_directories; - -struct target_dir_hash specified_files; - - -/* - * El-Torito boot information - */ -BOOL eltorito; // TRUE/FALSE: bootable/non-bootable CD-ROM -BOOL multi_boot; // TRUE/FALSE: multi/single-boot CD-ROM -DWORD boot_catalog_sector; -BOOT_VALIDATION_HEADER boot_validation_header; -BOOT_ENTRY default_boot_entry; -PBOOT_HEADER boot_header_list; - -/* - * Joliet information - */ -BOOL joliet; -DWORD joliet_path_table_size; -DWORD joliet_little_endian_path_table_sector; -DWORD joliet_big_endian_path_table_sector; - -/* - * UDF information - */ -BOOL make_bridged_udf = TRUE; // TRUE for "UDF-Bridge" (aka. UDF/ISO); FALSE for pure UDF. - - -/*----------------------------------------------------------------------------- -This function edits a 32-bit unsigned number into a comma-delimited form, such -as 4,294,967,295 for the largest possible number, and returns a pointer to a -static buffer containing the result. It suppresses leading zeros and commas, -but optionally pads the result with blanks at the left so the result is always -exactly 13 characters long (excluding the terminating zero). - -CAUTION: A statement containing more than one call on this function, such as -printf("%s, %s", edit_with_commas(a), edit_with_commas(b)), will produce -incorrect results because all calls use the same static bufffer. ------------------------------------------------------------------------------*/ - -static char *edit_with_commas(DWORD x, BOOL pad) -{ - static char s[14]; - unsigned i = 13; - do - { - if (i % 4 == 2) s[--i] = ','; - s[--i] = (char)(x % 10 + '0'); - } while ((x/=10) != 0); - if (pad) - { - while (i > 0) s[--i] = ' '; - } - return s + i; -} - -/*----------------------------------------------------------------------------- -This function releases all allocated memory blocks. ------------------------------------------------------------------------------*/ - -static void release_memory(void) -{ - while (boot_header_list) - { - PBOOT_HEADER next_header = boot_header_list->next_header; - - while (boot_header_list->entry_list) - { - PBOOT_ENTRY next_entry = boot_header_list->entry_list->next_entry; - free(boot_header_list->entry_list); - boot_header_list->entry_list = next_entry; - } - - free(boot_header_list); - boot_header_list = next_header; - } - - while (root.next_in_memory != NULL) - { - PDIR_RECORD next = root.next_in_memory->next_in_memory; - if (joliet) - free(root.next_in_memory->joliet_name); - free(root.next_in_memory); - root.next_in_memory = next; - } - if (joliet) - free(root.joliet_name); - - if (cd.buffer != NULL) - { - free(cd.buffer); - cd.buffer = NULL; - } -} - -/*----------------------------------------------------------------------------- -This function edits and displays an error message and then jumps back to the -error exit point in main(). ------------------------------------------------------------------------------*/ - -static -DECLSPEC_NORETURN -void error_exit(const char* fmt, ...) -{ - va_list arg; - - va_start(arg, fmt); - vprintf(fmt, arg); - va_end(arg); - printf("\n"); - if (cd.file != NULL) - fclose(cd.file); - release_memory(); - exit(1); -} - -/*----------------------------------------------------------------------------- -This function, which is called only on the second pass, and only when the -buffer is not empty, flushes the buffer to the CD-ROM image. ------------------------------------------------------------------------------*/ - -static void flush_buffer(void) -{ - if (fwrite(cd.buffer, cd.count, 1, cd.file) < 1) - error_exit("File write error"); - cd.count = 0; - if (show_progress) - { - printf("\r%s ", - edit_with_commas((total_sectors - cd.sector) * SECTOR_SIZE, TRUE)); - } -} - -/*----------------------------------------------------------------------------- -This function writes a single byte to the CD-ROM image. On the first pass (in -which cd.handle < 0), it does not actually write anything but merely updates -the file pointer as though the byte had been written. ------------------------------------------------------------------------------*/ - -static void write_byte(BYTE x) -{ - if (cd.file != NULL) - { - cd.buffer[cd.count] = x; - if (++cd.count == BUFFER_SIZE) - flush_buffer(); - } - if (++cd.offset == SECTOR_SIZE) - { - cd.sector++; - cd.offset = 0; - } -} - -/*----------------------------------------------------------------------------- -These functions write a word or double word to the CD-ROM image with the -specified endianity. ------------------------------------------------------------------------------*/ - -static void write_little_endian_word(WORD x) -{ - write_byte((BYTE)x); - write_byte((BYTE)(x >> 8)); -} - -static void write_big_endian_word(WORD x) -{ - write_byte((BYTE)(x >> 8)); - write_byte((BYTE)x); -} - -static void write_both_endian_word(WORD x) -{ - write_little_endian_word(x); - write_big_endian_word(x); -} - -static void write_little_endian_dword(DWORD x) -{ - write_byte((BYTE)x); - write_byte((BYTE)(x >> 8)); - write_byte((BYTE)(x >> 16)); - write_byte((BYTE)(x >> 24)); -} - -static void write_big_endian_dword(DWORD x) -{ - write_byte((BYTE)(x >> 24)); - write_byte((BYTE)(x >> 16)); - write_byte((BYTE)(x >> 8)); - write_byte((BYTE)x); -} - -static void write_both_endian_dword(DWORD x) -{ - write_little_endian_dword(x); - write_big_endian_dword(x); -} - -/*----------------------------------------------------------------------------- -This function writes enough zeros to fill out the end of a sector, and leaves -the file pointer at the beginning of the next sector. If the file pointer is -already at the beginning of a sector, it writes nothing. ------------------------------------------------------------------------------*/ - -static void fill_sector(void) -{ - while (cd.offset != 0) - write_byte(0); -} - -/*----------------------------------------------------------------------------- -This function writes a string to the CD-ROM image. The terminating \0 is not -written. ------------------------------------------------------------------------------*/ - -static void write_string(char *s) -{ - while (*s != 0) - write_byte(*s++); -} - -static void write_bytecounted_string(unsigned bytecount, char *s, char padding) -{ - while (*s != 0 && bytecount != 0) - { - write_byte(*s++); - bytecount--; - } - while (bytecount != 0) - { - write_byte(padding); - bytecount--; - } -} - -/*----------------------------------------------------------------------------- -This function writes a ansi string as a big endian unicode string to the CD-ROM -image. The terminating \0 is not written. ------------------------------------------------------------------------------*/ - -static void write_string_as_big_endian_unicode(char *s) -{ - while (*s != 0) - { - write_big_endian_word(*s++); - } -} - -static void write_bytecounted_string_as_big_endian_unicode(unsigned bytecount, char *s, char padding) -{ - unsigned wordcount = bytecount / 2; - - while (*s != 0 && wordcount != 0) - { - write_big_endian_word(*s++); - wordcount--; - } - while (wordcount != 0) - { - write_big_endian_word(padding); - wordcount--; - } - - if (bytecount % 2 != 0) - write_byte(padding); -} - -/*----------------------------------------------------------------------------- -This function writes a block of identical bytes to the CD-ROM image. ------------------------------------------------------------------------------*/ - -static void write_block(unsigned count, BYTE value) -{ - while (count != 0) - { - write_byte(value); - count--; - } -} - -/*----------------------------------------------------------------------------- -This function writes a block of identical big endian words to the CD-ROM image. ------------------------------------------------------------------------------*/ - -static void write_word_block(unsigned count, WORD value) -{ - while (count != 0) - { - write_big_endian_word(value); - count--; - } -} - -/*----------------------------------------------------------------------------- -This function writes a directory record to the CD_ROM image. ------------------------------------------------------------------------------*/ - -static void -write_directory_record(PDIR_RECORD d, - DIR_RECORD_TYPE DirType, - BOOL joliet) -{ - unsigned identifier_size; - unsigned record_size; - - if (joliet) - { - if (DirType == DOT_RECORD || DirType == DOT_DOT_RECORD) - identifier_size = 1; - else - identifier_size = strlen(d->joliet_name) * 2; - } - else - { - switch (DirType) - { - case DOT_RECORD: - case DOT_DOT_RECORD: - identifier_size = 1; - break; - case SUBDIRECTORY_RECORD: - /*printf("Subdir: %s\n", d->name_on_cd);*/ - identifier_size = strlen(d->name_on_cd); - break; - case FILE_RECORD: - /*printf("File: %s.%s -> %s.%s\n", d->name, d->extension, d->name_on_cd, d->extension_on_cd);*/ - identifier_size = strlen(d->name_on_cd) + 2; - if (d->extension_on_cd[0] != 0) - identifier_size += 1 + strlen(d->extension_on_cd); - break; - default: - identifier_size = 1; - break; - } - } - record_size = 33 + identifier_size; - if ((identifier_size & 1) == 0) - record_size++; - if (cd.offset + record_size > SECTOR_SIZE) - fill_sector(); - write_byte((BYTE)record_size); - write_byte(0); // number of sectors in extended attribute record - if (joliet) - { - write_both_endian_dword(d->joliet_sector); - write_both_endian_dword(d->joliet_size); - } - else - { - write_both_endian_dword(d->sector); - write_both_endian_dword(d->size); - } - write_byte((BYTE)(d->date_and_time.year - 1900)); - write_byte(d->date_and_time.month); - write_byte(d->date_and_time.day); - write_byte(d->date_and_time.hour); - write_byte(d->date_and_time.minute); - write_byte(d->date_and_time.second); - write_byte(0); // GMT offset - write_byte(d->flags); - write_byte(0); // file unit size for an interleaved file - write_byte(0); // interleave gap size for an interleaved file - write_both_endian_word(1); // volume sequence number - write_byte((BYTE)identifier_size); - switch (DirType) - { - case DOT_RECORD: - write_byte(0); - break; - case DOT_DOT_RECORD: - write_byte(1); - break; - case SUBDIRECTORY_RECORD: - if (joliet) - write_string_as_big_endian_unicode(d->joliet_name); - else - write_string(d->name_on_cd); - break; - case FILE_RECORD: - if (joliet) - { - write_string_as_big_endian_unicode(d->joliet_name); - } - else - { - write_string(d->name_on_cd); - if (d->extension_on_cd[0] != 0) - { - write_byte('.'); - write_string(d->extension_on_cd); - } - write_string(";1"); - } - break; - } - if ((identifier_size & 1) == 0) - write_byte(0); -} - -/*----------------------------------------------------------------------------- -This function converts the date and time words from an ffblk structure and -puts them into a date_and_time structure. ------------------------------------------------------------------------------*/ - -static void convert_date_and_time(PDATE_AND_TIME dt, time_t *time) -{ - struct tm *timedef; - timedef = gmtime(time); - - dt->second = timedef->tm_sec; - dt->minute = timedef->tm_min; - dt->hour = timedef->tm_hour; - dt->day = timedef->tm_mday; - dt->month = timedef->tm_mon + 1; - dt->year = timedef->tm_year + 1900; -} - -/*----------------------------------------------------------------------------- -This function checks the specified character, if necessary, and -generates an error if it is a punctuation mark other than an underscore. -It also converts small letters to capital letters and returns the -result. ------------------------------------------------------------------------------*/ - -static int check_for_punctuation(int c, const char *name) -{ - c = toupper(c & 0xFF); - if (!accept_punctuation_marks && !isalnum(c) && c != '_') - error_exit("Punctuation mark in %s", name); - return c; -} - -/*----------------------------------------------------------------------------- -This function checks to see if there's a cdname conflict. ------------------------------------------------------------------------------*/ - -#if defined(_WIN32) && !defined(strcasecmp) -#define strcasecmp stricmp -#endif // _WIN32 - -static BOOL cdname_exists(PDIR_RECORD d) -{ - PDIR_RECORD p = d->parent->first_record; - while (p) - { - if ( p != d - && !strcasecmp(p->name_on_cd, d->name_on_cd) - && !strcasecmp(p->extension_on_cd, d->extension_on_cd) ) - return TRUE; - p = p->next_in_directory; - } - return FALSE; -} - -static void parse_filename_into_dirrecord(const char* filename, PDIR_RECORD d, BOOL dir) -{ - const char *s = filename; - char *t = d->name_on_cd; - char *n = d->name; - int joliet_length; - int filename_counter; - filename_counter = 1; - while (*s != 0) - { - if (*s == '.') - { - s++; - break; - } - - if ((size_t)(t-d->name_on_cd) < sizeof(d->name_on_cd)-1) - *t++ = check_for_punctuation(*s, filename); - else if (!joliet) - error_exit("'%s' is not ISO-9660, aborting...", filename); - - if ((size_t)(n-d->name) < sizeof(d->name)-1) - *n++ = *s; - else if (!joliet) - error_exit("'%s' is not ISO-9660, aborting...", filename); - s++; - } - // Check for extension length - if (!joliet && strlen(s) > MAX_EXTENSION_LENGTH) - { - error_exit("'%s' has too long extension, aborting...", filename); - } - *t = 0; - strcpy(d->extension, s); - t = d->extension_on_cd; - while (*s != 0) - { - if ((size_t)(t-d->extension_on_cd) < sizeof(d->extension_on_cd)-1) - *t++ = check_for_punctuation(*s, filename); - else if (!joliet) - error_exit("'%s' is not ISO-9660, aborting...", filename); - s++; - } - *t = 0; - *n = 0; - - if (dir) - { - if (d->extension[0] != 0) - { - if (!joliet) - error_exit("Directory with extension '%s'", filename); - } - d->flags = DIRECTORY_FLAG; - } else - { - d->flags = 0; - } - - filename_counter = 1; - while (cdname_exists(d)) - { - // the file name must be at least 8 chars long - if (strlen(d->name_on_cd)<8) - error_exit("'%s' is a duplicate file name, aborting...", filename); - - if ((d->name_on_cd[8] == '.') && (strlen(d->name_on_cd) < 13)) - error_exit("'%s' is a duplicate file name, aborting...", filename); - - // max 255 times for equal short filename - if (filename_counter>255) - error_exit("'%s' is a duplicate file name, aborting...", filename); - - d->name_on_cd[8] = '~'; - memset(&d->name_on_cd[9],0,5); - sprintf(&d->name_on_cd[9],"%d",filename_counter); - filename_counter++; - } - - if (joliet) - { - joliet_length = strlen(filename); - if (joliet_length > 64) - error_exit("'%s' is not Joliet, aborting...", filename); - d->joliet_name = malloc(joliet_length + 1); - if (d->joliet_name == NULL) - error_exit("Insufficient memory"); - strcpy(d->joliet_name, filename); - } -} - -/*----------------------------------------------------------------------------- -This function creates a new directory record with the information from the -specified ffblk. It links it into the beginning of the directory list -for the specified parent and returns a pointer to the new record. ------------------------------------------------------------------------------*/ - -#ifdef _WIN32 - -/* Win32 version */ -PDIR_RECORD -new_directory_record(struct _finddata_t *f, - PDIR_RECORD parent) -{ - PDIR_RECORD d; - - d = calloc(1, sizeof(*d)); - if (d == NULL) - error_exit("Insufficient memory"); - d->next_in_memory = root.next_in_memory; - root.next_in_memory = d; - - /* I need the parent set before calling parse_filename_into_dirrecord(), - because that functions checks for duplicate file names*/ - d->parent = parent; - parse_filename_into_dirrecord(f->name, d, f->attrib & _A_SUBDIR); - - convert_date_and_time(&d->date_and_time, &f->time_write); - d->flags |= f->attrib & _A_HIDDEN ? HIDDEN_FLAG : 0; - d->size = d->joliet_size = f->size; - d->next_in_directory = parent->first_record; - parent->first_record = d; - return d; -} - -#else - -/* Linux version */ -PDIR_RECORD -new_directory_record(struct dirent *entry, - struct stat *stbuf, - PDIR_RECORD parent) -{ - PDIR_RECORD d; - - d = calloc(1, sizeof(*d)); - if (d == NULL) - error_exit("Insufficient memory"); - d->next_in_memory = root.next_in_memory; - root.next_in_memory = d; - - /* I need the parent set before calling parse_filename_into_dirrecord(), - because that functions checks for duplicate file names*/ - d->parent = parent; -#ifdef HAVE_D_TYPE - parse_filename_into_dirrecord(entry->d_name, d, entry->d_type == DT_DIR); -#else - parse_filename_into_dirrecord(entry->d_name, d, S_ISDIR(stbuf->st_mode)); -#endif - - convert_date_and_time(&d->date_and_time, &stbuf->st_mtime); - d->flags |= entry->d_name[0] == '.' ? HIDDEN_FLAG : 0; - d->size = d->joliet_size = stbuf->st_size; - d->next_in_directory = parent->first_record; - parent->first_record = d; - return d; -} - -#endif - -/*----------------------------------------------------------------------------- -This function compares two directory records according to the ISO9660 rules -for directory sorting and returns a negative value if p is before q, or a -positive value if p is after q. ------------------------------------------------------------------------------*/ - -static int compare_directory_order(PDIR_RECORD p, PDIR_RECORD q) -{ - int n = strcmp(p->name_on_cd, q->name_on_cd); - if (n == 0) - n = strcmp(p->extension_on_cd, q->extension_on_cd); - return n; -} - -/*----------------------------------------------------------------------------- -This function compares two directory records (which must represent -directories) according to the ISO9660 rules for path table sorting and returns -a negative value if p is before q, or a positive vlaue if p is after q. ------------------------------------------------------------------------------*/ - -static int compare_path_table_order(PDIR_RECORD p, PDIR_RECORD q) -{ - int n = p->level - q->level; - if (p == q) - return 0; - if (n == 0) - { - n = compare_path_table_order(p->parent, q->parent); - if (n == 0) - n = compare_directory_order(p, q); - } - return n; -} - -/*----------------------------------------------------------------------------- -This function appends the specified string to the buffer source[]. ------------------------------------------------------------------------------*/ - -static void append_string_to_source(char *s) -{ - while (*s != 0) - *end_source++ = *s++; -} - -/*----------------------------------------------------------------------------- -This function scans all files from the current source[] (which must end in \, -and represents a directory already in the database as d), -and puts the appropriate directory records into the database in memory, with -the specified root. It calls itself recursively to scan all subdirectories. ------------------------------------------------------------------------------*/ - -#ifdef _WIN32 - -static void -make_directory_records(PDIR_RECORD d) -{ - PDIR_RECORD new_d; - struct _finddata_t f; - char *old_end_source; - int findhandle; - - d->first_record = NULL; - strcpy(end_source, "*.*"); - - findhandle = _findfirst(source, &f); - if (findhandle != 0) - { - do - { - if ((f.attrib & (_A_HIDDEN | _A_SUBDIR)) == 0 && f.name[0] != '.') - { - if (strcmp(f.name, DIRECTORY_TIMESTAMP) == 0) - { - convert_date_and_time(&d->date_and_time, &f.time_write); - } - else - { - if (verbosity == VERBOSE) - { - old_end_source = end_source; - strcpy(end_source, f.name); - printf("%d: file %s\n", d->level, source); - end_source = old_end_source; - } - (void) new_directory_record(&f, d); - } - } - } - while (_findnext(findhandle, &f) == 0); - - _findclose(findhandle); - } - - strcpy(end_source, "*.*"); - findhandle = _findfirst(source, &f); - if (findhandle) - { - do - { - if (f.attrib & _A_SUBDIR && f.name[0] != '.') - { - old_end_source = end_source; - append_string_to_source(f.name); - *end_source++ = DIR_SEPARATOR_CHAR; - if (verbosity == VERBOSE) - { - *end_source = 0; - printf("%d: directory %s\n", d->level + 1, source); - } - if (d->level < MAX_LEVEL) - { - new_d = new_directory_record(&f, d); - new_d->next_in_path_table = root.next_in_path_table; - root.next_in_path_table = new_d; - new_d->level = d->level + 1; - make_directory_records(new_d); - } - else - { - error_exit("Directory is nested too deep"); - } - end_source = old_end_source; - } - } - while (_findnext(findhandle, &f) == 0); - - _findclose(findhandle); - } - - // sort directory - d->first_record = sort_linked_list(d->first_record, 0, compare_directory_order); -} - -#else - -/* Linux version */ -static void -make_directory_records(PDIR_RECORD d) -{ - PDIR_RECORD new_d; - DIR *dirp; - struct dirent *entry; - char *old_end_source; - struct stat stbuf; - char buf[MAX_PATH]; - - d->first_record = NULL; - -#ifdef HAVE_D_TYPE - dirp = opendir(source); - if (dirp != NULL) - { - while ((entry = readdir(dirp)) != NULL) - { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; // skip self and parent - - if (entry->d_type == DT_REG) // normal file - { - // Check for an absolute path - if (source[0] == DIR_SEPARATOR_CHAR) - { - strcpy(buf, source); - strcat(buf, DIR_SEPARATOR_STRING); - strcat(buf, entry->d_name); - } - else - { - if (!getcwd(buf, sizeof(buf))) - error_exit("Cannot get CWD: %s\n", strerror(errno)); - strcat(buf, DIR_SEPARATOR_STRING); - strcat(buf, source); - strcat(buf, entry->d_name); - } - - if (stat(buf, &stbuf) == -1) - { - error_exit("Cannot access '%s' (%s)\n", buf, strerror(errno)); - return; - } - - if (strcmp(entry->d_name, DIRECTORY_TIMESTAMP) == 0) - { - convert_date_and_time(&d->date_and_time, &stbuf.st_ctime); - } - else - { - if (verbosity == VERBOSE) - { - printf("%d: file %s\n", d->level, buf); - } - (void) new_directory_record(entry, &stbuf, d); - } - } - } - closedir(dirp); - } - else - { - error_exit("Cannot open '%s'\n", source); - return; - } - - dirp = opendir(source); - if (dirp != NULL) - { - while ((entry = readdir(dirp)) != NULL) - { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; // skip self and parent - - if (entry->d_type == DT_DIR) // directory - { - old_end_source = end_source; - append_string_to_source(entry->d_name); - *end_source++ = DIR_SEPARATOR_CHAR; - *end_source = 0; - if (verbosity == VERBOSE) - { - printf("%d: directory %s\n", d->level + 1, source); - } - if (d->level < MAX_LEVEL) - { - // Check for an absolute path - if (source[0] == DIR_SEPARATOR_CHAR) - { - strcpy(buf, source); - } - else - { - if (!getcwd(buf, sizeof(buf))) - error_exit("Cannot get CWD: %s\n", strerror(errno)); - strcat(buf, DIR_SEPARATOR_STRING); - strcat(buf, source); - } - - if (stat(buf, &stbuf) == -1) - { - error_exit("Cannot access '%s' (%s)\n", buf, strerror(errno)); - return; - } - new_d = new_directory_record(entry, &stbuf, d); - new_d->next_in_path_table = root.next_in_path_table; - root.next_in_path_table = new_d; - new_d->level = d->level + 1; - make_directory_records(new_d); - } - else - { - error_exit("Directory is nested too deep"); - } - end_source = old_end_source; - *end_source = 0; - } - } - closedir(dirp); - } - else - { - error_exit("Cannot open '%s'\n", source); - return; - } - -#else - - dirp = opendir(source); - if (dirp != NULL) - { - while ((entry = readdir(dirp)) != NULL) - { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; // skip self and parent - - // Check for an absolute path - if (source[0] == DIR_SEPARATOR_CHAR) - { - strcpy(buf, source); - strcat(buf, DIR_SEPARATOR_STRING); - strcat(buf, entry->d_name); - } - else - { - if (!getcwd(buf, sizeof(buf))) - error_exit("Cannot get CWD: %s\n", strerror(errno)); - strcat(buf, DIR_SEPARATOR_STRING); - strcat(buf, source); - strcat(buf, entry->d_name); - } - - if (stat(buf, &stbuf) == -1) - { - error_exit("Cannot access '%s' (%s)\n", buf, strerror(errno)); - return; - } - - if (S_ISDIR(stbuf.st_mode)) - { - old_end_source = end_source; - append_string_to_source(entry->d_name); - *end_source++ = DIR_SEPARATOR_CHAR; - *end_source = 0; - if (verbosity == VERBOSE) - { - printf("%d: directory %s\n", d->level + 1, source); - } - - if (d->level < MAX_LEVEL) - { - new_d = new_directory_record(entry, &stbuf, d); - new_d->next_in_path_table = root.next_in_path_table; - root.next_in_path_table = new_d; - new_d->level = d->level + 1; - make_directory_records(new_d); - } - else - { - error_exit("Directory is nested too deep"); - } - - end_source = old_end_source; - *end_source = 0; - } - else if (S_ISREG(stbuf.st_mode)) - { - if (strcmp(entry->d_name, DIRECTORY_TIMESTAMP) == 0) - { - convert_date_and_time(&d->date_and_time, &stbuf.st_ctime); - } - else - { - if (verbosity == VERBOSE) - { - printf("%d: file %s\n", d->level, buf); - } - (void) new_directory_record(entry, &stbuf, d); - } - } - } - closedir(dirp); - } - else - { - error_exit("Cannot open '%s'\n", source); - return; - } - -#endif - - // sort directory - d->first_record = sort_linked_list(d->first_record, 0, compare_directory_order); -} - -#endif - -static PDIR_RECORD -new_empty_dirrecord(PDIR_RECORD d, BOOL directory) -{ - PDIR_RECORD new_d; - new_d = calloc(1, sizeof(*new_d)); - new_d->parent = d; - new_d->level = d->level + 1; - new_d->next_in_directory = d->first_record; - d->first_record = new_d; - new_d->next_in_memory = root.next_in_memory; - root.next_in_memory = new_d; - new_d->date_and_time = d->date_and_time; - if (directory) - { - new_d->flags |= DIRECTORY_FLAG; - new_d->next_in_path_table = root.next_in_path_table; - root.next_in_path_table = new_d; - } - return new_d; -} - -#ifdef _WIN32 -static BOOL -get_cd_file_time(HANDLE handle, PDATE_AND_TIME cd_time_info) -{ - FILETIME file_time; - SYSTEMTIME sys_time; - - if (!GetFileTime(handle, NULL, NULL, &file_time)) - return FALSE; - - FileTimeToSystemTime(&file_time, &sys_time); - memset(cd_time_info, 0, sizeof(*cd_time_info)); - - cd_time_info->year = sys_time.wYear; - cd_time_info->month = sys_time.wMonth; - cd_time_info->day = sys_time.wDay; - cd_time_info->hour = sys_time.wHour; - cd_time_info->minute = sys_time.wMinute; - cd_time_info->second = sys_time.wSecond; - - return TRUE; -} -#endif - -static void -scan_specified_files(PDIR_RECORD d, struct target_dir_entry *dir) -{ - PDIR_RECORD new_d; -#ifdef _WIN32 - HANDLE open_file; - LARGE_INTEGER file_size; -#else - struct stat stbuf; -#endif - struct target_file *file; - struct target_dir_entry *child; - - d->first_record = NULL; - - for (file = dir->head; file; file = file->next) - { - if (strcmp(file->target_name, DIRECTORY_TIMESTAMP) == 0) - { -#ifdef _WIN32 - if ((open_file = CreateFileA(file->source_name, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL)) == INVALID_HANDLE_VALUE) - { - error_exit("Cannot open timestamp file '%s'\n", file->source_name); - } - - if (!get_cd_file_time(open_file, &d->date_and_time)) - { - error_exit("Cannot stat timestamp file '%s'\n", file->source_name); - } - CloseHandle(open_file); -#else - if (stat(file->target_name, &stbuf) == -1) - { - error_exit("Cannot stat timestamp file '%s'\n", file->source_name); - } - convert_date_and_time(&d->date_and_time, &stbuf.st_ctime); -#endif - } - else - { - if (verbosity == VERBOSE) - { - printf("%d: file %s (from %s)\n", - d->level, - file->target_name, - file->source_name); - } - new_d = new_empty_dirrecord(d, FALSE); - parse_filename_into_dirrecord(file->target_name, new_d, FALSE); -#ifdef _WIN32 - if ((open_file = CreateFileA(file->source_name, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL)) == INVALID_HANDLE_VALUE) - { - error_exit("Cannot open file '%s'\n", file->source_name); - } - if (!get_cd_file_time(open_file, &new_d->date_and_time)) - { - error_exit("Cannot stat file '%s'\n", file->source_name); - } - if (!GetFileSizeEx(open_file, &file_size)) - { - error_exit("Cannot get file size of '%s'\n", file->source_name); - } - new_d->size = new_d->joliet_size = file_size.QuadPart; - new_d->orig_name = file->source_name; - CloseHandle(open_file); -#else - if (stat(file->source_name, &stbuf) == -1) - { - error_exit("Cannot find '%s' (target '%s')\n", - file->source_name, - file->target_name); - } - convert_date_and_time(&new_d->date_and_time, &stbuf.st_mtime); - new_d->size = new_d->joliet_size = stbuf.st_size; - new_d->orig_name = file->source_name; -#endif - } - } - - for (child = dir->child; child; child = child->next) - { - if (verbosity == VERBOSE) - { - printf("%d: directory %s\n", d->level, child->case_name); - } - new_d = new_empty_dirrecord(d, TRUE); - parse_filename_into_dirrecord(child->case_name, new_d, TRUE); - scan_specified_files(new_d, child); - } - - /* sort directory */ - d->first_record = sort_linked_list(d->first_record, - 0, - compare_directory_order); - source[0] = 0; - end_source = source; -} - -/*----------------------------------------------------------------------------- -This function loads the file specifications for the file or directory -corresponding to the specified directory record into the source[] buffer. It -is recursive. ------------------------------------------------------------------------------*/ - -static void get_file_specifications(PDIR_RECORD d) -{ - if (d != &root) - { - get_file_specifications(d->parent); - if (d->joliet_name == NULL) - append_string_to_source(d->name); - else - append_string_to_source(d->joliet_name); - - if (((d->flags & DIRECTORY_FLAG) == 0 || joliet) && d->extension[0] != 0) - { - if (d->joliet_name == NULL) - { - *end_source++ = '.'; - append_string_to_source(d->extension); - } - } - if (d->flags & DIRECTORY_FLAG) - *end_source++ = DIR_SEPARATOR_CHAR; - } -} - -static void get_time_string(char *str) -{ - sprintf(str, "%04d%02d%02d%02d%02d%02d00", - root.date_and_time.year, - root.date_and_time.month, - root.date_and_time.day, - root.date_and_time.hour, - root.date_and_time.minute, - root.date_and_time.second); -} - -static BOOL write_from_file(FILE *file, DWORD size) -{ - if (cd.file != NULL) - { - int n; - - fseek(file, 0, SEEK_SET); - while (size > 0) - { - n = BUFFER_SIZE - cd.count; - if ((DWORD)n > size) - n = size; - - if (fread(cd.buffer + cd.count, n, 1, file) < 1) - return FALSE; - - cd.count += n; - if (cd.count == BUFFER_SIZE) - flush_buffer(); - cd.sector += n / SECTOR_SIZE; - cd.offset += n % SECTOR_SIZE; - size -= n; - } - } - else - { - cd.sector += size / SECTOR_SIZE; - cd.offset += size % SECTOR_SIZE; - } - - return TRUE; -} - -static void pass(void) -{ - PDIR_RECORD d, q; - unsigned int index; - unsigned int name_length; - DWORD size; - DWORD number_of_sectors; - char *old_end_source; - FILE *file; - - PBOOT_HEADER header; - PBOOT_ENTRY entry; - - char timestring[17]; - - get_time_string(timestring); - - // first 16 sectors are zeros - write_block(16 * SECTOR_SIZE, 0); - - - // Primary Volume Descriptor - if (make_bridged_udf) - { - write_string("\1CD001\1"); - write_byte(0); - write_bytecounted_string(32, "", ' '); // system identifier - write_bytecounted_string(32, volume_label, ' '); // volume label - - write_block(8, 0); - write_both_endian_dword(total_sectors); - write_block(32, 0); - write_both_endian_word(1); // volume set size - write_both_endian_word(1); // volume sequence number - write_both_endian_word(2048); // sector size - write_both_endian_dword(path_table_size); - write_little_endian_dword(little_endian_path_table_sector); - write_little_endian_dword(0); // second little endian path table - write_big_endian_dword(big_endian_path_table_sector); - write_big_endian_dword(0); // second big endian path table - write_directory_record(&root, DOT_RECORD, FALSE); - - write_bytecounted_string(128, volume_label, ' '); // volume set identifier - write_bytecounted_string(128, PUBLISHER_ID, ' '); // publisher identifier - write_bytecounted_string(128, DATA_PREP_ID, ' '); // data preparer identifier - write_bytecounted_string(128, APP_ID, ' '); // application identifier - - write_bytecounted_string(37, "", ' '); // copyright file identifier - write_bytecounted_string(37, "", ' '); // abstract file identifier - write_bytecounted_string(37, "", ' '); // bibliographic file identifier - - write_string(timestring); // volume creation - write_byte(0); - write_string(timestring); // most recent modification - write_byte(0); - write_string("0000000000000000"); // volume expires - write_byte(0); - write_string("0000000000000000"); // volume is effective - write_byte(0); - write_byte(1); - write_byte(0); - fill_sector(); - } - - // Boot Volume Descriptor - if (eltorito) - { - write_byte(0); // Boot record ID - write_string("CD001\1"); - write_bytecounted_string(32, "EL TORITO SPECIFICATION", 0); // El-Torito identifier - write_block(32, 0); // unused - write_little_endian_dword(boot_catalog_sector); // pointer to boot catalog - fill_sector(); - } - - // Supplementary Volume Descriptor - if (joliet) - { - write_string("\2CD001\1"); - write_byte(0); - write_bytecounted_string_as_big_endian_unicode(32, "", ' '); // system identifier - write_bytecounted_string_as_big_endian_unicode(32, volume_label, ' '); // volume label - - write_block(8, 0); - write_both_endian_dword(total_sectors); - write_string("%/E"); - write_block(29, 0); - write_both_endian_word(1); // volume set size - write_both_endian_word(1); // volume sequence number - write_both_endian_word(2048); // sector size - write_both_endian_dword(joliet_path_table_size); - write_little_endian_dword(joliet_little_endian_path_table_sector); - write_little_endian_dword(0); // second little endian path table - write_big_endian_dword(joliet_big_endian_path_table_sector); - write_big_endian_dword(0); // second big endian path table - write_directory_record(&root, DOT_RECORD, TRUE); - - write_bytecounted_string_as_big_endian_unicode(128, volume_label, ' '); // volume set identifier - write_bytecounted_string_as_big_endian_unicode(128, PUBLISHER_ID, ' '); // publisher identifier - write_bytecounted_string_as_big_endian_unicode(128, DATA_PREP_ID, ' '); // data preparer identifier - write_bytecounted_string_as_big_endian_unicode(128, APP_ID, ' '); // application identifier - - write_bytecounted_string_as_big_endian_unicode(37, "", ' '); // copyright file identifier - write_bytecounted_string_as_big_endian_unicode(37, "", ' '); // abstract file identifier - write_bytecounted_string_as_big_endian_unicode(37, "", ' '); // bibliographic file identifier - - write_string(timestring); // volume creation - write_byte(0); - write_string(timestring); // most recent modification - write_byte(0); - write_string("0000000000000000"); // volume expires - write_byte(0); - write_string("0000000000000000"); // volume is effective - write_byte(0); - write_byte(1); - write_byte(0); - fill_sector(); - } - - // Volume Descriptor Set Terminator - if (make_bridged_udf) - { - write_string("\377CD001\1"); - fill_sector(); - } - - // TODO: Add UDF support! - - // Boot Catalog - if (eltorito) - { - boot_catalog_sector = cd.sector; - - // Validation entry header - write_byte(boot_validation_header.header_id); - write_byte(boot_validation_header.platform_id); - write_little_endian_word(0); // reserved - write_bytecounted_string(24, MANUFACTURER_ID, 0); // Manufacturer identifier - write_little_endian_word(0x62E); // checksum // FIXME: This is hardcoded!! - write_little_endian_word(0xAA55); // signature - - // Default entry - write_byte(default_boot_entry.boot_id); - write_byte(default_boot_entry.boot_emu_type); - write_little_endian_word(default_boot_entry.load_segment); - write_byte(0); // partition type - write_byte(0); // unused - write_little_endian_word(default_boot_entry.sector_count); - write_little_endian_dword(default_boot_entry.load_rba); - write_block(20, 0); // unused - - // Loop through each boot header - header = boot_header_list; - while (header) - { - write_byte(header->header_id); - write_byte(header->platform_id); - write_little_endian_word(header->num_entries); - write_block(28, 0); // Identifier string (unused) - - // Loop through each boot entry - entry = header->entry_list; - while (entry) - { - write_byte(entry->boot_id); - write_byte(entry->boot_emu_type); - write_little_endian_word(entry->load_segment); - write_byte(0); // partition type - write_byte(0); // unused - write_little_endian_word(entry->sector_count); - write_little_endian_dword(entry->load_rba); - write_block(20, 0); // Selection criteria (unused) - - entry = entry->next_entry; - } - - header = header->next_header; - } - - fill_sector(); - } - - - // Boot Images - if (eltorito) - { - default_boot_entry.load_rba = cd.sector; - - file = fopen(default_boot_entry.bootimage, "rb"); - if (file == NULL) - error_exit("Cannot open '%s'\n", default_boot_entry.bootimage); - fseek(file, 0, SEEK_END); - size = ftell(file); - if (size == 0 || (size % 2048)) - { - fclose(file); - error_exit("Invalid boot image size (%lu bytes)\n", size); - } - // Sector count in 512 byte sectors and rounded up - default_boot_entry.sector_count = (size + 511) / 512; - if (!write_from_file(file, size)) - { - fclose(file); - error_exit("Read error in file '%s'\n", default_boot_entry.bootimage); - } - fclose(file); - - // Loop through each boot header - header = boot_header_list; - while (header) - { - // Loop through each boot entry - entry = header->entry_list; - while (entry) - { - entry->load_rba = cd.sector; - - file = fopen(entry->bootimage, "rb"); - if (file == NULL) - error_exit("Cannot open '%s'\n", entry->bootimage); - fseek(file, 0, SEEK_END); - size = ftell(file); - if (size == 0 || (size % 2048)) - { - fclose(file); - error_exit("Invalid boot image size (%lu bytes)\n", size); - } - // Sector count in 512 byte sectors and rounded up - entry->sector_count = (size + 511) / 512; - if (!write_from_file(file, size)) - { - fclose(file); - error_exit("Read error in file '%s'\n", entry->bootimage); - } - fclose(file); - - entry = entry->next_entry; - } - - header = header->next_header; - } - -// fill_sector(); - } - - - // Little Endian Path Table - - little_endian_path_table_sector = cd.sector; - write_byte(1); - write_byte(0); // number of sectors in extended attribute record - write_little_endian_dword(root.sector); - write_little_endian_word(1); - write_byte(0); - write_byte(0); - - index = 1; - root.path_table_index = 1; - for (d = root.next_in_path_table; d != NULL; d = d->next_in_path_table) - { - name_length = strlen(d->name_on_cd); - write_byte((BYTE)name_length); - write_byte(0); // number of sectors in extended attribute record - write_little_endian_dword(d->sector); - write_little_endian_word(d->parent->path_table_index); - write_string(d->name_on_cd); - if (name_length & 1) - write_byte(0); - d->path_table_index = ++index; - } - - path_table_size = (cd.sector - little_endian_path_table_sector) * - SECTOR_SIZE + cd.offset; - fill_sector(); - - - // Big Endian Path Table - - big_endian_path_table_sector = cd.sector; - write_byte(1); - write_byte(0); // number of sectors in extended attribute record - write_big_endian_dword(root.sector); - write_big_endian_word(1); - write_byte(0); - write_byte(0); - - for (d = root.next_in_path_table; d != NULL; d = d->next_in_path_table) - { - name_length = strlen(d->name_on_cd); - write_byte((BYTE)name_length); - write_byte(0); // number of sectors in extended attribute record - write_big_endian_dword(d->sector); - write_big_endian_word(d->parent->path_table_index); - write_string(d->name_on_cd); - if (name_length & 1) - write_byte(0); - } - fill_sector(); - - if (joliet) - { - // Little Endian Path Table - - joliet_little_endian_path_table_sector = cd.sector; - write_byte(1); - write_byte(0); // number of sectors in extended attribute record - write_little_endian_dword(root.joliet_sector); - write_little_endian_word(1); - write_byte(0); - write_byte(0); - - for (d = root.next_in_path_table; d != NULL; d = d->next_in_path_table) - { - name_length = strlen(d->joliet_name) * 2; - write_byte((BYTE)name_length); - write_byte(0); // number of sectors in extended attribute record - write_little_endian_dword(d->joliet_sector); - write_little_endian_word(d->parent->path_table_index); - write_string_as_big_endian_unicode(d->joliet_name); - } - - joliet_path_table_size = (cd.sector - joliet_little_endian_path_table_sector) * - SECTOR_SIZE + cd.offset; - fill_sector(); - - // Big Endian Path Table - - joliet_big_endian_path_table_sector = cd.sector; - write_byte(1); - write_byte(0); // number of sectors in extended attribute record - write_big_endian_dword(root.joliet_sector); - write_big_endian_word(1); - write_byte(0); - write_byte(0); - - for (d = root.next_in_path_table; d != NULL; d = d->next_in_path_table) - { - name_length = strlen(d->joliet_name) * 2; - write_byte((BYTE)name_length); - write_byte(0); // number of sectors in extended attribute record - write_big_endian_dword(d->joliet_sector); - write_big_endian_word(d->parent->path_table_index); - write_string_as_big_endian_unicode(d->joliet_name); - } - fill_sector(); - } - - // TODO: Add UDF support! - -#if 0 - // Boot Images ?? -#endif - - // TODO: Add CRC block for header! - - // Directories and files - for (d = &root; d != NULL; d = d->next_in_path_table) - { - // write directory - d->sector = cd.sector; - write_directory_record(d, DOT_RECORD, FALSE); - write_directory_record(d == &root ? d : d->parent, DOT_DOT_RECORD, FALSE); - for (q = d->first_record; q != NULL; q = q->next_in_directory) - { - write_directory_record(q, - q->flags & DIRECTORY_FLAG ? SUBDIRECTORY_RECORD : FILE_RECORD, - FALSE); - } - fill_sector(); - d->size = (cd.sector - d->sector) * SECTOR_SIZE; - - // write directory for joliet - if (joliet) - { - d->joliet_sector = cd.sector; - write_directory_record(d, DOT_RECORD, TRUE); - write_directory_record(d == &root ? d : d->parent, DOT_DOT_RECORD, TRUE); - for (q = d->first_record; q != NULL; q = q->next_in_directory) - { - write_directory_record(q, - q->flags & DIRECTORY_FLAG ? SUBDIRECTORY_RECORD : FILE_RECORD, - TRUE); - } - fill_sector(); - d->joliet_size = (cd.sector - d->joliet_sector) * SECTOR_SIZE; - bytes_in_directories += d->joliet_size; - } - - number_of_directories++; - bytes_in_directories += d->size; - - // write file data - for (q = d->first_record; q != NULL; q = q->next_in_directory) - { - if ((q->flags & DIRECTORY_FLAG) == 0) - { - q->sector = q->joliet_sector = cd.sector; - size = q->size; - if (cd.file == NULL) - { - number_of_sectors = (size + SECTOR_SIZE - 1) / SECTOR_SIZE; - cd.sector += number_of_sectors; - number_of_files++; - bytes_in_files += size; - unused_bytes_at_ends_of_files += - number_of_sectors * SECTOR_SIZE - size; - } - else - { - const char *file_source; - old_end_source = end_source; - if (!q->orig_name) - { - get_file_specifications(q); - *end_source = 0; - file_source = source; - } - else - { - file_source = q->orig_name; - } - if (verbosity == VERBOSE) - printf("Writing contents of %s\n", file_source); - file = fopen(file_source, "rb"); - if (file == NULL) - error_exit("Cannot open '%s'\n", file_source); - if (!write_from_file(file, size)) - { - fclose(file); - error_exit("Read error in file '%s'\n", file_source); - } - fclose(file); - end_source = old_end_source; - fill_sector(); - } - } - } - } - - // TODO: Add final CRC block! - - total_sectors = (DWORD)cd.sector; -} - -static char HELP[] = - "\n" - "CDMAKE CD-ROM Premastering Utility\n" - "Copyright (C) 1997 Philip J. Erdelsky\n" - "Copyright (C) 2003-2016 ReactOS Team\n" - "\n\n" - "CDMAKE [-vN] [-p] [-s N] [-m] [-j] [-q] " - // "[-x] " - "[-pN] [-eN] [-b bootimage]\n" - " [-bootdata:N###...#]\n" - " source volume image\n" - "\n" - "Mandatory options:\n" - " source Specifications of base directory containing all files to be\n" - " written to CD-ROM image. Can be a directory, or a path to a\n" - " file list (in which case the path must start with a '@').\n" - " volume Volume label.\n" - " image Image file or device.\n" - "\n" - "General options:\n" - " -vN Verbosity level. Valid values for 'N' are:\n" - " 0: Quiet mode - display nothing but error messages.\n" - " 1: Normal mode (default).\n" - " 2: Verbose mode - display file information as files are\n" - " scanned and written. Overrides the -p option.\n" - " -p Show progress while writing.\n" - " -s N Abort operation before beginning write if image will be larger\n" - " than N megabytes (i.e. 1024*1024*N bytes).\n" - " -q Only scan the source files; do not create an image.\n" - // " -x Compute and encode the AutoCRC value in the image.\n" - "\n" - "ISO 9660 and Joliet options:\n" - " -m Accept punctuation marks other than underscores in names and\n" - " extensions.\n" - " -j Generate Joliet filename records.\n" - "\n" - // "UDF options:\n" - // " Not implemented yet!\n" - // "\n" - "El-Torito boot options:\n" - " -pN Boot platform ID in hex format (default: 00 for a BIOS system).\n" - " -eN Boot media emulation. Valid values for 'N' are:\n" - " 0 (or nothing): No emulation.\n" - " 1: 1.2 MB diskette.\n" - " 2: 1.44MB diskette.\n" - " 3: 2.88MB diskette.\n" - " 4: Hard disk.\n" - " -b bootimage Create a single-boot El-Torito image.\n" - " -bootdata: Create a multi-boot El-Torito image. This option cannot be\n" - " combined with the -b option.\n" - " Syntax:\n" - " -bootdata:N###...#\n" - " 'N': number of boot entries following.\n" - " defaultBootEntry: The default boot entry, needed in all cases.\n" - " Used by BIOSes which do not support additional boot entries.\n" - " bootEntryX: Additional boot entries.\n" - " - Do not use spaces.\n" - " - Each multi-boot entry must be delimited with a hash symbol (#).\n" - " - Each option for a boot entry must be delimited with a comma (,).\n" - " - Each boot entry must specify the platform ID.\n"; - -/*----------------------------------------------------------------------------- -Program execution starts here. ------------------------------------------------------------------------------*/ - -#if (defined(__GNUC__) || (_MSC_VER < 1900)) -char* strtok_s(char *str, const char *delim, char **ctx) -{ - if (delim == NULL || ctx == NULL || (str == NULL && *ctx == NULL)) - { - return NULL; - } - - if (!str) - str = *ctx; - - while (*str && strchr(delim, *str)) - str++; - if (!*str) - { - *ctx = str; - return NULL; - } - - *ctx = str + 1; - while (**ctx && !strchr(delim, **ctx)) - (*ctx)++; - if (**ctx) - *(*ctx)++ = '\0'; - - return str; -} -#endif - -static void -init_boot_entry(PBOOT_ENTRY boot_entry, - BYTE boot_emu_type, WORD load_segment, - char* bootimage) -{ - boot_entry->boot_id = 0x88; // Bootable entry - boot_entry->boot_emu_type = boot_emu_type; // 0: No emulation, etc... - boot_entry->load_segment = load_segment; // If 0 then use default 0x07C0 - - boot_entry->bootimage[0] = '\0'; - strncpy(boot_entry->bootimage, bootimage, sizeof(boot_entry->bootimage)); - boot_entry->bootimage[sizeof(boot_entry->bootimage)-1] = '\0'; -} - -int main(int argc, char **argv) -{ - time_t timestamp = time(NULL); - int i; - char *t; - - if (argc < 2) - { - puts(HELP); - return 1; - } - - // Initialize CD-ROM write buffer - - cd.file = NULL; - cd.filespecs[0] = 0; - - cd.buffer = malloc(BUFFER_SIZE); - if (cd.buffer == NULL) - error_exit("Insufficient memory"); - - // Initialize root directory - - memset(&root, 0, sizeof(root)); - root.level = 1; - root.flags = DIRECTORY_FLAG; - convert_date_and_time(&root.date_and_time, ×tamp); - - // Initialize parameters - - scan_files_only = FALSE; - make_bridged_udf = TRUE; - // compute_crc = FALSE; - - verbosity = NORMAL; - show_progress = FALSE; - size_limit = 0; - accept_punctuation_marks = FALSE; - source[0] = 0; - volume_label[0] = 0; - - // Initialize boot information - eltorito = FALSE; - multi_boot = FALSE; - boot_validation_header.header_id = 1; // Validation header ID - boot_validation_header.platform_id = 0; // x86/64 BIOS system - init_boot_entry(&default_boot_entry, - 0, // No emulation - 0, // Use default 0x07C0 - ""); - default_boot_entry.sector_count = 0; - default_boot_entry.load_rba = 0; - boot_header_list = NULL; - - // Scan command line arguments - - for (i = 1; i < argc; i++) - { - if (strncmp(argv[i], "-v", 2) == 0) - { - t = argv[i] + 2; - if (*t == 0) // Normal verbosity level. - verbosity = NORMAL; - else // Verbosity level in decimal - verbosity = strtoul(t, NULL, 10); - - // Check for validity - if (verbosity > VERBOSE) - verbosity = NORMAL; - - // Disable by default, unless we are in normal verbosity level. - // If progress is still wanted, use '-p'. - if (verbosity == QUIET || verbosity == VERBOSE) - show_progress = FALSE; - } - else if (strcmp(argv[i], "-p") == 0) - show_progress = TRUE; - else if (strncmp(argv[i], "-s", 2) == 0) - { - t = argv[i] + 2; - if (*t == 0) - { - if (++i < argc) - t = argv[i]; - else - error_exit("Missing size limit parameter"); - } - // size_limit = strtoul(t, NULL, 10); - while (isdigit(*t)) - size_limit = size_limit * 10 + *t++ - '0'; - if (size_limit < 1 || size_limit > 800) - error_exit("Invalid size limit"); - size_limit <<= 9; // convert megabyte to sector count - } - else if (strcmp(argv[i], "-m") == 0) - accept_punctuation_marks = TRUE; - else if (strcmp(argv[i], "-j") == 0) - joliet = TRUE; - else if (strncmp(argv[i], "-e", 2) == 0) - { - // Check whether the multi-boot option '-bootdata:' was already set. - // If so, print an error and bail out. - if (eltorito && multi_boot) - error_exit("Single-boot and multi-boot entries cannot be combined"); - - eltorito = TRUE; - multi_boot = FALSE; - - t = argv[i] + 2; - if (*t == 0) // No emulation - default_boot_entry.boot_emu_type = 0; - else // ID in decimal - default_boot_entry.boot_emu_type = (BYTE)strtoul(t, NULL, 10); - } - else if (strncmp(argv[i], "-p", 2) == 0) - { - // Check whether the multi-boot option '-bootdata:' was already set. - // If so, print an error and bail out. - if (eltorito && multi_boot) - error_exit("Single-boot and multi-boot entries cannot be combined"); - - eltorito = TRUE; - multi_boot = FALSE; - - // Platform ID in hexadecimal - boot_validation_header.platform_id = (BYTE)strtoul(argv[i] + 2, NULL, 16); - } - else if (strcmp(argv[i], "-b") == 0) - { - // Check whether the multi-boot option '-bootdata:' was already set. - // If so, print an error and bail out. - if (eltorito && multi_boot) - error_exit("Single-boot and multi-boot entries cannot be combined"); - - eltorito = TRUE; - multi_boot = FALSE; - - strncpy(default_boot_entry.bootimage, argv[++i], sizeof(default_boot_entry.bootimage)); - default_boot_entry.bootimage[sizeof(default_boot_entry.bootimage)-1] = '\0'; - } - else if (strncmp(argv[i], "-bootdata:", sizeof("-bootdata:") - 1) == 0) - { - char *bootdata, *entry_ctx, *option_ctx; - DWORD num_boot_entries = 0; - - BOOL default_entry = TRUE; // Start by setting the default boot entry - PBOOT_HEADER boot_header = NULL; // Current boot header - PBOOT_ENTRY boot_entry = NULL; // The last boot entry in the current boot header - BYTE platform_id, old_platform_id = 0; - BYTE boot_emu_type; - WORD load_segment; - char bootimage[512]; - - // Check whether the single-boot option '-b' was already set. - // If so, print an error and bail out. - if (eltorito && !multi_boot) - error_exit("Single-boot and multi-boot entries cannot be combined"); - - t = argv[i] + (sizeof("-bootdata:") - 1); - bootdata = strdup(t); - if (bootdata == NULL) - error_exit("Insufficient memory"); - - eltorito = TRUE; - multi_boot = TRUE; - - // FIXME: Paths containing '#' or ',' or ' ' are not yet supported!! - - // Start parsing... - t = strtok_s(bootdata, "#", &entry_ctx); - if (t == NULL) - { - free(bootdata); - error_exit("Malformed bootdata command"); - } - - num_boot_entries = strtoul(t, NULL, 10); - - while (num_boot_entries--) - { - // Reset to default values - platform_id = 0; // x86/64 BIOS system - boot_emu_type = 0; // No emulation - load_segment = 0; // Use default 0x07C0 - bootimage[0] = '\0'; - - t = strtok_s(NULL, "#", &entry_ctx); - if (t == NULL) - { - free(bootdata); - error_exit("Malformed bootdata command"); - } - - t = strtok_s(t, ",", &option_ctx); - while (t != NULL) - { - switch (*t++) - { - case 'b': // Boot sector file - { - char *q; - - // Searches for any of the valid separators: - // '#' starts a new boot entry; - // ',' starts a new boot option; - // ' ' finishes the bootdata command. - q = strpbrk(t, "#, "); - if (!q) q = t + strlen(t); - strncpy(bootimage, t, q - t + 1); - break; - } - - case 'p': // Platform ID - { - // Platform ID in hexadecimal - platform_id = (BYTE)strtoul(t, NULL, 16); - break; - } - - case 'e': // No floppy-disk emulation - { - if (*t == 0) // No emulation - boot_emu_type = 0; - else // ID in decimal - boot_emu_type = (BYTE)strtoul(t, NULL, 10); - - break; - } - - case 't': // Loading segment - { - if (*t == 0) // Not specified: use default 0x07C0 - load_segment = 0; - else // Segment in hexadecimal - load_segment = (BYTE)strtoul(t, NULL, 16); - - break; - } - - default: - free(bootdata); - error_exit("Malformed bootdata command"); - } - - t = strtok_s(NULL, ",", &option_ctx); - } - - // Create a new entry and possibly a boot header - if (default_entry) - { - // Initialize the default boot entry and header - - boot_validation_header.header_id = 1; // Validation header ID - boot_validation_header.platform_id = platform_id; - - init_boot_entry(&default_boot_entry, boot_emu_type, load_segment, bootimage); - - // Default entry is now initialized. - default_entry = FALSE; - } - else - { - // Initialize a new boot entry - PBOOT_ENTRY old_boot_entry = boot_entry; - - boot_entry = calloc(1, sizeof(*boot_entry)); - if (boot_entry == NULL) - error_exit("Insufficient memory"); - // boot_entry->next_entry = NULL; - - init_boot_entry(boot_entry, boot_emu_type, load_segment, bootimage); - - // Create a new boot header if we don't have one yet - if (boot_header == NULL) - { - boot_header = calloc(1, sizeof(*boot_header)); - if (boot_header == NULL) - error_exit("Insufficient memory"); - - boot_header->header_id = 0x91; // So far this is the last boot header - boot_header->platform_id = platform_id; - // boot_header->next_header = NULL; - // boot_header->num_entries = 0; - // boot_header->entry_list = NULL; - - old_boot_entry = NULL; - old_platform_id = platform_id; - - boot_header_list = boot_header; - } - else - { - // Create a new boot header if we change the platform ID - if (old_platform_id != platform_id) - { - PBOOT_HEADER prev_boot_header = boot_header; - - boot_header = calloc(1, sizeof(*boot_header)); - if (boot_header == NULL) - error_exit("Insufficient memory"); - - boot_header->header_id = 0x91; // So far this is the last boot header - boot_header->platform_id = platform_id; - // boot_header->next_header = NULL; - // boot_header->num_entries = 0; - // boot_header->entry_list = NULL; - - old_boot_entry = NULL; - old_platform_id = platform_id; - - // Link into the header list - prev_boot_header->header_id = 0x90; // The previous boot header was not the last one - prev_boot_header->next_header = boot_header; - } - } - - // Add the entry into the header - ++boot_header->num_entries; - if (old_boot_entry == NULL) - boot_header->entry_list = boot_entry; - else - old_boot_entry->next_entry = boot_entry; - } - } - - free(bootdata); - } - else if (strcmp(argv[i], "-q") == 0) - scan_files_only = TRUE; - // else if (strcmp(argv[i], "-x") == 0) - // compute_crc = TRUE; - else if (i + 2 < argc) - { - strcpy(source, argv[i++]); - strncpy(volume_label, argv[i++], sizeof(volume_label) - 1); - strcpy(cd.filespecs, argv[i]); - } - else - error_exit("Missing command line argument"); - } - - if (source[0] == 0) - error_exit("Missing source directory"); - if (volume_label[0] == 0) - error_exit("Missing volume label"); - if (cd.filespecs[0] == 0) - error_exit("Missing image file specifications"); - - if (source[0] != '@') - { - /* set source[] and end_source to source directory, - * with a terminating directory separator */ - end_source = source + strlen(source); - if (end_source[-1] == ':') - *end_source++ = '.'; - if (end_source[-1] != DIR_SEPARATOR_CHAR) - *end_source++ = DIR_SEPARATOR_CHAR; - - /* scan all files and create directory structure in memory */ - make_directory_records(&root); - } - else - { - char *trimmedline, *targetname, *normdir, *srcname, *eq; - char lineread[1024]; - - FILE *f = fopen(source+1, "r"); - if (!f) - { - error_exit("Cannot open CD-ROM file description '%s'\n", source+1); - } - while (fgets(lineread, sizeof(lineread), f)) - { - /* We treat these characters as line endings */ - trimmedline = strtok(lineread, "\t\r\n;"); - eq = strchr(trimmedline, '='); - if (!eq) - { - /* Treat this as a directory name */ - targetname = trimmedline; - normdir = strdup(targetname); - normalize_dirname(normdir); - dir_hash_create_dir(&specified_files, targetname, normdir); - free(normdir); - } - else - { - targetname = strtok(lineread, "="); - srcname = strtok(NULL, ""); - -#ifdef _WIN32 - if (_access(srcname, R_OK) == 0) -#else - if (access(srcname, R_OK) == 0) -#endif - { - if (!dir_hash_add_file(&specified_files, srcname, targetname)) - error_exit("Target '%s' (file '%s') is invalid\n", targetname, srcname); - } - else - error_exit("Cannot access file '%s' (target '%s')\n", srcname, targetname); - } - } - fclose(f); - - /* scan all files and create directory structure in memory */ - scan_specified_files(&root, &specified_files.root); - } - - /* sort path table entries */ - root.next_in_path_table = sort_linked_list(root.next_in_path_table, - 1, - compare_path_table_order); - - // initialize CD-ROM write buffer - - cd.file = NULL; - cd.sector = 0; - cd.offset = 0; - cd.count = 0; - - // make non-writing pass over directory structure to obtain the proper - // sector numbers and offsets and to determine the size of the image - - number_of_files = bytes_in_files = number_of_directories = - bytes_in_directories = unused_bytes_at_ends_of_files = 0; - pass(); - - if (verbosity >= NORMAL) - { - printf("%s bytes ", edit_with_commas(bytes_in_files, TRUE)); - printf("in %s files\n", edit_with_commas(number_of_files, FALSE)); - printf("%s unused bytes at ends of files\n", - edit_with_commas(unused_bytes_at_ends_of_files, TRUE)); - printf("%s bytes ", edit_with_commas(bytes_in_directories, TRUE)); - printf("in %s directories\n", - edit_with_commas(number_of_directories, FALSE)); - printf("%s other bytes\n", edit_with_commas(root.sector * SECTOR_SIZE, TRUE)); - puts("-------------"); - printf("%s total bytes\n", - edit_with_commas(total_sectors * SECTOR_SIZE, TRUE)); - puts("============="); - } - - if (size_limit != 0 && total_sectors > size_limit) - error_exit("Size limit exceeded"); - - if (!scan_files_only) - { - // re-initialize CD-ROM write buffer - - cd.file = fopen(cd.filespecs, "w+b"); - if (cd.file == NULL) - error_exit("Cannot open image file '%s'", cd.filespecs); - cd.sector = 0; - cd.offset = 0; - cd.count = 0; - - - // make writing pass over directory structure - - pass(); - - if (cd.count > 0) - flush_buffer(); - if (show_progress) - printf("\r \n"); - if (fclose(cd.file) != 0) - { - cd.file = NULL; - error_exit("File write error in image file '%s'", cd.filespecs); - } - - if (verbosity >= NORMAL) - puts("CD-ROM image made successfully"); - } - - dir_hash_destroy(&specified_files); - release_memory(); - return 0; -} - -/* EOF */ diff --git a/modules/rosapps/applications/devutils/cdmake/config.h b/modules/rosapps/applications/devutils/cdmake/config.h deleted file mode 100644 index ffb5dabb1f6..00000000000 --- a/modules/rosapps/applications/devutils/cdmake/config.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _WIN32 -#ifndef MAX_PATH -#define MAX_PATH 260 -#endif -#define DIR_SEPARATOR_CHAR '/' -#define DIR_SEPARATOR_STRING "/" -#else -#define DIR_SEPARATOR_CHAR '\\' -#define DIR_SEPARATOR_STRING "\\" -#endif - -#define MANUFACTURER_ID "ReactOS Foundation" -#define PUBLISHER_ID "ReactOS Foundation" -#define DATA_PREP_ID "ReactOS Foundation" -#define APP_ID "CDMAKE CD-ROM Premastering Utility" diff --git a/modules/rosapps/applications/devutils/cdmake/dirhash.c b/modules/rosapps/applications/devutils/cdmake/dirhash.c deleted file mode 100644 index a44bad57e01..00000000000 --- a/modules/rosapps/applications/devutils/cdmake/dirhash.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS CD-ROM Maker - * FILE: tools/cdmake/dirhash.c - * PURPOSE: CD-ROM Premastering Utility - Directory names hashing - * PROGRAMMERS: Art Yerkes - */ - -#include -#include -#include -#include "config.h" -#include "dirhash.h" - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -/* This is the famous DJB hash */ -static unsigned int -djb_hash(const char *name) -{ - unsigned int val = 5381; - int i = 0; - - for (i = 0; name[i]; i++) - { - val = (33 * val) + name[i]; - } - - return val; -} - -static void -split_path(const char *path, char **dirname, char **filename /* OPTIONAL */) -{ - const char *result; - - /* Retrieve the file name */ - char *last_slash_1 = strrchr(path, '/'); - char *last_slash_2 = strrchr(path, '\\'); - - if (last_slash_1 || last_slash_2) - result = max(last_slash_1, last_slash_2) + 1; - else - result = path; - - /* Duplicate the file name for the user if needed */ - if (filename) - *filename = strdup(result); - - /* Remove any trailing directory separators */ - while (result > path && (*(result-1) == '/' || *(result-1) == '\\')) - result--; - - /* Retrieve and duplicate the directory */ - *dirname = malloc(result - path + 1); - if (result > path) - memcpy(*dirname, path, result - path); - (*dirname)[result - path] = '\0'; // NULL-terminate -} - -void normalize_dirname(char *filename) -{ - int i, tgt; - int slash = 1; - - for (i = 0, tgt = 0; filename[i]; i++) - { - if (slash) - { - if (filename[i] != '/' && filename[i] != '\\') - { - filename[tgt++] = toupper(filename[i]); - slash = 0; - } - } - else - { - if (filename[i] == '/' || filename[i] == '\\') - { - slash = 1; - filename[tgt++] = DIR_SEPARATOR_CHAR; - } - else - { - filename[tgt++] = toupper(filename[i]); - } - } - } - filename[tgt] = '\0'; // NULL-terminate -} - -static struct target_dir_entry * -get_entry_by_normname(struct target_dir_hash *dh, const char *norm) -{ - unsigned int hashcode; - struct target_dir_entry *de; - hashcode = djb_hash(norm); - de = dh->buckets[hashcode % NUM_DIR_HASH_BUCKETS]; - while (de && strcmp(de->normalized_name, norm)) - de = de->next_dir_hash_entry; - return de; -} - -static void -delete_entry(struct target_dir_hash *dh, struct target_dir_entry *de) -{ - struct target_dir_entry **ent; - ent = &dh->buckets[de->hashcode % NUM_DIR_HASH_BUCKETS]; - while (*ent && ((*ent) != de)) - ent = &(*ent)->next_dir_hash_entry; - if (*ent) - *ent = (*ent)->next_dir_hash_entry; -} - -struct target_dir_entry * -dir_hash_create_dir(struct target_dir_hash *dh, const char *casename, const char *targetnorm) -{ - struct target_dir_entry *de, *parent_de; - char *parentcase = NULL; - char *case_name = NULL; - char *parentname = NULL; - struct target_dir_entry **ent; - - if (!dh->root.normalized_name) - { - dh->root.normalized_name = strdup(""); - dh->root.case_name = strdup(""); - dh->root.hashcode = djb_hash(""); - dh->buckets[dh->root.hashcode % NUM_DIR_HASH_BUCKETS] = &dh->root; - } - - /* Check whether the directory was already created and just return it if so */ - de = get_entry_by_normname(dh, targetnorm); - if (de) - return de; - - /* - * If *case_name == '\0' after the following call to split_path(...), - * for example in the case where casename == "subdir/dir/", then just - * create the directories "subdir" and "dir" by a recursive call to - * dir_hash_create_dir(...) and return 'parent_de' instead (see after). - * We do not (and we never) create a no-name directory inside it. - */ - split_path(casename, &parentcase, &case_name); - split_path(targetnorm, &parentname, NULL); - parent_de = dir_hash_create_dir(dh, parentcase, parentname); - free(parentname); - free(parentcase); - - /* See the remark above */ - if (!*case_name) - { - free(case_name); - return parent_de; - } - - /* Now create the directory */ - de = calloc(1, sizeof(*de)); - de->parent = parent_de; - de->normalized_name = strdup(targetnorm); - de->case_name = case_name; - de->hashcode = djb_hash(targetnorm); - - de->next = parent_de->child; - parent_de->child = de; - - ent = &dh->buckets[de->hashcode % NUM_DIR_HASH_BUCKETS]; - while (*ent) - ent = &(*ent)->next_dir_hash_entry; - *ent = de; - - return de; -} - -struct target_file * -dir_hash_add_file(struct target_dir_hash *dh, const char *source, const char *target) -{ - struct target_file *tf; - struct target_dir_entry *de; - char *targetdir = NULL; - char *targetfile = NULL; - char *targetnorm; - - /* First create the directory; check whether the file name is valid and bail out if not */ - split_path(target, &targetdir, &targetfile); - if (!*targetfile) - { - free(targetdir); - free(targetfile); - return NULL; - } - targetnorm = strdup(targetdir); - normalize_dirname(targetnorm); - de = dir_hash_create_dir(dh, targetdir, targetnorm); - free(targetnorm); - free(targetdir); - - /* Now add the file */ - tf = calloc(1, sizeof(*tf)); - tf->next = de->head; - de->head = tf; - tf->source_name = strdup(source); - tf->target_name = targetfile; - - return tf; -} - -static void -dir_hash_destroy_dir(struct target_dir_hash *dh, struct target_dir_entry *de) -{ - struct target_file *tf; - struct target_dir_entry *te; - - while ((te = de->child)) - { - de->child = te->next; - dir_hash_destroy_dir(dh, te); - free(te); - } - while ((tf = de->head)) - { - de->head = tf->next; - free(tf->source_name); - free(tf->target_name); - free(tf); - } - - delete_entry(dh, de); - free(de->normalized_name); - free(de->case_name); -} - -void dir_hash_destroy(struct target_dir_hash *dh) -{ - dir_hash_destroy_dir(dh, &dh->root); -} diff --git a/modules/rosapps/applications/devutils/cdmake/dirhash.h b/modules/rosapps/applications/devutils/cdmake/dirhash.h deleted file mode 100644 index d06427f0401..00000000000 --- a/modules/rosapps/applications/devutils/cdmake/dirhash.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS CD-ROM Maker - * FILE: tools/cdmake/dirhash.h - * PURPOSE: CD-ROM Premastering Utility - Directory names hashing - * PROGRAMMERS: Art Yerkes - */ - -#ifndef _DIRHASH_H_ -#define _DIRHASH_H_ - -#define NUM_DIR_HASH_BUCKETS 1024 - -struct target_file -{ - struct target_file *next; - char *source_name; - char *target_name; -}; - -struct target_dir_entry -{ - unsigned int hashcode; - struct target_dir_entry *next_dir_hash_entry; - - struct target_dir_entry *next; - struct target_dir_entry *parent; - struct target_dir_entry *child; - struct target_file *head; - char *normalized_name; - char *case_name; -}; - -struct target_dir_hash -{ - struct target_dir_entry *buckets[NUM_DIR_HASH_BUCKETS]; - struct target_dir_entry root; -}; - -void normalize_dirname(char *filename); - -struct target_dir_entry * -dir_hash_create_dir(struct target_dir_hash *dh, const char *casename, const char *targetnorm); - -struct target_file * -dir_hash_add_file(struct target_dir_hash *dh, const char *source, const char *target); - -void dir_hash_destroy(struct target_dir_hash *dh); - -#endif // _DIRHASH_H_ diff --git a/modules/rosapps/applications/devutils/cdmake/llmsort.c b/modules/rosapps/applications/devutils/cdmake/llmsort.c deleted file mode 100644 index 004b9caaa9f..00000000000 --- a/modules/rosapps/applications/devutils/cdmake/llmsort.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * A Linked-List Memory Sort - * by Philip J. Erdelsky - * pje@acm.org - * pje@efgh.com - * http://alumnus.caltech.edu/~pje/ - * - * Version taken from: - * http://alumnus.caltech.edu/~pje/cdmake.txt - * - * An extended version can be found at: - * http://alumnus.caltech.edu/~pje/llmsort.html - * http://www.efgh.com/software/llmsort.htm - * - * Public domain; no restrictions on use. - */ - -#include - -void *sort_linked_list(void *p, unsigned index, int (*compare)(void *, void *)) -{ - unsigned base; - unsigned long block_size; - - struct record - { - struct record *next[1]; - /* other members not directly accessed by this function */ - }; - - struct tape - { - struct record *first, *last; - unsigned long count; - } tape[4]; - - /* Distribute the records alternately to tape[0] and tape[1]. */ - - tape[0].count = tape[1].count = 0L; - tape[0].first = NULL; - base = 0; - while (p != NULL) - { - struct record *next = ((struct record *)p)->next[index]; - ((struct record *)p)->next[index] = tape[base].first; - tape[base].first = ((struct record *)p); - tape[base].count++; - p = next; - base ^= 1; - } - - /* If the list is empty or contains only a single record, then */ - /* tape[1].count == 0L and this part is vacuous. */ - - for (base = 0, block_size = 1L; tape[base+1].count != 0L; - base ^= 2, block_size <<= 1) - { - int dest; - struct tape *tape0, *tape1; - tape0 = tape + base; - tape1 = tape + base + 1; - dest = base ^ 2; - tape[dest].count = tape[dest+1].count = 0; - for (; tape0->count != 0; dest ^= 1) - { - unsigned long n0, n1; - struct tape *output_tape = tape + dest; - n0 = n1 = block_size; - while (1) - { - struct record *chosen_record; - struct tape *chosen_tape; - if (n0 == 0 || tape0->count == 0) - { - if (n1 == 0 || tape1->count == 0) - break; - chosen_tape = tape1; - n1--; - } - else if (n1 == 0 || tape1->count == 0) - { - chosen_tape = tape0; - n0--; - } - else if ((*compare)(tape0->first, tape1->first) > 0) - { - chosen_tape = tape1; - n1--; - } - else - { - chosen_tape = tape0; - n0--; - } - chosen_tape->count--; - chosen_record = chosen_tape->first; - chosen_tape->first = chosen_record->next[index]; - if (output_tape->count == 0) - output_tape->first = chosen_record; - else - output_tape->last->next[index] = chosen_record; - output_tape->last = chosen_record; - output_tape->count++; - } - } - } - - if (tape[base].count > 1L) - tape[base].last->next[index] = NULL; - return tape[base].first; -} - -/* EOF */ diff --git a/modules/rosapps/applications/devutils/cdmake/readme.txt b/modules/rosapps/applications/devutils/cdmake/readme.txt deleted file mode 100644 index 4ddb07389eb..00000000000 --- a/modules/rosapps/applications/devutils/cdmake/readme.txt +++ /dev/null @@ -1,96 +0,0 @@ - CD-ROM Maker - Philip J. Erdelsky - -The CDMAKE utility converts files from DOS/Windows format to ISO9660 -(CD-ROM) format. - -First, gather all the files to be converted and put them into a single -base directory and its subdirectories, arranged just the way you want -them on the CD-ROM. Remember that ISO9660 allows subdirectories to be -nested only eight levels deep. Therefore, if the base directory is -C:\CDROM, - - C:\CDROM\D2\D3\D4\D5\D6\D7\D8\FOO.TXT is permitted, but - - C:\CDROM\D2\D3\D4\D5\D6\D7\D8\D9\FOO.TXT is forbidden. - -Also, ISO9660 does not allow directories to have extensions, although -DOS does. - -Finally, the characters in file and directory names and file extensions -must be letters, digits or underscores. Other punctuation marks -permitted by DOS/Windows are forbidden by ISO9660. You can use the -c -option to override this restriction, but the resulting CD-ROM may not be -readable on systems other than DOS/Windows. - -Files in the base directory will be written to the root directory of the -CD-ROM image. All subdirectories of the base directory will appear as -subdirectories of the root directory of the CD-ROM image. Their -contents, and the contents of their subdirectories, down to the eighth -level, will be faithfully copied to the CD-ROM image. - -System files will not be written to the CD-ROM image. Hidden files will -be written to the CD-ROM image, and will retain their hidden attributes. -Read-only files will be written, and will remain read-only on the -CD-ROM, but this does not distinguish them in any way, because on a -CD-ROM all files are read-only. The archive attribute will be lost. - -File and directory date and time stamps will be preserved in the CD-ROM -image. - -The utility is called up by a command line of the following form: - - CDMAKE [-q] [-v] [-p] [-s N] [-m] [-j] [-b bootimage] source volume image - - source specifications of base directory containing all files to - be written to CD-ROM image - - volume volume label - - image image file or device - - -q quiet mode - display nothing but error messages - - -v verbose mode - display file information as files are - scanned and written - overrides -p option - - -p show progress while writing - - -s N abort operation before beginning write if image will be - larger than N megabytes (i.e. 1024*1024*N bytes) - - -m accept punctuation marks other than underscores in - names and extensions - - -j generates Joliet filename records - - -b bootimage create bootable ElTorito CD-ROM using 'no emulation' mode - - -The utility makes three passes over the source files: - - (1) The scanning pass, in which the names and extensions are - checked for validity, and the names, extensions, sizes, dates, - times and attributes are recorded internally. The files are not - actually read during this pass. - - (2) The layout pass, in which the sizes and positions of - directories, files and other items in the CD-ROM image are - determined. - - (3) The writing pass, in which the files are actually read and the - CD-ROM image is actually written to the specified file or - device. The image is always written sequentially. - -If neither the -q nor the -v option is used, CDMAKE will display the -volume label, size, number of files and directories and the total bytes -in each at the end of the layout pass. - -If the -p option is used, and is not overridden by the -v option, then -during the writing pass, CDMAKE will display the number of bytes still -to be written to the CD-ROM image, updating it frequently. The number -will decrease as the operation progresses, and will reach zero when the -operation is complete. - -The operation of CDMAKE can be aborted by typing Ctrl-C when the utility -is displaying text of any kind.