Skip to content

Commit 58087e8

Browse files
committed
libnilfs: fix nilfs_open failure for mount points with escaped characters
nilfs_find_fs(), called from nilfs_open(), parses "/proc/mounts" using its own routines, but these parsing routines have a problem in that they cannot handle escaped path strings. For example, if the mount point path name contains spaces, the search will fail. This is causing errors when running lscp, lssu, and other nilfs tools. Fix this issue by avoiding custom parsing and using standard mount table access routines such as setmntent(), getmntent_r(), endmntent(), and hasmntopt(). Closes: #22 Signed-off-by: Ryusuke Konishi <[email protected]>
1 parent 44d91f9 commit 58087e8

File tree

1 file changed

+14
-72
lines changed

1 file changed

+14
-72
lines changed

lib/nilfs.c

Lines changed: 14 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868

6969
#include <errno.h>
7070
#include <assert.h>
71+
#include <mntent.h> /* setmntent, getmntent_r, endmntent, etc */
7172
#include "nilfs.h"
7273
#include "compat.h" /* PATH_MAX, etc */
7374
#include "util.h"
@@ -76,65 +77,8 @@
7677

7778
extern __u32 crc32_le(__u32 seed, unsigned char const *data, size_t length);
7879

79-
static inline int iseol(int c)
80-
{
81-
return c == '\n' || c == '\0';
82-
}
83-
84-
static size_t tokenize(char *line, char **tokens, size_t ntoks)
85-
{
86-
char *p;
87-
size_t n;
88-
89-
p = line;
90-
for (n = 0; n < ntoks; n++) {
91-
while (isspace(*p))
92-
p++;
93-
if (iseol(*p))
94-
break;
95-
tokens[n] = p++;
96-
while (!isspace(*p) && !iseol(*p))
97-
p++;
98-
if (isspace(*p))
99-
*p++ = '\0';
100-
else
101-
*p = '\0';
102-
}
103-
return n;
104-
}
105-
106-
#define NMNTFLDS 6
107-
#define MNTFLD_FS 0
108-
#define MNTFLD_DIR 1
109-
#define MNTFLD_TYPE 2
110-
#define MNTFLD_OPTS 3
111-
#define MNTFLD_FREQ 4
112-
#define MNTFLD_PASSNO 5
11380
#define MNTOPT_RW "rw"
11481
#define MNTOPT_RO "ro"
115-
#define MNTOPT_SEP ','
116-
117-
static int has_mntopt(const char *opts, const char *opt)
118-
{
119-
const char *p, *q;
120-
size_t len, n;
121-
122-
p = opts;
123-
len = strlen(opt);
124-
while (p != NULL) {
125-
q = strchr(p, MNTOPT_SEP);
126-
if (q) {
127-
n = max_t(size_t, q - p, len);
128-
q++;
129-
} else {
130-
n = max_t(size_t, strlen(p), len);
131-
}
132-
if (strncmp(p, opt, n) == 0)
133-
return 1;
134-
p = q;
135-
}
136-
return 0;
137-
}
13882

13983
#ifndef LINE_MAX
14084
#define LINE_MAX 2048
@@ -143,12 +87,13 @@ static int has_mntopt(const char *opts, const char *opt)
14387
static int nilfs_find_fs(struct nilfs *nilfs, const char *dev, const char *dir,
14488
const char *opt)
14589
{
146-
FILE *fp;
147-
char line[LINE_MAX], *mntent[NMNTFLDS];
148-
int ret, n;
90+
struct mntent *mntent, mntbuf;
91+
char buf[LINE_MAX];
14992
char canonical[PATH_MAX + 2];
15093
char *cdev = NULL, *cdir = NULL;
15194
char *mdev, *mdir;
95+
FILE *fp;
96+
int ret;
15297

15398
ret = -1;
15499
if (dev && myrealpath(dev, canonical, sizeof(canonical))) {
@@ -165,44 +110,41 @@ static int nilfs_find_fs(struct nilfs *nilfs, const char *dev, const char *dir,
165110
dir = cdir;
166111
}
167112

168-
fp = fopen(_PATH_PROC_MOUNTS, "r");
113+
fp = setmntent(_PATH_PROC_MOUNTS, "r");
169114
if (unlikely(fp == NULL))
170115
goto failed_dir;
171116

172-
while (fgets(line, sizeof(line), fp) != NULL) {
173-
n = tokenize(line, mntent, NMNTFLDS);
174-
assert(n == NMNTFLDS);
175-
176-
if (strcmp(mntent[MNTFLD_TYPE], NILFS_FSTYPE) != 0)
117+
while ((mntent = getmntent_r(fp, &mntbuf, buf, sizeof(buf))) != NULL) {
118+
if (strcmp(mntent->mnt_type, NILFS_FSTYPE) != 0)
177119
continue;
178120

179121
if (dir != NULL) {
180-
mdir = mntent[MNTFLD_DIR];
122+
mdir = mntent->mnt_dir;
181123
if (myrealpath(mdir, canonical, sizeof(canonical)))
182124
mdir = canonical;
183125
if (strcmp(mdir, dir) != 0)
184126
continue;
185127
}
186128

187129
if (dev != NULL) {
188-
mdev = mntent[MNTFLD_FS];
130+
mdev = mntent->mnt_fsname;
189131
if (myrealpath(mdev, canonical, sizeof(canonical)))
190132
mdev = canonical;
191133
if (strcmp(mdev, dev) != 0)
192134
continue;
193135
}
194136

195-
if (has_mntopt(mntent[MNTFLD_OPTS], opt)) {
137+
if (hasmntopt(mntent, opt)) {
196138
free(nilfs->n_dev);
197-
nilfs->n_dev = strdup(mntent[MNTFLD_FS]);
139+
nilfs->n_dev = strdup(mntent->mnt_fsname);
198140
if (unlikely(nilfs->n_dev == NULL)) {
199141
free(nilfs->n_ioc);
200142
nilfs->n_ioc = NULL;
201143
ret = -1;
202144
goto failed_proc_mounts;
203145
}
204146
free(nilfs->n_ioc);
205-
nilfs->n_ioc = strdup(mntent[MNTFLD_DIR]);
147+
nilfs->n_ioc = strdup(mntent->mnt_dir);
206148
if (unlikely(nilfs->n_ioc == NULL)) {
207149
free(nilfs->n_dev);
208150
nilfs->n_dev = NULL;
@@ -216,7 +158,7 @@ static int nilfs_find_fs(struct nilfs *nilfs, const char *dev, const char *dir,
216158
errno = ENXIO;
217159

218160
failed_proc_mounts:
219-
fclose(fp);
161+
endmntent(fp);
220162

221163
failed_dir:
222164
free(cdir);

0 commit comments

Comments
 (0)