#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
extern char *realpath3(const char *pathname, char *resolved);
struct rp_compare {
char * resolv2;
char * resolv3;
char * r2;
char * r3;
int e2;
int e3;
};
static struct rp_compare
rpcompare(const char *pathname, char *resolv2,
char *resolv3) {
struct rp_compare ret = {0};
errno = 0;
ret.r2 = realpath(pathname, resolv2);
ret.e2 = errno;
ret.resolv2 = resolv2;
errno = 0;
ret.r3 = realpath3(pathname, resolv3);
ret.e3 = errno;
ret.resolv3 = resolv3;
errno = 0;
return ret;
}
#define RP_SHOULD_SUCCEED(A, B, C) do { \
struct rp_compare rc = rpcompare(A, B, C); \
if (rc.r2 == NULL) { \
errno = rc.e2; \
err(1, "%s:%d - realpath of '%s' failed", __FILE__, \
__LINE__, (A)); \
} \
if (rc.r3 == NULL) { \
errno = rc.e3; \
err(1, "%s:%d - realpath3 of '%s' failed", __FILE__, \
__LINE__, (A)); \
} \
if (strcmp(rc.r2, rc.r3) != 0) \
errx(1, "%s:%d - realpath of '%s' result '%s', " \
"expected '%s", __FILE__, __LINE__, (A), rc.r2, \
rc.r3); \
} while(0);
#define RP_SHOULD_FAIL(A, B, C) do { \
struct rp_compare rc = rpcompare(A, B, C); \
if (rc.r2 != NULL) \
errx(1, "%s:%d - realpath of '%s' should have failed, " \
"returned '%s'", __FILE__, __LINE__, (A), rc.r2); \
if (rc.r3 != NULL) \
errx(1, "%s:%d - realpath3 of '%s' should have failed, "\
"returned '%s'", __FILE__, __LINE__, (A), rc.r3); \
if (rc.e2 != rc.e3) \
errx(1, "%s:%d - realpath of '%s' errno %d does not " \
"match realpath3 errno %d", __FILE__, __LINE__, (A),\
rc.e2, rc.e3 ); \
} while(0);
int
main(int argc, char *argv[])
{
int i, j;
char big[PATH_MAX+PATH_MAX];
char r2[PATH_MAX];
char r3[PATH_MAX];
RP_SHOULD_FAIL(NULL, NULL, NULL);
RP_SHOULD_FAIL("", NULL, NULL);
RP_SHOULD_SUCCEED("/", NULL, NULL);
RP_SHOULD_SUCCEED("//", NULL, NULL);
RP_SHOULD_SUCCEED("/./", NULL, NULL);
RP_SHOULD_SUCCEED("/./.", NULL, NULL);
RP_SHOULD_SUCCEED("/./..", NULL, NULL);
RP_SHOULD_SUCCEED("/../../", NULL, NULL);
RP_SHOULD_SUCCEED("/tmp", NULL, NULL);
RP_SHOULD_FAIL("/tmp/noreallydoesntexist", NULL, NULL);
RP_SHOULD_FAIL("/tmp/noreallydoesntexist/stillnope", NULL, NULL);
RP_SHOULD_SUCCEED("/bin", NULL, NULL);
RP_SHOULD_FAIL("/bin/herp", NULL, NULL);
RP_SHOULD_SUCCEED("////usr/bin", NULL, NULL);
RP_SHOULD_FAIL("//.//usr/bin/.././../herp", r2, r3);
RP_SHOULD_SUCCEED("/usr/include/machine/setjmp.h", r2, r3);
RP_SHOULD_FAIL("//.//usr/bin/.././../herp/derp", r2, r3);
RP_SHOULD_FAIL("/../.../usr/bin", r2, r3);
RP_SHOULD_FAIL("/bsd/herp", r2, r3);
if (mkdir("hoobla", 0755) == -1) {
if (errno != EEXIST)
err(1, "mkdir");
}
RP_SHOULD_SUCCEED("hoobla", r2, r3);
RP_SHOULD_FAIL("hoobla/porkrind", r2, r3);
RP_SHOULD_FAIL("hoobla/porkrind/peepee", r2, r3);
memset(big, '/', PATH_MAX + 1);
RP_SHOULD_FAIL(big, r2, r3);
memset(big, 'a', PATH_MAX + 1);
big[0] = '/';
big[NAME_MAX+1] = '\0';
RP_SHOULD_FAIL(big, r2, r3);
memset(big, 'a', PATH_MAX + 1);
big[0] = '/';
big[NAME_MAX+2] = '\0';
RP_SHOULD_FAIL(big, r2, r3);
for (i = 0; i < (PATH_MAX - 4); i += 3) {
big[i] = '.';
big[i+1] = '.';
big[i+2] = '/';
}
i-= 3;
strlcpy(big+i, "bsd", 4);
RP_SHOULD_SUCCEED(big, r2, r3);
for (i = 0; i < (PATH_MAX - 5); i += 3) {
big[i] = '.';
big[i+1] = '.';
big[i+2] = '/';
}
i-= 3;
strlcpy(big+i, "bsd/", 5);
RP_SHOULD_FAIL(big, r2, r3);
for (i = 0; i < (PATH_MAX - 5); i += 3) {
big[i] = '.';
big[i+1] = '.';
big[i+2] = '/';
}
i-= 3;
strlcpy(big+i, "derp", 5);
RP_SHOULD_FAIL(big, r2, r3);
for (i = 0; i < (PATH_MAX - 6); i += 3) {
big[i] = '.';
big[i+1] = '.';
big[i+2] = '/';
}
i-= 3;
strlcpy(big+i, "derp/", 6);
RP_SHOULD_FAIL(big, r2, r3);
for (i = 0; i < (PATH_MAX - 4); i += 3) {
big[i] = '.';
big[i+1] = '.';
big[i+2] = '/';
}
i-= 3;
strlcpy(big+i, "xxx", 4);
RP_SHOULD_FAIL(big, r2, r3);
for (i = 0; i < (PATH_MAX - 8); i += 3) {
big[i] = '.';
big[i+1] = '.';
big[i+2] = '/';
}
i-= 3;
strlcpy(big+i, "xxx/../", 8);
RP_SHOULD_FAIL(big, r2, r3);
return (0);
}