void cfs_expr_list_free_list(struct list_head *list);
int cfs_ip_addr_parse(char *str, int len, struct list_head *list);
int cfs_ip_addr_match(__u32 addr, struct list_head *list);
+int cfs_abs_path(const char *request_path, char **resolved_path);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
+#include <unistd.h>
#include <libcfs/util/string.h>
/*
cfs_expr_list_free(el);
}
}
+
+/**
+ * cfs_abs_path() - Get the absolute path of a relative path
+ * @request_path: The relative path to be resolved
+ * @resolved_path: Set to the resolved absolute path
+ *
+ * Returns the canonicalized absolute pathname. This function is a wrapper to
+ * realpath, but will work even if the target file does not exist. All
+ * directories in the path must exist.
+ *
+ * Return: On success, 0 is returned and resolved_path points to an allocated
+ * string containing the absolute pathname. On error, errno is set
+ * appropriately, -errno is returned, and resolved_path points to NULL.
+ */
+int cfs_abs_path(const char *request_path, char **resolved_path)
+{
+ char buf[PATH_MAX + 1] = "";
+ char *path;
+ char *ptr;
+ int len;
+ int rc = 0;
+ const char *fmt;
+
+ path = malloc(sizeof(buf));
+ if (path == NULL)
+ return -ENOMEM;
+
+ if (request_path[0] != '/') {
+ if (getcwd(path, sizeof(buf) - 1) == NULL) {
+ rc = -errno;
+ goto out;
+ }
+ len = snprintf(buf, sizeof(buf), "%s/%s", path, request_path);
+ if (len >= sizeof(buf)) {
+ rc = -ENAMETOOLONG;
+ goto out;
+ }
+ } else {
+ /* skip duplicate leading '/' */
+ len = snprintf(buf, sizeof(buf), "%s",
+ request_path + strspn(request_path, "/") - 1);
+ if (len >= sizeof(buf)) {
+ rc = -ENAMETOOLONG;
+ goto out;
+ }
+ }
+
+ /* if filename not in root directory, call realpath for parent path */
+ ptr = strrchr(buf, '/');
+ if (ptr != buf) {
+ *ptr = '\0';
+ if (path != realpath(buf, path)) {
+ rc = -errno;
+ goto out;
+ }
+ /* add the filename back */
+ len = strlen(path);
+ fmt = (path[len - 1] == '/') ? "%s" : "/%s";
+ len = snprintf(path + len, sizeof(buf) - len, fmt, ptr + 1);
+ if (len >= sizeof(buf) - len) {
+ rc = -ENAMETOOLONG;
+ goto out;
+ }
+ } else {
+ len = snprintf(path, sizeof(buf), "%s", buf);
+ if (len >= sizeof(buf)) {
+ rc = -ENAMETOOLONG;
+ goto out;
+ }
+ }
+
+out:
+ if (rc == 0) {
+ *resolved_path = path;
+ } else {
+ *resolved_path = NULL;
+ free(path);
+ }
+ return rc;
+}
#include <libcfs/util/param.h>
#include <linux/lnet/libcfs_debug.h>
#include <linux/lnet/lnetctl.h>
+#include <libcfs/util/string.h>
static char rawbuf[8192];
static char *buf = rawbuf;
{
int rc;
int fd;
+ char *resolved_path = NULL;
if (argc <= 1) {
fprintf(stderr, debug_daemon_usage, argv[0]);
}
}
- rc = dbg_write_cmd(fd, argv[2], strlen(argv[2]));
+ rc = cfs_abs_path(argv[2], &resolved_path);
+ if (rc != 0) {
+ fprintf(stderr,
+ "%s debug_daemon: cannot resolve path '%s': %s\n",
+ program_invocation_short_name, argv[2],
+ strerror(-rc));
+ goto out;
+ }
+ rc = dbg_write_cmd(fd, resolved_path, strlen(resolved_path));
if (rc != 0) {
fprintf(stderr, "start debug_daemon on %s failed: %s\n",
argv[2], strerror(errno));
rc = -1;
out:
dbg_close_ctlhandle(fd);
+ if (resolved_path != NULL)
+ free(resolved_path);
return rc;
}
#include <linux/version.h>
#include <linux/lnet/lnetctl.h>
#include <linux/lustre/lustre_ver.h>
+#include <libcfs/util/string.h>
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
}
#endif
-/* return canonicalized absolute pathname, even if the target file does not
- * exist, unlike realpath */
-static char *absolute_path(char *devname)
-{
- char buf[PATH_MAX + 1] = "";
- char *path;
- char *ptr;
- int len;
-
- path = malloc(sizeof(buf));
- if (path == NULL)
- return NULL;
-
- if (devname[0] != '/') {
- if (getcwd(buf, sizeof(buf) - 1) == NULL) {
- free(path);
- return NULL;
- }
- len = snprintf(path, sizeof(buf), "%s/%s", buf, devname);
- if (len >= sizeof(buf)) {
- free(path);
- return NULL;
- }
- } else {
- len = snprintf(path, sizeof(buf), "%s", devname);
- if (len >= sizeof(buf)) {
- free(path);
- return NULL;
- }
- }
-
- /* truncate filename before calling realpath */
- ptr = strrchr(path, '/');
- if (ptr == NULL) {
- free(path);
- return NULL;
- }
- *ptr = '\0';
- if (buf != realpath(path, buf)) {
- free(path);
- return NULL;
- }
- /* add the filename back */
- len = snprintf(path, PATH_MAX, "%s/%s", buf, ptr+1);
- if (len >= PATH_MAX) {
- free(path);
- return NULL;
- }
- return path;
-}
-
/* Determine if a device is a block device (as opposed to a file) */
static int is_block(char *devname)
{
int ret = 0;
char *devpath;
- devpath = absolute_path(devname);
- if (devpath == NULL) {
- fprintf(stderr, "%s: failed to resolve path to %s\n",
- progname, devname);
+ ret = cfs_abs_path(devname, &devpath);
+ if (ret != 0) {
+ fprintf(stderr, "%s: failed to resolve path '%s': %s\n",
+ progname, devname, strerror(-ret));
return -1;
}