1 /*
2  * Copyright (c) 2007 Bret S. Lambert <blambert@gsipt.net>
3  *
4  * Public domain.
5  */
6 
7 #include <libgen.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <limits.h>
11 #include <errno.h>
12 #include <err.h>
13 
14 int
15 main(void)
16 {
17 	char path[2 * PATH_MAX];
18 	char dname[128];
19 	const char *dir = "junk";
20 	const char *fname = "/file.name.ext";
21 	char *str;
22 	int i;
23 
24 	/* Test normal functioning */
25 	strlcpy(path, "/", sizeof(path));
26 	strlcpy(dname, "/", sizeof(dname));
27 	strlcat(path, dir, sizeof(path));
28 	strlcat(dname, dir, sizeof(dname));
29 	strlcat(path, fname, sizeof(path));
30 	str = dirname(path);
31 	if (strcmp(str, dname) != 0)
32 		errx(1, "0: dirname(%s) = %s != %s", path, str, dname);
33 
34 	/*
35 	 * There are four states that require special handling:
36 	 *
37 	 * 1) path is NULL
38 	 * 2) path is the empty string
39 	 * 3) path is composed entirely of slashes
40 	 * 4) the resulting name is larger than PATH_MAX
41 	 *
42 	 * The first two cases require that a pointer
43 	 * to the string "." be returned.
44 	 *
45 	 * The third case requires that a pointer
46 	 * to the string "/" be returned.
47 	 *
48 	 * The final case requires that NULL be returned
49 	 * and errno * be set to ENAMETOOLONG.
50 	 */
51 	/* Case 1 */
52 	str = dirname(NULL);
53 	if (strcmp(str, ".") != 0)
54 		errx(1, "1: dirname(NULL) = %s != .", str);
55 
56 	/* Case 2 */
57 	strlcpy(path, "", sizeof(path));
58 	str = dirname(path);
59 	if (strcmp(str, ".") != 0)
60 		errx(1, "2: dirname(%s) = %s != .", path, str);
61 
62 	/* Case 3 */
63 	for (i = 0; i < PATH_MAX - 1; i++)
64 		strlcat(path, "/", sizeof(path));	/* path cleared above */
65 	str = dirname(path);
66 	if (strcmp(str, "/") != 0)
67 		errx(1, "3: dirname(%s) = %s != /", path, str);
68 
69 	/* Case 4 */
70 	strlcpy(path, "/", sizeof(path));		/* reset path */
71 	for (i = 0; i <= PATH_MAX; i += strlen(dir))
72 		strlcat(path, dir, sizeof(path));
73 	strlcat(path, fname, sizeof(path));
74 	str = dirname(path);
75 	if (str != NULL)
76 		errx(1, "4: dirname(%s) = %s != NULL", path, str);
77 	if (errno != ENAMETOOLONG)
78 		errx(1, "4: dirname(%s) sets errno to %d", path, errno);
79 
80 	return (0);
81 }
82