mirror of
https://github.com/adtools/clib2.git
synced 2025-12-08 14:59:05 +00:00
- 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
This commit is contained in:
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user