mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-31 19:26:42 +00:00
[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. svn path=/trunk/; revision=70552
This commit is contained in:
@@ -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 @@ djb_hash(const char *name)
|
||||
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)
|
||||
split_path(const char *path, char **dirname, char **filename /* OPTIONAL */)
|
||||
{
|
||||
char *last_slash = strrchr(name, '/');
|
||||
if (!last_slash)
|
||||
last_slash = strrchr(name, '\\');
|
||||
if (!last_slash)
|
||||
{
|
||||
*dirname = malloc(1);
|
||||
**dirname = 0;
|
||||
}
|
||||
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
|
||||
{
|
||||
char *newdata = malloc(last_slash - name + 1);
|
||||
memcpy(newdata, name, last_slash - name);
|
||||
newdata[last_slash - name] = 0;
|
||||
*dirname = newdata;
|
||||
}
|
||||
}
|
||||
result = path;
|
||||
|
||||
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;
|
||||
}
|
||||
/* Duplicate the file name for the user if needed */
|
||||
if (filename)
|
||||
*filename = strdup(result);
|
||||
|
||||
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;
|
||||
/* 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 @@ void normalize_dirname(char *filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
filename[tgt] = 0;
|
||||
filename[tgt] = '\0'; // NULL-terminate
|
||||
}
|
||||
|
||||
while (tgt && (filename[--tgt] == DIR_SEPARATOR_CHAR))
|
||||
{
|
||||
filename[tgt] = 0;
|
||||
}
|
||||
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 *parentname = NULL;
|
||||
char *parentcase = NULL;
|
||||
char *case_name = NULL;
|
||||
char *parentname = NULL;
|
||||
struct target_dir_entry **ent;
|
||||
|
||||
if (!dh->root.normalized_name)
|
||||
@@ -133,20 +129,32 @@ dir_hash_create_dir(struct target_dir_hash *dh, const char *casename, const char
|
||||
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 @@ dir_hash_create_dir(struct target_dir_hash *dh, const char *casename, const char
|
||||
|
||||
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 @@ void dir_hash_add_file(struct target_dir_hash *dh, const char *source, const cha
|
||||
{
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user