Bootcd target Modified: trunk/reactos/ReactOS.xml Added: trunk/reactos/bootdata/ Added: trunk/reactos/bootdata/bootcd/ Added: trunk/reactos/bootdata/bootcd/bootcd.xml Added: trunk/reactos/bootdata/bootdata.xml Added: trunk/reactos/tools/cdmake/ Added: trunk/reactos/tools/cdmake/cdmake.c Added: trunk/reactos/tools/cdmake/cdmake.mak Added: trunk/reactos/tools/cdmake/llmosrt.c Added: trunk/reactos/tools/cdmake/readme.txt Modified: trunk/reactos/tools/rbuild/backend/mingw/modulehandler.cpp Modified: trunk/reactos/tools/tools.mak Property changes on: trunk/reactos ___________________________________________________________________ Name: svn:ignore + reactos obj-i386 output-i386 makefile.auto ReactOS.iso _____
Modified: trunk/reactos/ReactOS.xml --- trunk/reactos/ReactOS.xml 2006-01-27 22:10:19 UTC (rev 4) +++ trunk/reactos/ReactOS.xml 2006-01-27 22:21:26 UTC (rev 5) @@ -43,9 +43,11 @@
<directory name="boot"> <xi:include href="boot/boot.xml" /> </directory> +--> <directory name="bootdata"> <xi:include href="bootdata/bootdata.xml" /> </directory> +<!-- <directory name="drivers"> <xi:include href="drivers/directory.xml" /> </directory> _____
Added: trunk/reactos/bootdata/bootcd/bootcd.xml --- trunk/reactos/bootdata/bootcd/bootcd.xml 2006-01-27 22:10:19 UTC (rev 4) +++ trunk/reactos/bootdata/bootcd/bootcd.xml 2006-01-27 22:21:26 UTC (rev 5) @@ -0,0 +1,2 @@
+<module name="bootcd" type="iso"> +</module> _____
Added: trunk/reactos/bootdata/bootdata.xml --- trunk/reactos/bootdata/bootdata.xml 2006-01-27 22:10:19 UTC (rev 4) +++ trunk/reactos/bootdata/bootdata.xml 2006-01-27 22:21:26 UTC (rev 5) @@ -0,0 +1,5 @@
+<group> +<directory name="bootcd"> + <xi:include href="bootcd/bootcd.xml" /> +</directory> +</group> _____
Added: trunk/reactos/tools/cdmake/cdmake.c --- trunk/reactos/tools/cdmake/cdmake.c 2006-01-27 22:10:19 UTC (rev 4) +++ trunk/reactos/tools/cdmake/cdmake.c 2006-01-27 22:21:26 UTC (rev 5) @@ -0,0 +1,1675 @@
+/* + * CD-ROM Maker + * by Philip J. Erdelsky + * pje@acm.org + * http://www.alumni.caltech.edu/~pje/ + * + * ElTorito-Support + * by Eric Kohl + * ekohl@rz-online.de + * + * 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 + * + * $Id: cdmake.c 18952 2005-11-02 16:13:00Z gvg $ + */ + +/* According to his website, this file was released into the public domain by Phillip J. Erdelsky */ + +#include <stdio.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#ifdef WIN32 +# include <io.h> +# include <dos.h> +#else +# ifdef __FreeBSD__ +# include <sys/uio.h> +# else +# include <sys/io.h> +# endif // __FreeBSD__ +# include <errno.h> +# include <sys/types.h> +# include <dirent.h> +# include <unistd.h> +#endif // WIN32 +#include <ctype.h> +#include <setjmp.h> +#include <time.h> +#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 + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; + +const BOOL TRUE = 1; +const BOOL FALSE = 0; + +// 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) + +const BYTE HIDDEN_FLAG = 1; +const BYTE 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 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; + 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 jmp_buf error; +static struct cd_image cd; + +char volume_label[32]; +DIR_RECORD root; +char source[512]; +char *end_source; +enum {QUIET, NORMAL, VERBOSE} verbosity; +BOOL show_progress; +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; +DWORD number_of_files; +DWORD bytes_in_files; +DWORD unused_bytes_at_ends_of_files; +DWORD number_of_directories; +DWORD bytes_in_directories; + +char bootimage[512]; +BOOL eltorito; +DWORD boot_catalog_sector; +DWORD boot_image_sector; +WORD boot_image_size; // counted in 512 byte sectors + +BOOL joliet; +DWORD joliet_path_table_size; +DWORD joliet_little_endian_path_table_sector; +DWORD joliet_big_endian_path_table_sector; + +/*--------------------------------------------------------------------- -------- +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 (root.next_in_memory != NULL) + { + struct directory_record *next = + root.next_in_memory->next_in_memory; + if (joliet) + free (root.joliet_name); + free (root.next_in_memory); + root.next_in_memory = next; + } + 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(). +----------------------------------------------------------------------- ------*/ + +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++); +} + +/*--------------------------------------------------------------------- -------- +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_byte(0); + write_byte(*s++); + } +} + +/*--------------------------------------------------------------------- -------- +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 bige 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((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 = localtime(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; +} + +#if WIN32 +#define strcasecmp stricmp +#endif//WIN32 + +/*--------------------------------------------------------------------- -------- +This function checks to see if there's a cdname conflict. +----------------------------------------------------------------------- ------*/ + +int 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 1; + p = p->next_in_directory; + } + return 0; +} + +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 ( (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 ( (n-d->name) < sizeof(d->name)-1 ) + *n++ = *s; + else if (!joliet) + error_exit ( "'%s' is not ISO-9660, aborting...", filename ); + s++; + } + if (strlen(s) > MAX_EXTENSION_LENGTH) + { + error_exit ( "'%s' has too long extension for cdmake, aborting...", filename ); + } + *t = 0; + strcpy(d->extension, s); + t = d->extension_on_cd; + while ( *s != 0 ) + { + if ( (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) + d->extension_on_cd[0] = 0; + else + 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 least 8 char 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); + 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. +----------------------------------------------------------------------- ------*/ + +#if WIN32 + +/* Win32 version */ +PDIR_RECORD +new_directory_record (struct _finddata_t *f, + PDIR_RECORD parent) +{ + PDIR_RECORD d; + + d = malloc(sizeof(DIR_RECORD)); + if (d == NULL) + error_exit("Insufficient memory"); + memset ( d, 0, sizeof(DIR_RECORD) ); + 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; + /* + char *s; + char *t; + char *n; + */ + + d = malloc(sizeof(DIR_RECORD)); + if (d == NULL) + error_exit("Insufficient memory"); + memset ( d, 0, sizeof(DIR_RECORD) ); + 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 + { + getcwd(buf, sizeof(buf)); + strcat(buf, DIR_SEPARATOR_STRING); + strcat(buf, source); + strcat(buf, entry->d_name); + } + + if (stat(buf, &stbuf) == -1) + { + error_exit("Can't 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("Can't 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 + { + getcwd(buf, sizeof(buf)); + strcat(buf, DIR_SEPARATOR_STRING); + strcat(buf, source); + } + + if (stat(buf, &stbuf) == -1) + { [truncated at 1000 lines; 1037 more skipped]