AC_HEADER_REQUIRE(fcntl.h)
AC_HEADER_REQUIRE(getopt.h)
AC_HEADER_REQUIRE(libgen.h)
-AC_HEADER_REQUIRE(limits.h)
AC_HEADER_REQUIRE(linux/xattr.h)
AC_HEADER_REQUIRE(sys/acl.h)
AC_HEADER_REQUIRE(unistd.h)
[[#define _GNU_SOURCE
#include <fcntl.h>]])
+# And check for the GNU/BSD extension asprintf(), which lets us avoid
+# praying to the PATH_MAX gods while constructing long paths.
+AC_CHECK_FUNC(asprintf,
+ [],
+ AC_MSG_ERROR(missing required asprintf function))
+
LT_INIT
AC_OUTPUT
*
*/
-/* Enables get_current_dir_name() in unistd.h and the O_PATH flag. */
+/* Enables get_current_dir_name() in unistd.h, the O_PATH flag, and
+ * the asprintf() function.
+*/
#define _GNU_SOURCE
#include <dirent.h> /* readdir(), etc. */
#include <errno.h> /* EINVAL, ELOOP, ENOTDIR, etc. */
#include <fcntl.h> /* openat() */
#include <libgen.h> /* basename(), dirname() */
-#include <limits.h> /* PATH_MAX */
#include <stdbool.h> /* the "bool" type */
-#include <stdio.h> /* perror(), snprintf() */
+#include <stdio.h> /* perror(), asprintf() */
#include <stdlib.h> /* free() */
#include <string.h> /* strdup() */
#include <sys/stat.h> /* fstat() */
*/
#define CLOSE_ERROR -1
#define OPEN_ERROR -1
-#define SNPRINTF_ERROR -1
+#define ASPRINTF_ERROR -1
#define STAT_ERROR -1
#define XATTR_ERROR -1
return OPEN_ERROR;
}
- char abspath[PATH_MAX];
- int snprintf_result = 0;
+ char* abspath = NULL;
+ int asprintf_result = 0;
if (strchr(pathname, '/') == pathname) {
/* pathname is already absolute; just copy it. */
- snprintf_result = snprintf(abspath, PATH_MAX, "%s", pathname);
+ asprintf_result = asprintf(&abspath, "%s", pathname);
}
else {
/* Concatenate the current working directory and pathname into an
free(cwd);
return OPEN_ERROR;
}
- snprintf_result = snprintf(abspath, PATH_MAX, "%s/%s", abs_cwd, pathname);
+ asprintf_result = asprintf(&abspath, "%s/%s", abs_cwd, pathname);
free(cwd);
}
- if (snprintf_result == SNPRINTF_ERROR || snprintf_result > PATH_MAX) {
- perror("safe_open (snprintf)");
+ if (asprintf_result == ASPRINTF_ERROR) {
+ perror("safe_open (asprintf)");
return OPEN_ERROR;
}
+ /* Beyond here, asprintf() worked, and we need to free abspath. */
+ int result = OPEN_ERROR;
+
bool abspath_is_root = (strcmp(abspath, "/") == 0);
int rootflags = flags | O_DIRECTORY;
if (!abspath_is_root) {
int rootfd = open("/", rootflags);
if (rootfd == OPEN_ERROR) {
perror("safe_open (open)");
- return OPEN_ERROR;
+ result = OPEN_ERROR;
+ goto cleanup;
}
if (abspath_is_root) {
- return rootfd;
+ result = rootfd;
+ goto cleanup;
}
- int result = safe_open_ex(rootfd, abspath+1, flags);
+ result = safe_open_ex(rootfd, abspath+1, flags);
if (close(rootfd) == CLOSE_ERROR) {
perror("safe_open (close)");
- return OPEN_ERROR;
+ result = OPEN_ERROR;
+ goto cleanup;
}
+
+ cleanup:
+ free(abspath);
return result;
}