On Tue, Mar 11, 2003 at 10:47:10AM +0100, Paul Slootman wrote:
> On Tue 11 Mar 2003, jw schultz wrote:
> > 
> > That or char fscratch[MAXPATHLEN];
> > Just don't use malloc.
> 
> How about this:
> 
> 
> static int get_tmpname(char *fnametmp, char *fname)
> {
>       char    *f;
>       char    *dir = "";      /* what dir to put the temp file in */
>       char    namepart[NAME_MAX-10];  /* we never need more than this, if   */
>                                       /* the name is longer, we would end   */
>                                       /* up having to shorten it anyway     */
>       if (tmpdir)
>               dir = tmpdir;
> 
>       f = strrchr(fname,'/'); /* is there a directory to skip in fname? */
>       if (f == NULL) {                /* no */
>               /* the strlcpy takes care of making the name short enough */
>               /* and null-terminating it at the same time. */
>               strlcpy(namepart, fname, sizeof(namepart));
>       }
>       else {                          /* yes */
>               strlcpy(namepart, f+1, sizeof(namepart));

If we aren't using tmpdir we need to strlcpy(dir, fname, f - fname)
at which point we've just copied all of fname anyway.

>       }
> 
>       if (strlen(dir)+strlen(namepart)+1 > MAXPATHLEN) {
>               /* how often will this happen... the temp dir would have to */
>               /* a very long name, and hence the fault of the user who    */
>               /* specified it. Let him fix the problem.                   */
>               rprintf(FERROR,"filename too long\n");
>               return 0;
>       }
> 
>       /* construct temp name template */
>       snprintf(fnametmp, MAXPATHLEN, "%s%s.%s.XXXXXX",
>                                         dir, dir[0]?"/":"", namepart);

Please use whitespace in the ?: 

> 
>       return 1;
> }
> 
> 
> Even shorter than it was, it should now be difficult to mess this up :-)
> I thought of letting the default value of dir be "./", but then
> clean_fname would end up shifting that off again, thus wasting
> resources.

I'd say it was better to copy fname and mangle the copy.
The alternative is to make the dir array MAXPATHLEN long.

Should also add to rsync.h
#ifndef NAME_MAX
#define NAME_MAX 255
#endif
Just in case.

Hmm.  I'm thinking we should just build fnametmp a piece at
a time.  I coded it up to see how it would look.  Not as
intuitive but there is a lot less strlen and no snprintf.
It also deals shortens the filename both for MAXPATHLEN and
for NAME_MAX so it is almost impossible for the function to
fail or produce a pathname that breaks things.

The only more surefire way to not make a bad tempfile name
would be to always make maxname = max(strlen(f) < 10, 0)

static int get_tmpname(char *fnametmp, char *fname)
{
        char    *f;
        int     length = 0;
        int     maxname;


        if (tmpdir)
        {
                strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
                length = strlen(fnametmp);
        }

        if (f = strrchr(fname, '/')) {
                if (!tmpdir) {
                        length = f - fname;
                        strlcpy(fnametmp, fname, length);
                }
                ++f;
        } else {
                f = fname;
        }
        strcpy(fnametmp + length, "/.");
        length += 2;

        maxname = MIN(MAXPATHLEN - 8 - length, NAME_MAX - 9);
                
        if (maxname < 1)
        {
                rprintf(FERROR, "temporary filename too long: %s\n", fname);
                return 0;
        }

        strlcpy(fnametmp + length, f, maxname); 
        strcat(fnametmp + length, ".XXXXXX");

        return 1;
}



-- 
________________________________________________________________
        J.W. Schultz            Pegasystems Technologies
        email address:          [EMAIL PROTECTED]

                Remember Cernan and Schmitt
-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.tuxedo.org/~esr/faqs/smart-questions.html

Reply via email to