From 3c1df9b1db5fd8222d4cfc587fd0e4f9d3a3d28d Mon Sep 17 00:00:00 2001 From: Olaf Barthel Date: Wed, 10 Nov 2004 17:45:40 +0000 Subject: [PATCH] - mktemp() was broken in libunix.a with Unix path semantics enabled. This was because the name template was translated and translated back again, overwriting the translation buffer. This, funny enough, broke Samba's printing feature. Fixed by translating the name only before each test for "uniqueness" is made. The new code also handles empty "" templates gracefully, which was a problem with both the "standard" and the Unix path semantics flavour. Why is it that I find bugs like this always after having just released another library update? git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@14768 87f5fb63-7c3d-0410-a384-fd976d0f7a62 --- library/changes | 12 ++++ library/stdlib_mktemp.c | 144 +++++++++++++++++++++++----------------- 2 files changed, 94 insertions(+), 62 deletions(-) diff --git a/library/changes b/library/changes index 7f588de..569dce7 100644 --- a/library/changes +++ b/library/changes @@ -1,3 +1,15 @@ +- mktemp() was broken in libunix.a with Unix path semantics enabled. + This was because the name template was translated and translated + back again, overwriting the translation buffer. This, funny enough, + broke Samba's printing feature. Fixed by translating the name only + before each test for "uniqueness" is made. The new code also handles + empty "" templates gracefully, which was a problem with both the + "standard" and the Unix path semantics flavour. + + Why is it that I find bugs like this always after having just + released another library update? + + c.lib 1.182 (8.11.2004) - Changed the error abort condition for the %s conversion of the diff --git a/library/stdlib_mktemp.c b/library/stdlib_mktemp.c index 03a75f1..721af37 100644 --- a/library/stdlib_mktemp.c +++ b/library/stdlib_mktemp.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_mktemp.c,v 1.2 2004-08-07 09:15:32 obarthel Exp $ + * $Id: stdlib_mktemp.c,v 1.3 2004-11-10 17:45:40 obarthel Exp $ * * :ts=4 * @@ -57,16 +57,19 @@ mktemp(char * name_template) { #if defined(UNIX_PATH_SEMANTICS) struct name_translation_info name_template_nti; - char * original_name_template = NULL; #endif /* UNIX_PATH_SEMANTICS */ + char * test_name; struct Process * this_process; APTR old_window_pointer; char * result = NULL; - int template_offset; - int template_len; + size_t template_offset; + size_t template_len; + size_t name_len; + size_t offset; time_t now; + ULONG pseudo_random_number; BPTR lock; - int i; + size_t i; ENTER(); @@ -74,6 +77,8 @@ mktemp(char * name_template) assert(name_template != NULL); + this_process = (struct Process *)FindTask(NULL); + #if defined(CHECK_FOR_NULL_POINTERS) { if(name_template == NULL) @@ -89,43 +94,11 @@ mktemp(char * name_template) if(__check_abort_enabled) __check_abort(); - #if defined(UNIX_PATH_SEMANTICS) - { - if(__unix_path_semantics) - { - original_name_template = name_template; - - if(__translate_unix_to_amiga_path_name((char const **)&name_template,&name_template_nti) != 0) - goto out; - - if(name_template_nti.is_root) - { - errno = EACCES; - goto out; - } - } - } - #endif /* UNIX_PATH_SEMANTICS */ - SHOWSTRING(name_template); - template_offset = -1; - template_len = 0; - - for(i = strlen(name_template)-1 ; i >= 0 ; i--) - { - if(name_template[i] == 'X') - { - template_offset = i; - template_len++; - } - else - { - break; - } - } - - if(template_offset == -1) + /* So, how long is that name template? */ + name_len = strlen(name_template); + if(name_len == 0) { SHOWMSG("invalid name template"); @@ -133,23 +106,65 @@ mktemp(char * name_template) goto out; } - this_process = (struct Process *)FindTask(NULL); + /* Find out how many trailing 'X' characters there are in + the template. There should be at least 6. We also want + to know where to find the first 'X' and how many of the + 'X' characters there are. */ + template_offset = 0; + template_len = 0; + for(i = 0 ; i < name_len ; i++) + { + assert( name_len >= (i + 1) ); + + offset = name_len - (i + 1); + + if(name_template[offset] != 'X') + break; + + template_offset = offset; + template_len++; + } + + SHOWVALUE(template_offset); + SHOWVALUE(template_len); + + if(template_len == 0) + { + SHOWMSG("invalid name template"); + + errno = EINVAL; + goto out; + } + + /* Generate a pseudo-random number from the current time and + the address of the current process. */ time(&now); - now += (time_t)this_process; + pseudo_random_number = (ULONG)now + (ULONG)this_process; + /* Fill the template 'X' characters with letters made up by + converting the pseudo-random number. */ for(i = 0 ; i < template_len ; i++) { - name_template[template_offset + i] = 'A' + (now % 26); + name_template[template_offset + i] = 'A' + (pseudo_random_number % 26); - now = (now / 26); - if(now == 0) + /* One more letter taken; if we run out of letters, + cook up another pseudo-random number. */ + pseudo_random_number = (pseudo_random_number / 26); + if(pseudo_random_number == 0) + { time(&now); + + pseudo_random_number = (ULONG)now; + } } + SHOWSTRING(name_template); + old_window_pointer = this_process->pr_WindowPtr; + /* Now check if the name we picked is unique. If not, make another name. */ while(TRUE) { if(__check_abort_enabled) @@ -157,12 +172,32 @@ mktemp(char * name_template) D(("checking '%s'",name_template)); + test_name = name_template; + + /* If necessary, quickly translate the semantics of the file name + we cooked up above. */ + #if defined(UNIX_PATH_SEMANTICS) + { + if(__unix_path_semantics) + { + if(__translate_unix_to_amiga_path_name((char const **)&test_name,&name_template_nti) != 0) + goto out; + + if(name_template_nti.is_root) + { + errno = EACCES; + goto out; + } + } + } + #endif /* UNIX_PATH_SEMANTICS */ + /* Turn off DOS error requesters. */ this_process->pr_WindowPtr = (APTR)-1; /* Does this object exist already? */ PROFILE_OFF(); - lock = Lock(name_template,SHARED_LOCK); + lock = Lock(test_name,SHARED_LOCK); PROFILE_ON(); /* Restore DOS requesters. */ @@ -191,8 +226,7 @@ mktemp(char * name_template) PROFILE_ON(); /* Change one letter; if that 'overflows', start - * over with 'A' and move on to the next position. - */ + over with 'A' and move on to the next position. */ for(i = 0 ; i < template_len ; i++) { name_template[template_offset + i]++; @@ -205,20 +239,6 @@ mktemp(char * name_template) SHOWSTRING(name_template); - #if defined(UNIX_PATH_SEMANTICS) - { - if(__unix_path_semantics) - { - if(__translate_amiga_to_unix_path_name((char const **)&name_template,&name_template_nti) != 0) - goto out; - - strcpy(original_name_template,name_template); - } - } - #endif /* UNIX_PATH_SEMANTICS */ - - SHOWSTRING(name_template); - out: RETURN(result);