Whamcloud - gitweb
LU-5030 libcfs: create cfs_get_paths() function
[fs/lustre-release.git] / libcfs / libcfs / util / param.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the GNU Lesser General Public License
8  * (LGPL) version 2.1 or (at your discretion) any later version.
9  * (LGPL) version 2.1 accompanies this distribution, and is available at
10  * http://www.gnu.org/licenses/lgpl-2.1.html
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * LGPL HEADER END
18  */
19 /*
20  * libcfs/libcfs/utils/param.c
21  *
22  * This code handles user interaction with the configuration interface
23  * to the Lustre file system to fine tune it.
24  */
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <glob.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <linux/limits.h>
34 #include <libcfs/util/string.h>
35
36 /**
37  * Get parameter path matching the pattern
38  *
39  * \param[out] paths    glob_t structure used to hold the final result
40  * \param[in]  pattern  the pattern containing sprintf format specifiers
41  *                      which will be used to create the path to match
42  *
43  * The \param pattern is appended to the default path glob to complete the
44  * absolute path to the file the caller is requesting. If the results point
45  * to one or more files that exist those results are stored in the \param
46  * paths glob_t structure that is passed by the caller.
47  *
48  * Lustre tunables traditionally were in /proc/{sys,fs}/{lnet,lustre}
49  * but in upstream kernels starting with Linux 4.2 these parameters
50  * have been moved to /sys/fs/lustre and /sys/kernel/debug/{lnet,lustre}
51  * so the user tools need to check both locations.
52  *
53  * \retval       0 for success, with results stored in \param paths.
54  * \retval      -1 for failure with errno set to report the reason.
55  */
56 int
57 cfs_get_param_paths(glob_t *paths, const char *pattern, ...)
58 {
59         char path[PATH_MAX] = "{/sys/{fs,kernel/debug}/{lnet,lustre}/,"
60                                "/proc/{fs,sys}/{lnet,lustre}/}";
61         size_t len = strlen(path);
62         char buf[PATH_MAX];
63         va_list args;
64         int rc;
65
66         va_start(args, pattern);
67         rc = vsnprintf(buf, sizeof(buf), pattern, args);
68         va_end(args);
69         if (rc < 0) {
70                 return rc;
71         } else if (rc >= sizeof(buf)) {
72                 errno = EINVAL;
73                 return -1;
74         }
75         len += rc;
76
77         if (strlcat(path, buf, sizeof(path)) != len) {
78                 errno = E2BIG;
79                 return -1;
80         }
81
82         rc = glob(path, GLOB_BRACE, NULL, paths);
83         if (rc != 0) {
84                 switch (rc) {
85                 case GLOB_NOSPACE:
86                         errno = ENOMEM;
87                         break;
88                 case GLOB_ABORTED:
89                         errno = ENODEV;
90                         break;
91                 case GLOB_NOMATCH:
92                 default:
93                         errno = ENOENT;
94                         break;
95                 }
96                 rc = -1;
97         }
98
99         return rc;
100 }