Subject: issue with pax creating a directory
To: None <tech-pkg@netbsd.org>
From: Georg Schwarz <georg.schwarz@freenet.de>
List: tech-pkg
Date: 12/06/2005 00:26:26
I just came across an issue with the current version of pax that occurs
on IRIX 5.3:

lorenz 105% /var/tmp/pkg/bin/pax -rw . /var/tmp/pkg/share/x11-links
pax: Cannot create directory `/var' (Permission denied)

With older versions of pax the problem does not occur.

Looking through the code I fine:

int
mkpath(path)
        char *path;
{
        char *slash;
        int done = 0;

        slash = path;

        while (!done) {
                slash += strspn(slash, "/");
                slash += strcspn(slash, "/");

                done = (*slash == '\0');
                *slash = '\0';

                if (domkdir(path, 0777) == -1)
                        goto out;

                if (!done)
                        *slash = '/';
        }
        return 0;
out:
        /* Can't create or or not a directory */
        syswarn(1, errno, "Cannot create directory `%s'", path);
        return -1;
}


domkdir() is:

int
domkdir(const char *fname, mode_t mode)
{
        int error;
        struct stat sb;

        if ((error = mkdir(fname, mode)) != -1)
                return error;

        switch (errno) {
        case EISDIR:
                return 0;
        case EEXIST:
                error = errno;
                if (stat(fname, &sb) != -1 && S_ISDIR(sb.st_mode))
                        return 0;
                errno = error;
                /*FALLTHROUGH*/
        default:
                return -1;
        }
}



I wrote a small test program:

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>

void main(void)
{
int error;
error=mkdir("/var",0777);
printf("%d,%d\n",error,errno);
}

which on IRIX 5.3 yields:

lorenz 44% a.out
-1,13


on Linux I get -1,17 as I do on Darwin.

/usr/include/sys/errno.h says:

#define EACCES  13      /* Permission denied                    */


#define EEXIST  17      /* File exists                          */


so it seems IRIX 5.3 first checks whether it does have permissions to
create /var (which it does not since it does not have write permissions
to /) and exists with EACCES before checking whether /var already
exists.


what do you think of just changing the above code to

....
       case EISDIR:
                return 0;
        case EEXIST:
        case EACCES:
               error = errno;
.... 



-- 
Georg Schwarz    http://home.pages.de/~schwarz/
 georg.schwarz@freenet.de  +49 178 8545053