diff --git a/source_code/include/smb/smb_fs_sb.h b/source_code/include/smb/smb_fs_sb.h index d3a7b40..2489b93 100644 --- a/source_code/include/smb/smb_fs_sb.h +++ b/source_code/include/smb/smb_fs_sb.h @@ -18,6 +18,8 @@ #include #endif /* _SMB_MOUNT_H */ +#include "kvs.h" + struct smb_server { enum smb_protocol protocol; /* The protocol this @@ -88,6 +90,10 @@ struct smb_server /* olsen (2018-06-11): Prefer SMB core protocol commands over NT1 commands. */ int prefer_core_protocol; + + // Tygre 21/05/15: Stores for UTF16le strings and their sizes + KVSstore *latin1_to_utf16le_bytes; + KVSstore *latin1_to_utf16le_sizes; }; #endif diff --git a/source_code/kvs.c b/source_code/kvs.c new file mode 100644 index 0000000..95c39b7 --- /dev/null +++ b/source_code/kvs.c @@ -0,0 +1,346 @@ +/* + * http://codereview.stackexchange.com/questions/63493/simple-key-value-store-in-c-take-2 + * CC BY-SA + * + * Parts copyright (c) 2015-2021 Tygre + * These parts are under the same license CC BY-SA as the original source code. + */ + + + +/* Includes */ + +#include "kvs.h" + +#include // For realloc()... +#include // For memmove()... + + + +/* Constants and declarations */ + +struct KVSpair { + const KVSkey *key; + KVSvalue *value; +}; + +struct KVSstore { + KVSpair *pairs; + const KVScompare *compare; + size_t length; + size_t space; +}; + + KVSstore *kvs_create(const KVScompare *); + void kvs_destroy(const KVSstore *); + void kvs_put(const KVSstore *, const KVSkey *, const KVSvalue *); + KVSkey *kvs_get_key(const KVSstore *, const size_t); + KVSvalue *kvs_get_value(const KVSstore *, const KVSkey *); + void kvs_remove(const KVSstore *, const KVSkey *); + size_t kvs_length(const KVSstore *); + int kvs_compare_pointers(const KVSkey *, const KVSkey *); + int kvs_compare_unsigned_longs(const KVSkey *, const KVSkey *); + int kvs_compare_strings(const KVSkey *, const KVSkey *); +static KVSpair *kvs_search(const KVSstore *, const KVSkey *, const int); +static KVSpair *kvs_get_pair(const KVSstore *, const KVSkey *); +static void kvs_resize_pairs(const KVSstore *, const size_t); +static void _kvs_resize_pairs(const KVSstore *, const size_t); +static size_t kvs_get_pair_index(const KVSstore *, const KVSpair *); +static size_t kvs_get_bytes_from_pair(const KVSstore *, const KVSpair *); +static void kvs_create_pair(const KVSstore *, const KVSkey *, const KVSvalue *); +static void kvs_remove_pair(const KVSstore *, const KVSpair *); + +static const size_t _kvs_pair_size = sizeof(KVSpair); +static const size_t _kvs_store_size = sizeof(KVSstore); + + + +/* Definitions */ + +KVSstore *kvs_create( + const KVScompare *compare) +{ + KVSstore *store = malloc(_kvs_store_size); + if(store == NULL) + { + // TODO: Add SMBFS-compliant error reporting + // log_print_fatal_error( GetString( MSG_KVS_KVSCREATECOULDNOTALLOCATEMEMORY ) ); + return NULL; + } + + store->pairs = NULL; + store->length = 0; + store->space = 0; + if(compare) + { + store->compare = compare; + } + else + { + store->compare = kvs_compare_pointers; + } + kvs_resize_pairs(store, 0); + return store; +} + +void kvs_destroy( + const KVSstore *store) +{ + KVSkey *key = NULL; + KVSvalue *value = NULL; + int length = 0; + + if(!store) + { + return; + } + if(store->pairs) + { + length = kvs_length(store); + while(length > 0) + { + length--; + + key = kvs_get_key (store, length); + value = kvs_get_value(store, key); + + // printf("ppp %p %p\n", key, value); + // printf("### %s <-> %s\n", (char *)key, (char *)value); + // printf("@@@ %lu <-> %s\n", *((ULONG *)key), (char *)value); + + free((void *)key); + free((void *)value); + } + free((void *)store->pairs); + } + free((void *)store); +} + +void kvs_put( + const KVSstore *store, + const KVSkey *key, + const void *value) +{ + KVSpair *pair = kvs_get_pair(store, key); + if(pair) + { + if(value) + { + free((void *)pair->key); + free((void *)pair->value); + + pair->key = (void *)key; + pair->value = (void *)value; + } + else + { + kvs_remove_pair(store, pair); + } + } + else if(value) + { + kvs_create_pair(store, key, value); + } +} + +KVSkey *kvs_get_key( + const KVSstore *store, + const size_t index) +{ + if((!store) || (index >= store->length)) + { + return NULL; + } + return (store->pairs + index)->key; +} + +KVSvalue *kvs_get_value( + const KVSstore *store, + const KVSkey *key) +{ + KVSpair *pair = kvs_get_pair(store, key); + return pair ? pair->value : NULL; +} + +void kvs_remove( + const KVSstore *store, + const KVSkey *key) +{ + kvs_put(store, key, NULL); +} + +size_t kvs_length( + const KVSstore *store) +{ + if(!store) + { + return 0; + } + return store->length; +} + +int kvs_compare_pointers( + const KVSkey *a, + const KVSkey *b) +{ + return (char *)a - (char *)b; +} + +int kvs_compare_unsigned_longs( + const KVSkey *a, + const KVSkey *b) +{ + ULONG x = *((ULONG *)a); + ULONG y = *((ULONG *)b); + + return (int)(x - y); +} + +int kvs_compare_strings( + const KVSkey *a, + const KVSkey *b) +{ + char *x = (char *)a; + char *y = (char *)b; + + return strcmp(x, y); +} + +static KVSpair *kvs_search( + const KVSstore *store, + const KVSkey *key, + const int exact) +{ + size_t lbound = 0; + size_t rbound = store->length; + size_t index = 0; + KVSpair *element = NULL; + KVSpair *pairs = store->pairs; + int result = 0; + KVScompare *compare = (KVScompare *)store->compare; + // Cannot compile with VBCC v0.8f or v0.9g because of "internal error 0 in line 5307 of file machines/m68k/machine.c": + // const KVScompare *compare = store->compare; + + while(lbound < rbound) + { + index = lbound + ((rbound - lbound) >> 1); + element = pairs + index; + result = compare(key, element->key); + if(result < 0) + { + rbound = index; + } + else if(result > 0) + { + lbound = index + 1; + } + else + { + return element; + } + } + return exact ? NULL : pairs + lbound; +} + +static KVSpair *kvs_get_pair( + const KVSstore *store, + const KVSkey *key) +{ + if((!store) || (!store->pairs)) + { + return NULL; + } + return kvs_search(store, key, 1); +} + +static void kvs_resize_pairs( + const KVSstore *store, + const size_t amount) +{ + _kvs_resize_pairs((KVSstore *)store, amount); +} + +static void _kvs_resize_pairs( + const KVSstore *store, + const size_t amount) +{ + if(!store) + { + return; + } + ((KVSstore *)store)->length += amount; + if(store->space > store->length * _kvs_pair_size) + { + return; + } + ((KVSstore *)store)->space += _kvs_pair_size; + ((KVSstore *)store)->pairs = realloc(store->pairs, store->space); + + if(store->pairs == NULL) + { + // TODO: Add SMBFS-compliant error reporting + // log_print_fatal_error( GetString( MSG_KVS_KVSRESIZEPAIRSCOULDNOTALLOCATEMEMORY ) ); + } +} + +static size_t kvs_get_pair_index( + const KVSstore *store, + const KVSpair *pair) +{ + if((!store) || (!pair)) + { + return -1; + } + return (size_t)(pair - store->pairs); +} + +static size_t kvs_get_bytes_from_pair( + const KVSstore *store, + const KVSpair *pair) +{ + size_t pair_index; + + if((!store) || (!pair)) + { + return 0; + } + pair_index = kvs_get_pair_index(store, pair); + return (store->length - pair_index) * _kvs_pair_size; +} + +static void kvs_create_pair( + const KVSstore *store, + const KVSkey *key, + const KVSvalue *value) +{ + KVSpair *pair; + + if(!store) + { + return; + } + pair = kvs_search(store, key, 0); + if(pair < store->pairs + store->length) + { + size_t bytes = kvs_get_bytes_from_pair(store, pair); + memmove(pair + 1, pair, bytes); + } + pair->key = (void *)key; + pair->value = (void *)value; + kvs_resize_pairs(store, +1); +} + +static void kvs_remove_pair( + const KVSstore *store, + const KVSpair *pair) +{ + if((!store) || (!pair)) + { + return; + } + free((void *)pair->key); + free((void *)pair->value); + memmove((void *)pair, (void *)(pair + 1), kvs_get_bytes_from_pair(store, pair + 1)); + kvs_resize_pairs(store, -1); +} + diff --git a/source_code/kvs.h b/source_code/kvs.h new file mode 100644 index 0000000..1e1641f --- /dev/null +++ b/source_code/kvs.h @@ -0,0 +1,57 @@ +/* + * http://codereview.stackexchange.com/questions/63493/simple-key-value-store-in-c-take-2 + * CC BY-SA + * + * Changes by Tygre as part of AmiModRadio. + * tygre@chingu.asia + */ + +#ifndef KVS_H +#define KVS_H 1 + +#include + +typedef struct KVSstore KVSstore; +typedef struct KVSpair KVSpair; +typedef void KVSkey; +typedef void KVSvalue; +typedef int KVScompare(const KVSkey *a, const KVSkey *b); + +KVSstore *kvs_create( + const KVScompare *compare); + +void kvs_destroy( + const KVSstore *store); + +void kvs_put( + const KVSstore *store, + const KVSkey *key, + const KVSvalue *value); + +KVSkey *kvs_get_key( + const KVSstore *store, + const size_t index); + +KVSvalue *kvs_get_value( + const KVSstore *store, + const KVSkey *key); + +void kvs_remove( + const KVSstore *store, + const KVSkey *key); + +size_t kvs_length( + const KVSstore *store); + +int kvs_compare_pointers( + const KVSkey *a, + const KVSkey *b); + +int kvs_compare_unsigned_longs( + const KVSkey *a, + const KVSkey *b); + +int kvs_compare_strings( + const KVSkey *a, + const KVSkey *b); +#endif diff --git a/source_code/main.c b/source_code/main.c index d5c6136..13e1a09 100644 --- a/source_code/main.c +++ b/source_code/main.c @@ -272,9 +272,9 @@ static void file_system_handler(BOOL raise_priority, const TEXT * volume_name, c /****************************************************************************/ struct Library * SysBase; -struct Library * DOSBase; +struct DosLibrary * DOSBase; struct Library * UtilityBase; -struct Library * IntuitionBase; +struct IntuitionBase * IntuitionBase; struct Library * SocketBase; struct Library * LocaleBase; struct Library * TimerBase; @@ -1606,6 +1606,11 @@ main(void) goto out; } + // Tygre 2021/04/30: Mutual exclusion + // SMBFS should warn if options TRANSLATE + // and UNICODE=ON are combined, because + // TRANSLATE silently switches OFF UNICODE. + /* Code page based translation using a file disables * Unicode support and the built-in CP437 and CP850 * translation. @@ -10475,7 +10480,6 @@ file_system_handler( * doesn't happen). */ Quiet = TRUE; - done = FALSE; if(raise_priority) diff --git a/source_code/proc.c b/source_code/proc.c index fa53548..abaad54 100644 --- a/source_code/proc.c +++ b/source_code/proc.c @@ -268,6 +268,28 @@ static void convert_time_t_to_long_date(time_t t, QUAD * long_date); /*****************************************************************************/ +static int +size_utf16le_of_latin1(const struct smb_server *server, const byte *from) +{ + const byte* from1; + int latin1_part_size; + + from1 = strrchr(from, '\\'); + from1++; + + latin1_part_size = (from1 - from) * 2; // * 2 because UTF16 + + if(NULL != kvs_get_value(server->latin1_to_utf16le_bytes, from1)) + { + // report_error("%s is in store! (1)", from1); + return latin1_part_size + atoi(kvs_get_value(server->latin1_to_utf16le_sizes, from1)); + } + else + { + return -1; + } +} + /* Copy a string in ISO-Latin-1 form (8 bits per character) into a * buffer, converting it into a little-endian 16 bit Unicode version * of the string. This works because the ISO-Latin-1 character sits @@ -282,11 +304,43 @@ static void convert_time_t_to_long_date(time_t t, QUAD * long_date); * output buffer is filled. */ static int -copy_latin1_to_utf16le(byte * to,int to_size, const byte * from,int len) +copy_latin1_to_utf16le(const struct smb_server *server, byte * to,int to_size, const byte * from,int len) { int num_bytes_written = 0; int i; + // Tygre 21/05/15: Asymmetry + // The arguments of this function are not symetrical + // with those of copy_utf16le_to_latin1(). While in + // copy_utf16le_to_latin1(), the "from" represents + // a single part of a path, i.e., "toto". Here, the + // "from" includes the whole path, i.e., "a\b\toto". + // + // Right now, I *ASSUME* that only the file name, + // i.e., the last part of the path, can be non-Latin1. + // I replace this last part with the stored original + // UTF16le name if it exists. + const byte* from1; + long id_l; + char* id_s; + BOOL is_stored; + + from1 = strrchr(from, '\\'); + from1++; + id_s = malloc(11); + if(NULL == id_s) + { + return -1; + } + is_stored = FALSE; + + if(NULL != kvs_get_value(server->latin1_to_utf16le_bytes, from1)) + { + // report_error("%s is in store! (2)", from1); + is_stored = TRUE; + len = len - strlen(from1); + } + /* We have to have enough room to NUL-terminate the * resulting converted string. */ @@ -306,11 +360,45 @@ copy_latin1_to_utf16le(byte * to,int to_size, const byte * from,int len) num_bytes_written += 2; } - /* And we terminate that string... */ - (*to++) = '\0'; - (*to) = '\0'; + // Tygre 21/05/15: Stored UTF16le + if(is_stored) + { + /* No needdd to take care of the NUL. */ + to_size += 2; - num_bytes_written += 2; + /* We already wrote some bytes */ + to_size -= num_bytes_written; + + + id_l = atoi(kvs_get_value(server->latin1_to_utf16le_sizes, from1)); + // sprintf(id_s, "%ld", id_l); + // report_error("Retrieving %s bytes for %s", id_s, from1); + // sprintf(id_s, "%ld", to_size); + // report_error("To be copied in %s bytes", id_s); + if(id_l > to_size) + { + report_error("Cannot copy all bytes for lack of space!"); + } + else if(id_l < to_size) + { + report_error("Cannot fill in all space!"); + } + + memcpy( + to, + kvs_get_value(server->latin1_to_utf16le_bytes, from1), + to_size); + + num_bytes_written += to_size; + } + else + { + /* And we terminate that string... */ + (*to++) = '\0'; + (*to) = '\0'; + + num_bytes_written += 2; + } } return(num_bytes_written); @@ -335,11 +423,34 @@ copy_latin1_to_utf16le(byte * to,int to_size, const byte * from,int len) * output buffer is filled. */ static int -copy_utf16le_to_latin1(byte * to,int to_size,const byte * from,int len) +copy_utf16le_to_latin1(const struct smb_server *server, byte * to, int to_size, const byte * from, int len) { int num_bytes_written = 0; word c; - int i; + int i, j; + + // Tygre 21/05/08: Encoding of non-Latin1 names + // The maximum number of chars for representing a long is 10 on 32-bit computers (2147483647) + #define LONG_MAX_CHARS 10 + // The maximum number of chars for a file name in OFS + #define MAX_SIZE 31 + const byte* from1; + byte* from1_copy; + byte* to1; + long tmp_l; + byte* tmp_s; + long id_l; + char* id_s; + BOOL should_store; + char tmp[MAX_SIZE]; + + from1 = from; + to1 = to; + id_s = malloc(LONG_MAX_CHARS + 1); // LONG_MAX_CHARS plus NUL + if(NULL == id_s) + { + return -1; + } /* We have to have enough room to NUL-terminate the * resulting converted string. @@ -349,7 +460,7 @@ copy_utf16le_to_latin1(byte * to,int to_size,const byte * from,int len) /* That takes care of the NUL. */ to_size -= 1; - for(i = 0 ; i < len ; i++, from += 2) + for(i = 0, id_l = 0, should_store = FALSE; i < len ; i++, from += 2) { if(num_bytes_written + 1 > to_size) break; @@ -365,16 +476,180 @@ copy_utf16le_to_latin1(byte * to,int to_size,const byte * from,int len) */ c = ((word)from[1] << 8) | from[0]; if(c >= 256) - c = 0x80; - - (*to++) = c; - num_bytes_written++; + { + // Tygre 21/05/08: Encoding + // Replace non-Latin1 chars by 'X' + // and sum up their values to make + // up an encoding. + should_store = TRUE; + id_l += c; + (*to++) = 'X'; + num_bytes_written++; + } + else + { + id_l += c; + (*to++) = c; + num_bytes_written++; + } } /* And we terminate that string... */ (*to) = '\0'; - num_bytes_written++; + + // Tygre 21/05/08: Encoding of non-Latin1 names + // I can memmove happily because to_size is always 255 + // and thus greater than the longest file name (107) + // and the dozen chars that I add. + // Tested with six files whose names are (with X for non-Latin1 chars): + // - <40 chars> + // - <40 chars>.txt + // - <40 chars>.<40 chars> + // - <5 chars> + // - <5 chars>.txt + // - <5 chars>.<40 chars> + if(should_store) + { + // 1. Replace non-Latin1 names with a unique (?) number + // TOO SIMPLISTIC + /* + sprintf(id_s, "%0*ld", LONG_MAX_CHARS, id_l); + memmove(to1, id_s, LONG_MAX_CHARS + 1); + num_bytes_written = LONG_MAX_CHARS + 1; + */ + + // 2. Replace non-Latin1 names with a unique (?) number and add extension + // BETTER BUT WHAT IF EXTENSION IS LOOONG? + /* + if(tmp_s = strrchr(to1, '.')) + { + tmp_l = strlen(tmp_s); + memmove(to1 + LONG_MAX_CHARS, tmp_s, tmp_l + 1); // "+ 1" to include the NUL + } + else + { + tmp_l = 0; + (*(to1 + LONG_MAX_CHARS)) = '\0'; + } + sprintf(id_s, "%0*ld", LONG_MAX_CHARS, id_l); + memmove(to1, id_s, LONG_MAX_CHARS); + num_bytes_written = LONG_MAX_CHARS + tmp_l + 1; + */ + + // 3. Prefix non-Latin1 names with unique (?) number + // WHAT ABOUT FILE NAMES GREATER THAN A LIMIT? (31 or 107...) + /* + sprintf(id_s, "%0*ld", LONG_MAX_CHARS, id_l); + if(num_bytes_written > to_size - LONG_MAX_CHARS - 1) + { + num_bytes_written = num_bytes_written - (to_size - LONG_MAX_CHARS - 1 - num_bytes_written); + } + memmove(to1 + (LONG_MAX_CHARS + 1), to1, num_bytes_written); + memmove(to1, id_s, LONG_MAX_CHARS); + (*(to1 + LONG_MAX_CHARS)) = ' '; + to = to + (LONG_MAX_CHARS + 1); + (*to) = '\0'; + num_bytes_written += (LONG_MAX_CHARS + 1); + */ + + // 4. Postfix, before any '.', non-Latin1 names with unique (?) number + // WHAT ABOUT FILE NAMES GREATER THAN A LIMIT? (31 or 107...) + /* + sprintf(id_s, "%0*ld", LONG_MAX_CHARS, id_l); + if(NULL != (tmp = strrchr(to1, '.'))) + { + memmove(tmp + (LONG_MAX_CHARS + 1), tmp, strlen(tmp) + 1); // + 1 to include the NUL + to = tmp; + } + (*to++) = ' '; + memmove(to, id_s, LONG_MAX_CHARS); + to += LONG_MAX_CHARS; + num_bytes_written += strlen(to1) + 1; + */ + + // 5. Keep as many chars of the extension as possible (with Xs for non-Latin1 chars). + // Insert the unique ID before the extension, the ID is always LONG_MAX_CHARS long. + // Keep as many chars of the original name (with Xs for non-Latin1 chars). + /* + #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) + #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) + if(tmp_s = strrchr(to1, '.')) + { + tmp_l = strlen(tmp_s); + if(tmp_l > MAX_SIZE - 1 - LONG_MAX_CHARS - 1) + { + j = MAX_SIZE - 1 - LONG_MAX_CHARS - 1; + sprintf(tmp, "@%0*ld%.*s", LONG_MAX_CHARS, id_l, j, tmp_s); + } + else + { + j = tmp_l; + tmp_l = strlen(to1) - j; + i = MIN(tmp_l, MAX_SIZE - j - 1 - 1 - LONG_MAX_CHARS - 1); + sprintf(tmp, "%.*s @%0*ld%.*s", i, to1, LONG_MAX_CHARS, id_l, j, tmp_s); + } + } + else + { + tmp_l = strlen(to1); + i = MIN(tmp_l, MAX_SIZE - 1 - 1 - LONG_MAX_CHARS - 1); + sprintf(tmp, "%.*s @%0*ld", i, LONG_MAX_CHARS, id_l); + } + memmove(to1, tmp, tmp_l + 1); + num_bytes_written = tmp_l + 1; + */ + + + // 6. Keep as many chars of the extension as possible (with Xs for non-Latin1 chars). + // Insert the unique ID before the extension, as long as need but no longer. + // Keep as many chars of the original name (with Xs for non-Latin1 chars). + #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) + #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) + sprintf(id_s, "%ld", id_l); + if(tmp_s = strrchr(to1, '.')) + { + tmp_l = strlen(tmp_s); + if(tmp_l > MAX_SIZE - 1 - strlen(id_s) - 1) + { + j = MAX_SIZE - 1 - strlen(id_s) - 1; + tmp_l = sprintf(tmp, "@%s%.*s", id_s, j, tmp_s); + } + else + { + j = tmp_l; + tmp_l = strlen(to1) - j; + i = strlen(id_s); + i = MIN(tmp_l, MAX_SIZE - j - 1 - 1 - i - 1); + tmp_l = sprintf(tmp, "%.*s @%s%.*s", i, to1, id_s, j, tmp_s); + } + } + else + { + tmp_l = strlen(to1); + i = strlen(id_s); + i = MIN(tmp_l, MAX_SIZE - 1 - 1 - i - 1); + tmp_l = sprintf(tmp, "%.*s @%s", i, to1, id_s); + } + memmove(to1, tmp, tmp_l + 1); + num_bytes_written = tmp_l + 1; + + // If the bytes and their sizes are not already in store + if(NULL == kvs_get_value(server->latin1_to_utf16le_bytes, to1)) + { + id_l = len * 2; // "* 2" because each UTF16 char takes 2 bytes + from1_copy = malloc(id_l); // Make a copy of "from" of length "len" + if(NULL == from1_copy) + { + return -1; + } + memcpy(from1_copy, from1, id_l); + kvs_put(server->latin1_to_utf16le_bytes, to1, from1_copy); + + sprintf(id_s, "%ld", id_l); + kvs_put(server->latin1_to_utf16le_sizes, to1, id_s); + } + } } return(num_bytes_written); @@ -1287,7 +1562,16 @@ smb_proc_open ( if(server->unicode_enabled) { - pathname_size = 2 * (len + 1); + // Tygre 2015/05/29: Size in UTF16 + // The size is that of the bytes stored, + // plus the Latin1 path as prefix, not + // two bytes per char anymore in UTF16. + pathname_size = size_utf16le_of_latin1(server, pathname); + if(-1 == pathname_size) + { + // Default size + pathname_size = 2 * (len + 1); + } pathname_pad = 1; } else @@ -1369,8 +1653,7 @@ smb_proc_open ( * will be word-aligned. */ (*data++) = 0; - - (void) copy_latin1_to_utf16le(data, pathname_size, pathname, len); + (void) copy_latin1_to_utf16le(server, data, pathname_size, pathname, len); } else { @@ -1454,11 +1737,24 @@ smb_proc_open ( int path_size; if(server->unicode_enabled) - path_size = 1 + 2 * (len+1); + { + // Tygre 2015/05/29: Size in UTF16 + // The size is that of the bytes stored, + // plus the Latin1 path as prefix, not + // two bytes per char anymore in UTF16. + path_size = size_utf16le_of_latin1(server, pathname); + if(-1 == path_size) + { + // Default size + path_size = 2 * (len + 1); + } + } else - path_size = 1 + len+1; + { + path_size = len + 1; + } - ASSERT( smb_payload_size(server, 2, path_size) >= 0 ); + ASSERT( smb_payload_size(server, 2, 1 + path_size) >= 0 ); SHOWMSG("using the old SMB_COM_OPEN"); @@ -1469,14 +1765,14 @@ smb_proc_open ( else access_and_share_modes = SMB_OPEN_SHARE_DENY_NOTHING|SMB_OPEN_ACCESS_READ_ONLY; - p = smb_setup_header (server, SMBopen, 2, path_size); + p = smb_setup_header (server, SMBopen, 2, 1 + path_size); WSET (buf, smb_vwv0, access_and_share_modes); WSET (buf, smb_vwv1, SMB_FILE_ATTRIBUTE_HIDDEN|SMB_FILE_ATTRIBUTE_SYSTEM|SMB_FILE_ATTRIBUTE_DIRECTORY); if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - copy_latin1_to_utf16le(p,2 * (len+1),pathname,len); + copy_latin1_to_utf16le(server, p, path_size, pathname, len); } else { @@ -2159,22 +2455,35 @@ smb_proc_create (struct smb_server *server, const char *path, int len, struct sm #endif /* DEBUG */ if(server->unicode_enabled) - path_size = 1 + 2 * (len + 1); + { + // Tygre 2015/05/29: Size in UTF16 + // The size is that of the bytes stored, + // plus the Latin1 path as prefix, not + // two bytes per char anymore in UTF16. + path_size = size_utf16le_of_latin1(server, path); + if(-1 == path_size) + { + // Default size + path_size = 2 * (len + 1); + } + } else - path_size = 1 + len + 1; + { + path_size = len + 1; + } retry: - ASSERT( smb_payload_size(server, 3, path_size) >= 0 ); + ASSERT( smb_payload_size(server, 3, 1 + path_size) >= 0 ); - p = smb_setup_header (server, SMBcreate, 3, path_size); + p = smb_setup_header (server, SMBcreate, 3, 1 + path_size); WSET (buf, smb_vwv0, entry->attr); DSET (buf, smb_vwv1, local_time); if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - copy_latin1_to_utf16le(p,2 * (len+1),path,len); + copy_latin1_to_utf16le(server, p, path_size, path, len); } else { @@ -2212,6 +2521,7 @@ smb_proc_mv ( int size; int result; + // TODO: Tygre if(server->unicode_enabled) size = 2 + 1 + 2 * (old_path_len+1) + 2 * (new_path_len+1); else @@ -2228,12 +2538,12 @@ smb_proc_mv ( if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - p += copy_latin1_to_utf16le(p,2 * (old_path_len+1),old_path,old_path_len); + p += copy_latin1_to_utf16le(server, p,2 * (old_path_len+1),old_path,old_path_len); (*p++) = 4; /* A NUL-terminated string follows. */ (*p++) = 0; /* Padding byte, allowing for the string to be word-aligned. */ - (void) copy_latin1_to_utf16le(p,2 * (new_path_len+1),new_path,new_path_len); + (void) copy_latin1_to_utf16le(server, p,2 * (new_path_len+1),new_path,new_path_len); } else { @@ -2258,6 +2568,7 @@ smb_proc_mkdir (struct smb_server *server, const char *path, const int len, int int result; char *p; + // TODO: Tygre if(server->unicode_enabled) path_size = 2 * (len + 1); else @@ -2272,7 +2583,7 @@ smb_proc_mkdir (struct smb_server *server, const char *path, const int len, int if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - (void) copy_latin1_to_utf16le(p,path_size,path,len); + (void) copy_latin1_to_utf16le(server, p,path_size,path,len); } else { @@ -2298,6 +2609,7 @@ smb_proc_rmdir (struct smb_server *server, const char *path, const int len, int int result; char *p; + // TODO: Tygre if(server->unicode_enabled) path_size = 2 * (len + 1); else @@ -2312,7 +2624,7 @@ smb_proc_rmdir (struct smb_server *server, const char *path, const int len, int if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - (void) copy_latin1_to_utf16le(p,path_size,path,len); + (void) copy_latin1_to_utf16le(server, p,path_size,path,len); } else { @@ -2337,6 +2649,7 @@ smb_proc_unlink (struct smb_server *server, const char *path, const int len, int char *buf = server->transmit_buffer; int result; + // TODO: Tygre if(server->unicode_enabled) path_size = 2 * (len + 1); else @@ -2356,7 +2669,7 @@ smb_proc_unlink (struct smb_server *server, const char *path, const int len, int if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - (void) copy_latin1_to_utf16le(p,path_size,path,len); + (void) copy_latin1_to_utf16le(server, p,path_size,path,len); } else { @@ -2517,9 +2830,22 @@ smb_proc_readdir_short ( mask_len = strlen (mask); if(server->unicode_enabled) - mask_size = 1 + 2 * (mask_len+1) + 3; + { + // Tygre 2015/05/29: Size in UTF16 + // The size is that of the bytes stored, + // plus the Latin1 path as prefix, not + // two bytes per char anymore in UTF16. + mask_size = size_utf16le_of_latin1(server, path); + if(-1 == mask_size) + { + // Default size + mask_size = 2 * (mask_len + 1); + } + } else - mask_size = 1 + mask_len+1 + 3; + { + mask_size = mask_len+1; + } SHOWMSG("SMB call readdir_short"); D((" mask = '%s'", escape_name(mask))); @@ -2555,16 +2881,16 @@ smb_proc_readdir_short ( { SHOWMSG("reading first directory entries"); - ASSERT( smb_payload_size(server, 2, mask_size) >= 0 ); + ASSERT( smb_payload_size(server, 2, 1 + mask_size + 3) >= 0 ); - p = smb_setup_header (server, SMBsearch, 2, mask_size); + p = smb_setup_header (server, SMBsearch, 2, 1 + mask_size + 3); WSET (buf, smb_vwv0, entries_asked); WSET (buf, smb_vwv1, SMB_FILE_ATTRIBUTE_DIRECTORY); if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - p += copy_latin1_to_utf16le(p,2 * (mask_len+1),mask,mask_len); + p += copy_latin1_to_utf16le(server, p, mask_size, mask, mask_len); } else { @@ -2582,6 +2908,7 @@ smb_proc_readdir_short ( SHOWMSG("reading next directory entries"); + // TODO: Tygre if(server->unicode_enabled) size = 1 + 2 * (1) + 3 + SMB_RESUME_KEY_SIZE; else @@ -2597,7 +2924,7 @@ smb_proc_readdir_short ( if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - p += copy_latin1_to_utf16le(p,2 * (1),"",0); + p += copy_latin1_to_utf16le(server, p,2 * (1),"",0); } else { @@ -2867,7 +3194,7 @@ smb_decode_long_dirent ( if(server->unicode_enabled) { - copy_utf16le_to_latin1(finfo->complete_path, finfo->complete_path_size, name, name_len); + copy_utf16le_to_latin1(server, finfo->complete_path, finfo->complete_path_size, name, name_len); } else { @@ -2993,7 +3320,7 @@ smb_decode_long_dirent ( if(server->unicode_enabled) { - copy_utf16le_to_latin1(finfo->complete_path, finfo->complete_path_size, p, name_len); + copy_utf16le_to_latin1(server, finfo->complete_path, finfo->complete_path_size, p, name_len); } else { @@ -3213,7 +3540,7 @@ smb_proc_readdir_long ( if(server->unicode_enabled) { - copy_latin1_to_utf16le(p,pattern_size,pattern,pattern_len); + copy_latin1_to_utf16le(server, p,pattern_size,pattern,pattern_len); } else { @@ -3456,20 +3783,33 @@ smb_proc_getattr_core (struct smb_server *server, const char *path, int len, str D(("path='%s'", escape_name(path))); if(server->unicode_enabled) - path_size = 1 + 2 * (len + 1); + { + // Tygre 2015/05/29: Size in UTF16 + // The size is that of the bytes stored, + // plus the Latin1 path as prefix, not + // two bytes per char anymore in UTF16. + path_size = size_utf16le_of_latin1(server, path); + if(-1 == path_size) + { + // Default size + path_size = 2 * (len + 1); + } + } else - path_size = 1 + len + 1; + { + path_size = len + 1; + } - ASSERT( smb_payload_size(server, 0, path_size) >= 0 ); + ASSERT( smb_payload_size(server, 0, 1 + path_size) >= 0 ); retry: - p = smb_setup_header (server, SMBgetatr, 0, path_size); + p = smb_setup_header (server, SMBgetatr, 0, 1 + path_size); if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - copy_latin1_to_utf16le(p,2 * (len+1),path,len); + copy_latin1_to_utf16le(server, p, path_size, path, len); } else { @@ -3480,9 +3820,13 @@ smb_proc_getattr_core (struct smb_server *server, const char *path, int len, str if (result < 0) { if ((*error_ptr) != error_check_smb_error && smb_retry (server)) + { goto retry; + } else + { goto out; + } } entry->attr = WVAL (buf, smb_vwv0); @@ -3600,7 +3944,7 @@ smb_query_path_information( if(server->unicode_enabled) { - copy_latin1_to_utf16le(p,path_size,path,len); + copy_latin1_to_utf16le(server, p,path_size,path,len); } else { @@ -3697,7 +4041,7 @@ smb_query_path_information( * text is provided as 16 bit characters, * even if Unicode mode is not enabled. */ - copy_utf16le_to_latin1(name, sizeof(name), file_name, file_name_length / sizeof(word)); + copy_utf16le_to_latin1(server, name, sizeof(name), file_name, file_name_length / sizeof(word)); entry_size_quad.Low = entry->size_low; entry_size_quad.High = entry->size_high; @@ -3913,11 +4257,24 @@ smb_proc_setattr_core (struct smb_server *server, const char *path, int len, con return(0); if(server->unicode_enabled) - path_size = 1 + 2 * (len + 1); + { + // Tygre 2015/05/29: Size in UTF16 + // The size is that of the bytes stored, + // plus the Latin1 path as prefix, not + // two bytes per char anymore in UTF16. + path_size = size_utf16le_of_latin1(server, path); + if(-1 == path_size) + { + // Default size + path_size = 2 * (len + 1); + } + } else - path_size = 1 + len + 1; + { + path_size = len + 1; + } - ASSERT( smb_payload_size(server, 8, path_size) >= 0 ); + ASSERT( smb_payload_size(server, 8, 1 + path_size) >= 0 ); /* We cache these because if the connection needs to be * reestablished, the direntry values will all get @@ -3956,7 +4313,7 @@ smb_proc_setattr_core (struct smb_server *server, const char *path, int len, con retry: - p = smb_setup_header (server, SMBsetatr, 8, path_size); + p = smb_setup_header (server, SMBsetatr, 8, 1 + path_size); WSET (buf, smb_vwv0, attr); DSET (buf, smb_vwv1, local_time); WSET (buf, smb_vwv3, 0); @@ -3968,7 +4325,7 @@ smb_proc_setattr_core (struct smb_server *server, const char *path, int len, con if(server->unicode_enabled) { (*p++) = 4; /* A NUL-terminated string follows. */ - p += copy_latin1_to_utf16le(p,2 * (len+1),path,len); + p += copy_latin1_to_utf16le(server, p, path_size, path, len); } else { @@ -4688,22 +5045,23 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr) const char * s; int l; - copy_latin1_to_utf16le(p,2 * (user_len + 1),server->mount_data.username,user_len); + // TODO: Tygre + copy_latin1_to_utf16le(server, p,2 * (user_len + 1),server->mount_data.username,user_len); p += 2 * (user_len + 1); s = server->mount_data.workgroup_name; l = strlen(s); - copy_latin1_to_utf16le(p,2 * (l + 1),s,l); + copy_latin1_to_utf16le(server, p,2 * (l + 1),s,l); p += 2 * (l + 1); s = native_os; l = strlen(s); - copy_latin1_to_utf16le(p,2 * (l + 1),s,l); + copy_latin1_to_utf16le(server, p,2 * (l + 1),s,l); p += 2 * (l + 1); s = native_lanman; l = strlen(s); - copy_latin1_to_utf16le(p,2 * (l + 1),s,l); + copy_latin1_to_utf16le(server, p,2 * (l + 1),s,l); } /* No, just use OEM strings. */ else @@ -4850,9 +5208,13 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr) (*p++) = 0; if(server->unicode_enabled) - copy_latin1_to_utf16le(p,share_name_size,share_name,share_name_len); + { + copy_latin1_to_utf16le(server, p,share_name_size,share_name,share_name_len); + } else + { memcpy(p,share_name,share_name_size); + } p += share_name_size; diff --git a/source_code/smakefile b/source_code/smakefile index ffa89fb..506e973 100644 --- a/source_code/smakefile +++ b/source_code/smakefile @@ -32,7 +32,6 @@ .c.o: sc $(CFLAGS) $< - @ctags >tagfiles/$* $< .asm.o: asm $(ASMFLAGS) $< @@ -97,9 +96,10 @@ LFLAGS = \ ############################################################################### +# Tygre: added KVS OBJS = \ main.o cp437.o cp850.o crypt.o dump_smb.o parse-smb-url.o proc.o \ - quad_math.o smb_abstraction.o sock.o splay.o swap_stack_and_call.o + quad_math.o smb_abstraction.o sock.o splay.o swap_stack_and_call.o kvs.o ############################################################################### @@ -112,9 +112,6 @@ $(PROJECT): $(OBJS) system_headers.gst Assert.o slink $(OBJS) to $@.debug lib $(LIBS) Assert.o $(LFLAGS) \ map $(PROJECT).map,fhx fwidth 32 pwidth 32 swidth 32 slink $@.debug to $@ noicons nodebug - @type tagfiles/\#? >t:tags - @copy t:tags "" - @delete >nil: t:tags system_headers.gst: system_headers.h system_headers.c gst unload $@ @@ -125,6 +122,7 @@ exall-example: exall-example.c ############################################################################### +# Tygre: added KVS assert.o : assert.c cp437.o : cp437.c cp850.o : cp850.c @@ -132,11 +130,12 @@ crypt.o : crypt.c system_headers.h assert.h quad_math.h splay.h smbfs.h dump_smb.o : dump_smb.c system_headers.h assert.h quad_math.h splay.h smbfs.h dump_smb.h main.o : main.c system_headers.h assert.h quad_math.h splay.h smbfs.h smb_abstraction.h cp437.h cp850.h errors.h dump_smb.h parse-smb-url.h smbfs_rev.h parse-smb-url.o : parse-smb-url.c system_headers.h assert.h quad_math.h splay.h smbfs.h parse-smb-url.h -proc.o : proc.c system_headers.h assert.h quad_math.h splay.h smbfs.h errors.h smbfs_rev.h +proc.o : proc.c system_headers.h assert.h quad_math.h splay.h smbfs.h errors.h smbfs_rev.h kvs.h quad_math.o : quad_math.c quad_math.h -smb_abstraction.o : smb_abstraction.c system_headers.h assert.h quad_math.h splay.h smbfs.h errors.h smb_abstraction.h +smb_abstraction.o : smb_abstraction.c system_headers.h assert.h quad_math.h splay.h smbfs.h errors.h smb_abstraction.h kvs.h sock.o : sock.c system_headers.h assert.h quad_math.h splay.h smbfs.h smb_abstraction.h dump_smb.h errors.h splay.o : splay.c system_headers.h assert.h quad_math.h splay.h smbfs.h +kvs.o : kvs.c ############################################################################### diff --git a/source_code/smb_abstraction.c b/source_code/smb_abstraction.c index 5ba3fcf..936ee3e 100644 --- a/source_code/smb_abstraction.c +++ b/source_code/smb_abstraction.c @@ -595,6 +595,10 @@ smba_connect ( init_open_file_list(res); + // Tygre 21/05/15: Create stores for UTF16le strings and their sizes + res->server.latin1_to_utf16le_bytes = kvs_create(strcmp); + res->server.latin1_to_utf16le_sizes = kvs_create(strcmp); + if (smb_proc_connect (&res->server, error_ptr) < 0) goto error_occured; @@ -632,6 +636,10 @@ smba_disconnect (smba_server_t * server) cleanup_server_dircache(server); + // Tygre 21/05/15: Delete stores for UTF16le strings and their sizes + kvs_destroy(server->server.latin1_to_utf16le_bytes); + kvs_destroy(server->server.latin1_to_utf16le_sizes); + free (server); }