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);