Author: akhaldi
Date: Sun Jul 21 13:33:03 2013
New Revision: 59547
URL:
http://svn.reactos.org/svn/reactos?rev=59547&view=rev
Log:
* Improve the way we create bootcd, livecd and bootcdregtest. The effort results in ~28%
*smaller* build folder, and *much* faster generation of the ISOs.
[CDMAKE]
* Introduce a way to create an iso using a file map instead of the current on-disk layout.
This allows us to massively reduce the IO and the disk space needed to perform the
creation of the 3 ISOs, and at the same time speed up the process. Brought to you by Art
Yerkes (arty) with review/bug fix by Thomas Faber.
[CMAKE]
* Leverage the newly introduced cdmake feature.
* Silence cdmake verbosity.
* Write the contents of the file lists at once, instead of appending to it one item by
one.
[VGAFONTS]
* Don't include the cab file twice.
Added:
trunk/reactos/tools/cdmake/dirhash.c (with props)
trunk/reactos/tools/cdmake/dirhash.h (with props)
trunk/reactos/tools/cdmake/dirsep.h (with props)
Modified:
trunk/reactos/CMakeLists.txt
trunk/reactos/boot/CMakeLists.txt
trunk/reactos/cmake/CMakeMacros.cmake
trunk/reactos/media/vgafonts/CMakeLists.txt
trunk/reactos/tools/cdmake/CMakeLists.txt
trunk/reactos/tools/cdmake/cdmake.c
Modified: trunk/reactos/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/CMakeLists.txt?rev=59547&a…
==============================================================================
--- trunk/reactos/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/CMakeLists.txt [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -235,6 +235,9 @@
add_subdirectory(subsystems)
add_subdirectory(win32ss)
+ # Create {bootcd, livecd, bootcdregtest}.lst
+ create_iso_lists()
+
file(MAKE_DIRECTORY ${REACTOS_BINARY_DIR}/include/reactos)
add_dependency_footer()
Modified: trunk/reactos/boot/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/CMakeLists.txt?rev=59…
==============================================================================
--- trunk/reactos/boot/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/boot/CMakeLists.txt [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -1,50 +1,27 @@
##bootcd
#clear it out
-file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bootcd.cmake
- "file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bootcd)\n")
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bootcd.lst "")
add_custom_target(bootcd
- ${CMAKE_COMMAND} -D CD_DIR=${CMAKE_CURRENT_BINARY_DIR}/bootcd
- -P ${CMAKE_CURRENT_BINARY_DIR}/bootcd.cmake
- COMMAND native-cdmake -v -j -m -b
${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin
${CMAKE_CURRENT_BINARY_DIR}/bootcd REACTOS ${REACTOS_BINARY_DIR}/bootcd.iso
+ COMMAND native-cdmake -j -m -b
${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin
@${CMAKE_CURRENT_BINARY_DIR}/bootcd.lst REACTOS ${REACTOS_BINARY_DIR}/bootcd.iso
DEPENDS native-cdmake
VERBATIM)
-
+
##bootcdregtest
#clear it out
-file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest.cmake
- "file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest)\n")
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest.lst "")
add_custom_target(bootcdregtest
- ${CMAKE_COMMAND} -D CD_DIR=${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest
- -P ${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest.cmake
- COMMAND native-cdmake -v -j -m -b
${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isobtrt.bin
${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest REACTOS ${REACTOS_BINARY_DIR}/bootcdregtest.iso
+ COMMAND native-cdmake -j -m -b
${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isobtrt.bin
@${CMAKE_CURRENT_BINARY_DIR}/bootcdregtest.lst REACTOS
${REACTOS_BINARY_DIR}/bootcdregtest.iso
DEPENDS native-cdmake
VERBATIM)
-
##livecd
-#clear it out
-file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- "file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/livecd)\n")
-#create profiles directories too
-file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- "file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/livecd/Profiles)\n")
-file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- "file(MAKE_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/livecd/Profiles/All
Users\")\n")
-file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- "file(MAKE_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/livecd/Profiles/All
Users/Desktop\")\n")
-file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- "file(MAKE_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/livecd/Profiles/Default
User\")\n")
-file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- "file(MAKE_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/livecd/Profiles/Default
User/Desktop\")\n")
-file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- "file(MAKE_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/livecd/Profiles/Default
User/My Documents\")\n")
+#clear it out and create the empty Desktop folder
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/livecd.lst "Profiles/Default
User/Desktop\n")
add_custom_target(livecd
- ${CMAKE_COMMAND} -D CD_DIR=${CMAKE_CURRENT_BINARY_DIR}/livecd
- -P ${CMAKE_CURRENT_BINARY_DIR}/livecd.cmake
- COMMAND native-cdmake -v -j -m -b
${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin
${CMAKE_CURRENT_BINARY_DIR}/livecd REACTOS ${REACTOS_BINARY_DIR}/livecd.iso
+ COMMAND native-cdmake -j -m -b
${CMAKE_CURRENT_BINARY_DIR}/freeldr/bootsect/isoboot.bin
@${CMAKE_CURRENT_BINARY_DIR}/livecd.lst REACTOS ${REACTOS_BINARY_DIR}/livecd.iso
DEPENDS native-cdmake
VERBATIM)
Modified: trunk/reactos/cmake/CMakeMacros.cmake
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/cmake/CMakeMacros.cmake?re…
==============================================================================
--- trunk/reactos/cmake/CMakeMacros.cmake [iso-8859-1] (original)
+++ trunk/reactos/cmake/CMakeMacros.cmake [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -227,13 +227,14 @@
if(_CD_NO_CAB)
#directly on cd
foreach(item ${_CD_FILE})
- file(APPEND ${REACTOS_BINARY_DIR}/boot/bootcd.cmake "file(COPY
\"${item}\" DESTINATION \"\${CD_DIR}/${_CD_DESTINATION}\")\n")
+ if(_CD_NAME_ON_CD)
+ #rename it in the cd tree
+ set(__file ${_CD_NAME_ON_CD})
+ else()
+ get_filename_component(__file ${item} NAME)
+ endif()
+ set_property(GLOBAL APPEND PROPERTY BOOTCD_FILE_LIST
"${_CD_DESTINATION}/${__file}=${item}")
endforeach()
- if(_CD_NAME_ON_CD)
- get_filename_component(__file ${_CD_FILE} NAME)
- #rename it in the cd tree
- file(APPEND ${REACTOS_BINARY_DIR}/boot/bootcd.cmake "file(RENAME
\${CD_DIR}/${_CD_DESTINATION}/${__file}
\${CD_DIR}/${_CD_DESTINATION}/${_CD_NAME_ON_CD})\n")
- endif()
if(_CD_TARGET)
#manage dependency
add_dependencies(bootcd ${_CD_TARGET})
@@ -259,13 +260,14 @@
add_dependencies(livecd ${_CD_TARGET})
endif()
foreach(item ${_CD_FILE})
- file(APPEND ${REACTOS_BINARY_DIR}/boot/livecd.cmake "file(COPY
\"${item}\" DESTINATION \"\${CD_DIR}/${_CD_DESTINATION}\")\n")
+ if(_CD_NAME_ON_CD)
+ #rename it in the cd tree
+ set(__file ${_CD_NAME_ON_CD})
+ else()
+ get_filename_component(__file ${item} NAME)
+ endif()
+ set_property(GLOBAL APPEND PROPERTY LIVECD_FILE_LIST
"${_CD_DESTINATION}/${__file}=${item}")
endforeach()
- if(_CD_NAME_ON_CD)
- get_filename_component(__file ${_CD_FILE} NAME)
- #rename it in the cd tree
- file(APPEND ${REACTOS_BINARY_DIR}/boot/livecd.cmake "file(RENAME
\${CD_DIR}/${_CD_DESTINATION}/${__file}
\${CD_DIR}/${_CD_DESTINATION}/${_CD_NAME_ON_CD})\n")
- endif()
endif() #end livecd
#do we add it to regtest?
@@ -275,13 +277,14 @@
if(_CD_NO_CAB)
#directly on cd
foreach(item ${_CD_FILE})
- file(APPEND ${REACTOS_BINARY_DIR}/boot/bootcdregtest.cmake
"file(COPY \"${item}\" DESTINATION
\"\${CD_DIR}/${_CD_DESTINATION}\")\n")
+ if(_CD_NAME_ON_CD)
+ #rename it in the cd tree
+ set(__file ${_CD_NAME_ON_CD})
+ else()
+ get_filename_component(__file ${item} NAME)
+ endif()
+ set_property(GLOBAL APPEND PROPERTY BOOTCDREGTEST_FILE_LIST
"${_CD_DESTINATION}/${__file}=${item}")
endforeach()
- if(_CD_NAME_ON_CD)
- get_filename_component(__file ${_CD_FILE} NAME)
- #rename it in the cd tree
- file(APPEND ${REACTOS_BINARY_DIR}/boot/bootcdregtest.cmake
"file(RENAME \${CD_DIR}/${_CD_DESTINATION}/${__file}
\${CD_DIR}/${_CD_DESTINATION}/${_CD_NAME_ON_CD})\n")
- endif()
if(_CD_TARGET)
#manage dependency
add_dependencies(bootcdregtest ${_CD_TARGET})
@@ -296,6 +299,23 @@
#endif()
endif()
endif() #end bootcd
+endfunction()
+
+function(create_iso_lists)
+ get_property(_filelist GLOBAL PROPERTY BOOTCD_FILE_LIST)
+ string(REPLACE ";" "\n" _filelist "${_filelist}")
+ file(APPEND ${REACTOS_BINARY_DIR}/boot/bootcd.lst "${_filelist}")
+ unset(_filelist)
+
+ get_property(_filelist GLOBAL PROPERTY LIVECD_FILE_LIST)
+ string(REPLACE ";" "\n" _filelist "${_filelist}")
+ file(APPEND ${REACTOS_BINARY_DIR}/boot/livecd.lst "${_filelist}")
+ unset(_filelist)
+
+ get_property(_filelist GLOBAL PROPERTY BOOTCDREGTEST_FILE_LIST)
+ string(REPLACE ";" "\n" _filelist "${_filelist}")
+ file(APPEND ${REACTOS_BINARY_DIR}/boot/bootcdregtest.lst "${_filelist}")
+ unset(_filelist)
endfunction()
# Create module_clean targets
Modified: trunk/reactos/media/vgafonts/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/vgafonts/CMakeLists.…
==============================================================================
--- trunk/reactos/media/vgafonts/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/media/vgafonts/CMakeLists.txt [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -18,4 +18,3 @@
add_custom_target(vgafonts DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vgafonts.cab)
add_cd_file(TARGET vgafonts FILE ${CMAKE_CURRENT_BINARY_DIR}/vgafonts.cab DESTINATION
reactos NO_CAB FOR all)
-add_cd_file(TARGET vgafonts FILE ${CMAKE_CURRENT_BINARY_DIR}/vgafonts.cab DESTINATION
reactos FOR all)
Modified: trunk/reactos/tools/cdmake/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/CMakeLists.tx…
==============================================================================
--- trunk/reactos/tools/cdmake/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/tools/cdmake/CMakeLists.txt [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -1,2 +1,2 @@
+add_executable(cdmake cdmake.c dirhash.c llmosrt.c)
-add_executable(cdmake cdmake.c llmosrt.c)
Modified: trunk/reactos/tools/cdmake/cdmake.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/cdmake.c?rev=…
==============================================================================
--- trunk/reactos/tools/cdmake/cdmake.c [iso-8859-1] (original)
+++ trunk/reactos/tools/cdmake/cdmake.c [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -33,8 +33,13 @@
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
# include <io.h>
# include <dos.h>
+# ifdef _MSC_VER
+# define R_OK 4
+# endif
#else
# if defined(__FreeBSD__) || defined(__APPLE__)
# include <sys/uio.h>
@@ -45,28 +50,19 @@
# include <sys/types.h>
# include <dirent.h>
# include <unistd.h>
+# define TRUE 1
+# define FALSE 0
#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
+#include "dirsep.h"
+#include "dirhash.h"
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
@@ -115,6 +111,7 @@
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;
@@ -172,6 +169,8 @@
DWORD joliet_path_table_size;
DWORD joliet_little_endian_path_table_sector;
DWORD joliet_big_endian_path_table_sector;
+
+struct target_dir_hash specified_files;
/*-----------------------------------------------------------------------------
This function edits a 32-bit unsigned number into a comma-delimited form, such
@@ -1067,6 +1066,159 @@
}
#endif
+
+static PDIR_RECORD
+new_empty_dirrecord(PDIR_RECORD d, BOOL directory)
+{
+ PDIR_RECORD new_d;
+ new_d = malloc(sizeof(*new_d));
+ memset(new_d, 0, 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;
+ 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;
+}
+
+#if _WIN32
+static int
+get_cd_file_time(HANDLE handle, DATE_AND_TIME *cd_time_info)
+{
+ FILETIME file_time;
+ SYSTEMTIME sys_time;
+ if (!GetFileTime(handle, NULL, NULL, &file_time))
+ {
+ return -1;
+ }
+ 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 - 1;
+ 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 0;
+}
+#endif
+
+static void
+scan_specified_files(PDIR_RECORD d, struct target_dir_entry *dir)
+{
+ PDIR_RECORD new_d;
+#if _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)
+ {
+#if _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("Can't open timestamp file %s\n",
file->source_name);
+ }
+
+ if (get_cd_file_time(open_file, &d->date_and_time) == -1)
+ {
+ error_exit("Can't stat timestamp file %s\n",
file->source_name);
+ }
+ CloseHandle(open_file);
+#else
+ if (stat(file->target_name, &stbuf) == -1)
+ {
+ error_exit("Can't 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);
+#if _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("Can't open file %s\n", file->source_name);
+ }
+ if (get_cd_file_time(open_file, &new_d->date_and_time) == -1)
+ {
+ error_exit("Can't stat file %s\n", file->source_name);
+ }
+ if (!GetFileSizeEx(open_file, &file_size))
+ {
+ error_exit("Can't 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("Can't 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
@@ -1455,14 +1607,23 @@
}
else
{
+ const char *file_source;
old_end_source = end_source;
- get_file_specifications(q);
- *end_source = 0;
+ 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 %s\n", source);
- file = fopen(source, "rb");
+ printf("Writing contents of %s\n", file_source);
+ file = fopen(file_source, "rb");
if (file == NULL)
- error_exit("Can't open %s\n", source);
+ error_exit("Can't open %s\n", file_source);
fseek(file, 0, SEEK_SET);
while (size > 0)
{
@@ -1472,7 +1633,7 @@
if (fread (cd.buffer + cd.count, n, 1, file) < 1)
{
fclose(file);
- error_exit("Read error in file %s\n", source);
+ error_exit("Read error in file %s\n", file_source);
}
cd.count += n;
if (cd.count == BUFFER_SIZE)
@@ -1626,23 +1787,71 @@
if (cd.filespecs[0] == 0)
error_exit("Missing image file specifications");
-
- // 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);
-
- // sort path table entries
-
- root.next_in_path_table = sort_linked_list(root.next_in_path_table, 1,
- compare_path_table_order);
+ 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, *srcname, *eq;
+ char lineread[1024];
+ FILE *f = fopen(source+1, "r");
+ if (!f)
+ {
+ error_exit("Can't open cd 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)
+ {
+ char *normdir;
+ /* 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, "");
+
+#if _WIN32
+ if (_access(srcname, R_OK) == 0)
+ dir_hash_add_file(&specified_files, srcname, targetname);
+ else
+ error_exit("can't access file '%s' (target %s)\n",
srcname, targetname);
+#else
+ if (access(srcname, R_OK) == 0)
+ dir_hash_add_file(&specified_files, srcname, targetname);
+ else
+ error_exit("can't access file '%s' (target %s)\n",
srcname, targetname);
+#endif
+ }
+ }
+ 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
@@ -1704,9 +1913,9 @@
if (verbosity >= NORMAL)
puts("CD-ROM image made successfully");
+ dir_hash_destroy(&specified_files);
release_memory();
return 0;
}
-
/* EOF */
Added: trunk/reactos/tools/cdmake/dirhash.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/dirhash.c?rev…
==============================================================================
--- trunk/reactos/tools/cdmake/dirhash.c (added)
+++ trunk/reactos/tools/cdmake/dirhash.c [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -0,0 +1,205 @@
+#include <string.h>
+#include <malloc.h>
+#include "dirsep.h"
+#include "dirhash.h"
+
+/* 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 const char *
+chop_filename(const char *target)
+{
+ char *last_slash = strrchr(target, '/');
+ if (!last_slash)
+ last_slash = strrchr(target, '\\');
+ if (last_slash)
+ return last_slash + 1;
+ else
+ return target;
+}
+
+static void
+chop_dirname(const char *name, char **dirname)
+{
+ char *last_slash = strrchr(name, '/');
+ if (!last_slash)
+ last_slash = strrchr(name, '\\');
+ if (!last_slash)
+ {
+ free(*dirname);
+ *dirname = malloc(1);
+ **dirname = 0;
+ }
+ else
+ {
+ char *newdata = malloc(last_slash - name + 1);
+ memcpy(newdata, name, last_slash - name);
+ newdata[last_slash - name] = 0;
+ free(*dirname);
+ *dirname = newdata;
+ }
+}
+
+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;
+ return de;
+}
+
+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;
+}
+
+struct target_dir_entry *
+dir_hash_create_dir(struct target_dir_hash *dh, const char *casename, const char
*targetnorm)
+{
+ unsigned int hashcode;
+ struct target_dir_entry *de, *parent_de;
+ char *parentname = NULL;
+ char *parentcase = NULL;
+ struct target_dir_entry **ent;
+ if (!dh->root.normalized_name)
+ {
+ dh->root.normalized_name = strdup("");
+ dh->root.case_name = strdup("");
+ hashcode = djb_hash("");
+ dh->buckets[hashcode % NUM_DIR_HASH_BUCKETS] = &dh->root;
+ }
+ de = get_entry_by_normname(dh, targetnorm);
+ if (de)
+ return de;
+ chop_dirname(targetnorm, &parentname);
+ chop_dirname(casename, &parentcase);
+ parent_de = dir_hash_create_dir(dh, parentcase, parentname);
+ free(parentname);
+ free(parentcase);
+ hashcode = djb_hash(targetnorm);
+ de = malloc(sizeof(*de));
+ memset(de, 0, sizeof(*de));
+ de->parent = parent_de;
+ de->normalized_name = strdup(targetnorm);
+ de->case_name = strdup(chop_filename(casename));
+ de->next = parent_de->child;
+ parent_de->child = de;
+ ent = &dh->buckets[hashcode % NUM_DIR_HASH_BUCKETS];
+ while ((*ent))
+ {
+ ent = &(*ent)->next;
+ }
+ *ent = de;
+ return de;
+}
+
+void dir_hash_add_file(struct target_dir_hash *dh, const char *source, const char
*target)
+{
+ unsigned int hashcode;
+ struct target_file *tf;
+ struct target_dir_entry *de;
+ const char *filename = chop_filename(target);
+ char *targetdir = NULL;
+ char *targetnorm;
+ chop_dirname(target, &targetdir);
+ targetnorm = strdup(targetdir);
+ normalize_dirname(targetnorm);
+ de = dir_hash_create_dir(dh, targetdir, targetnorm);
+ tf = malloc(sizeof(*tf));
+ memset(tf, 0, sizeof(*tf));
+ tf->next = de->head;
+ de->head = tf;
+ tf->source_name = strdup(source);
+ tf->target_name = strdup(filename);
+}
+
+struct target_dir_entry *
+dir_hash_next_dir(struct target_dir_hash *dh, struct target_dir_traversal *t)
+{
+ if (t->i == -1)
+ return NULL;
+ if (!t->it)
+ {
+ while (++t->i != NUM_DIR_HASH_BUCKETS)
+ {
+ if (dh->buckets[t->i])
+ {
+ t->it = dh->buckets[t->i];
+ return t->it;
+ }
+ }
+ t->i = -1;
+ return NULL;
+ }
+ else
+ {
+ t->it = t->it->next;
+ if (!t->it)
+ {
+ t->i = -1;
+ return NULL;
+ }
+ else
+ return t->it;
+ }
+}
+
+void dir_hash_destroy_dir(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(te);
+ free(te);
+ }
+ while ((tf = de->head))
+ {
+ de->head = tf->next;
+ free(tf->source_name);
+ free(tf->target_name);
+ free(tf);
+ }
+ free(de->normalized_name);
+ free(de->case_name);
+}
+
+void dir_hash_destroy(struct target_dir_hash *dh)
+{
+ dir_hash_destroy_dir(&dh->root);
+}
Propchange: trunk/reactos/tools/cdmake/dirhash.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/tools/cdmake/dirhash.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/dirhash.h?rev…
==============================================================================
--- trunk/reactos/tools/cdmake/dirhash.h (added)
+++ trunk/reactos/tools/cdmake/dirhash.h [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -0,0 +1,38 @@
+#ifndef _REACTOS_TOOLS_CDMAKE_DIRHASH_H_
+#define _REACTOS_TOOLS_CDMAKE_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 {
+ 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;
+};
+
+struct target_dir_traversal {
+ struct target_dir_entry *it;
+ int i;
+};
+
+void normalize_dirname(char *filename);
+void dir_hash_add_file(struct target_dir_hash *dh, const char *source, const char
*target);
+struct target_dir_entry *
+dir_hash_create_dir(struct target_dir_hash *dh, const char *casename, const char
*targetnorm);
+struct target_dir_entry *dir_hash_next_dir(struct target_dir_hash *dh, struct
target_dir_traversal *t);
+void dir_hash_destroy(struct target_dir_hash *dh);
+
+#endif//_REACTOS_TOOLS_CDMAKE_DIRHASH_H_
Propchange: trunk/reactos/tools/cdmake/dirhash.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/tools/cdmake/dirsep.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/cdmake/dirsep.h?rev=…
==============================================================================
--- trunk/reactos/tools/cdmake/dirsep.h (added)
+++ trunk/reactos/tools/cdmake/dirsep.h [iso-8859-1] Sun Jul 21 13:33:03 2013
@@ -0,0 +1,10 @@
+#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
Propchange: trunk/reactos/tools/cdmake/dirsep.h
------------------------------------------------------------------------------
svn:eol-style = native