Author: hbelusca
Date: Fri Jan 8 18:43:46 2016
New Revision: 70552
URL:
http://svn.reactos.org/svn/reactos?rev=70552&view=rev
Log:
[CDMAKE]
- Optimize splitting paths (merge chop_dirname and chop_filename functions).
- Make the code working as expected for the following testcases (you can test these by
adding the following lines into e.g. bootcd.lst):
testdir1 --> create "testdir1" in the root directory.
testdir2/ --> create "testdir2" in the root directory. No no-named
subdirectory is created.
testdir3// --> create "testdir3" in the root directory. No no-named
subdirectory is created.
dir1//\/dir14///\//\// --> create "dir1" in the root directory, and
"dir14" inside dir1. No no-named subdirectory is created.
EFI/ReactOS/Boot/Fonts//chs_boot.ttf=C:/somepath/chs_boot.ttf --> create the
directories "EFI/ReactOS/Boot/Fonts", no no-named subdirectory is created, and
create in the Fonts directory the file "chs_boot.ttf".
Before those changes, empty no-named (therefore, invalid) subdirectories were created in
the second, third and fourth testcases, and an obscure error was returned in the fifth
testcase.
Modified:
trunk/reactos/tools/cdmake/dirhash.c
Modified: 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 [iso-8859-1] (original)
+++ trunk/reactos/tools/cdmake/dirhash.c [iso-8859-1] Fri Jan 8 18:43:46 2016
@@ -5,12 +5,15 @@
* PURPOSE: CD-ROM Premastering Utility - Directory names hashing
* PROGRAMMERS: Art Yerkes
*/
+
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "config.h"
#include "dirhash.h"
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
/* This is the famous DJB hash */
static unsigned int
djb_hash(const char *name)
@@ -26,59 +29,33 @@
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;
+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
- 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)
- {
- *dirname = malloc(1);
- **dirname = 0;
- }
- else
- {
- char *newdata = malloc(last_slash - name + 1);
- memcpy(newdata, name, last_slash - name);
- newdata[last_slash - name] = 0;
- *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_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;
+ 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)
@@ -109,20 +86,39 @@
}
}
}
- filename[tgt] = 0;
-
- while (tgt && (filename[--tgt] == DIR_SEPARATOR_CHAR))
- {
- filename[tgt] = 0;
- }
+ 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;
- char *parentcase = NULL;
struct target_dir_entry **ent;
if (!dh->root.normalized_name)
@@ -133,20 +129,32 @@
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;
- chop_dirname(targetnorm, &parentname);
- chop_dirname(casename, &parentcase);
+ /*
+ * 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) return parent_de;
+
+ /* Now create the directory */
de = calloc(1, sizeof(*de));
de->parent = parent_de;
de->normalized_name = strdup(targetnorm);
- de->case_name = strdup(chop_filename(casename));
+ de->case_name = case_name;
de->hashcode = djb_hash(targetnorm);
de->next = parent_de->child;
@@ -154,9 +162,7 @@
ent = &dh->buckets[de->hashcode % NUM_DIR_HASH_BUCKETS];
while (*ent)
- {
ent = &(*ent)->next_dir_hash_entry;
- }
*ent = de;
return de;
@@ -166,21 +172,24 @@
{
struct target_file *tf;
struct target_dir_entry *de;
- char *targetdir = NULL;
+ char *targetdir = NULL;
+ char *targetfile = NULL;
char *targetnorm;
- chop_dirname(target, &targetdir);
+ /* Create first the directory */
+ split_path(target, &targetdir, &targetfile);
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 = strdup(chop_filename(target));
+ tf->target_name = targetfile;
}
static void