+ /* get rid of '\', glob doesn't like it */
+ if ((tmp = strrchr(path, '\\')) != NULL) {
+ char *tail = path + strlen(path);
+ while (tmp != path) {
+ if (*tmp == '\\') {
+ memmove(tmp, tmp + 1, tail - tmp);
+ --tail;
+ }
+ --tmp;
+ }
+ }
+}
+
+/* Supporting file paths creates perilous behavoir: LU-888.
+ * Path support is deprecated.
+ * If a path is supplied it must begin with /proc. */
+static void lprocfs_param_pattern(const char *cmd, const char *path, char *buf,
+ size_t buf_size)
+{
+ /* test path to see if it begins with '/proc/' */
+ if (strncmp(path, "/proc/", strlen("/proc/")) == 0) {
+ static int warned;
+ if (!warned) {
+ fprintf(stderr, "%s: specifying parameters via "
+ "full paths is deprecated.\n", cmd);
+#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2,6,50,0)
+#warning "remove deprecated full path tunable access"
+#endif
+ warned = 1;
+ }
+ snprintf(buf, buf_size, "%s", path);
+ } else {
+ snprintf(buf, buf_size, "/proc/{fs,sys}/{lnet,lustre}/%s",
+ path);
+ }
+}
+
+struct param_opts {
+ int only_path:1;
+ int show_path:1;
+ int show_type:1;
+ int recursive:1;
+};
+
+static int listparam_cmdline(int argc, char **argv, struct param_opts *popt)
+{
+ int ch;
+
+ popt->show_path = 1;
+ popt->only_path = 1;
+ popt->show_type = 0;
+ popt->recursive = 0;
+
+ while ((ch = getopt(argc, argv, "FR")) != -1) {
+ switch (ch) {
+ case 'F':
+ popt->show_type = 1;
+ break;
+ case 'R':
+ popt->recursive = 1;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ return optind;
+}
+
+static int listparam_display(struct param_opts *popt, char *pattern)
+{
+ int rc;
+ int i;
+ glob_t glob_info;
+ char filename[PATH_MAX + 1]; /* extra 1 byte for file type */
+
+ rc = glob(pattern, GLOB_BRACE | (popt->recursive ? GLOB_MARK : 0),
+ NULL, &glob_info);
+ if (rc) {
+ fprintf(stderr, "error: list_param: %s: %s\n",
+ pattern, globerrstr(rc));
+ return -ESRCH;
+ }
+
+ for (i = 0; i < glob_info.gl_pathc; i++) {
+ char *valuename = NULL;
+ int last;
+
+ /* Trailing '/' will indicate recursion into directory */
+ last = strlen(glob_info.gl_pathv[i]) - 1;
+
+ /* Remove trailing '/' or it will be converted to '.' */
+ if (last > 0 && glob_info.gl_pathv[i][last] == '/')
+ glob_info.gl_pathv[i][last] = '\0';
+ else
+ last = 0;
+ strcpy(filename, glob_info.gl_pathv[i]);
+ valuename = display_name(filename, popt->show_type);
+ if (valuename)
+ printf("%s\n", valuename);
+ if (last) {
+ strcpy(filename, glob_info.gl_pathv[i]);
+ strcat(filename, "/*");
+ listparam_display(popt, filename);
+ }
+ }
+
+ globfree(&glob_info);
+ return rc;
+}
+
+int jt_lcfg_listparam(int argc, char **argv)
+{
+ int rc = 0, i;
+ struct param_opts popt;
+ char pattern[PATH_MAX];
+ char *path;
+
+ rc = listparam_cmdline(argc, argv, &popt);
+ if (rc == argc && popt.recursive) {
+ rc--; /* we know at least "-R" is a parameter */
+ argv[rc] = "*";
+ } else if (rc < 0 || rc >= argc) {
+ return CMD_HELP;
+ }
+
+ for (i = rc; i < argc; i++) {
+ path = argv[i];
+
+ clean_path(path);