]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxcmd/paths.c
2 * Copyright (c) 2005-2006 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <sys/types.h>
28 #include <xfs/input.h>
29 #include <xfs/project.h>
31 extern char *progname
;
34 struct fs_path
*fs_table
;
35 struct fs_path
*fs_path
;
38 #define PROC_MOUNTS "/proc/self/mounts"
47 if (stat64(name
, &sbuf
) < 0)
50 * We want to match st_rdev if the path provided is a device
51 * special file. Otherwise we are looking for the the
52 * device id for the containing filesystem, in st_dev.
54 if (S_ISBLK(sbuf
.st_mode
) || S_ISCHR(sbuf
.st_mode
))
55 *devnum
= sbuf
.st_rdev
;
57 *devnum
= sbuf
.st_dev
;
63 * Find the FS table entry for the given path. The "flags" argument
64 * is a mask containing FS_MOUNT_POINT or FS_PROJECT_PATH (or both)
65 * to indicate the type of table entry sought.
75 if (fs_device_number(dir
, &dev
))
78 for (i
= 0; i
< fs_count
; i
++) {
79 if ((flags
& fs_table
[i
].fs_flags
) == 0)
81 if (fs_table
[i
].fs_datadev
== dev
)
96 dev_t datadev
, logdev
, rtdev
;
97 struct fs_path
*tmp_fs_table
;
102 datadev
= logdev
= rtdev
= 0;
103 if (fs_device_number(dir
, &datadev
))
105 if (fslog
&& fs_device_number(fslog
, &logdev
))
107 if (fsrt
&& fs_device_number(fsrt
, &rtdev
))
110 tmp_fs_table
= realloc(fs_table
, sizeof(fs_path_t
) * (fs_count
+ 1));
113 fs_table
= tmp_fs_table
;
115 fs_path
= &fs_table
[fs_count
];
116 fs_path
->fs_dir
= dir
;
117 fs_path
->fs_prid
= prid
;
118 fs_path
->fs_flags
= flags
;
119 fs_path
->fs_name
= fsname
;
120 fs_path
->fs_log
= fslog
;
121 fs_path
->fs_rt
= fsrt
;
122 fs_path
->fs_datadev
= datadev
;
123 fs_path
->fs_logdev
= logdev
;
124 fs_path
->fs_rtdev
= rtdev
;
130 fs_table_destroy(void)
132 while (--fs_count
>= 0) {
133 free(fs_table
[fs_count
].fs_name
);
134 if (fs_table
[fs_count
].fs_log
)
135 free(fs_table
[fs_count
].fs_log
);
136 if (fs_table
[fs_count
].fs_rt
)
137 free(fs_table
[fs_count
].fs_rt
);
138 free(fs_table
[fs_count
].fs_dir
);
147 #if defined(HAVE_GETMNTENT)
151 fs_extract_mount_options(
158 /* Extract log device and realtime device from mount options */
159 if ((fslog
= hasmntopt(mnt
, "logdev=")))
161 if ((fsrt
= hasmntopt(mnt
, "rtdev=")))
164 /* Do this only after we've finished processing mount options */
167 fslog
= strdup(fslog
);
179 fs_table_initialise_mounts(
184 char *dir
, *fsname
, *fslog
, *fsrt
;
188 dir
= fsname
= fslog
= fsrt
= NULL
;
191 mtab_file
= PROC_MOUNTS
;
192 if (access(mtab_file
, R_OK
) != 0)
196 if ((mtp
= setmntent(mtab_file
, "r")) == NULL
)
199 while ((mnt
= getmntent(mtp
)) != NULL
) {
200 if (strcmp(mnt
->mnt_type
, "xfs") != 0)
203 ((strcmp(path
, mnt
->mnt_dir
) != 0) &&
204 (strcmp(path
, mnt
->mnt_fsname
) != 0)))
207 dir
= strdup(mnt
->mnt_dir
);
208 fsname
= strdup(mnt
->mnt_fsname
);
209 if (!dir
|| !fsname
) {
213 fs_extract_mount_options(mnt
, &fslog
, &fsrt
);
214 if ((error
= fs_table_insert(dir
, 0, FS_MOUNT_POINT
,
215 fsname
, fslog
, fsrt
)))
219 if (!error
&& path
&& !found
)
223 if (fsrt
) free(fsrt
);
224 if (fslog
) free(fslog
);
225 if (fsname
) free(fsname
);
230 #elif defined(HAVE_GETMNTINFO)
231 #include <sys/mount.h>
234 fs_table_initialise_mounts(
237 struct statfs
*stats
;
238 char *dir
, *fsname
, *fslog
, *fsrt
;
239 int i
, count
, error
, found
;
242 dir
= fsname
= fslog
= fsrt
= NULL
;
244 if ((count
= getmntinfo(&stats
, 0)) < 0) {
245 fprintf(stderr
, _("%s: getmntinfo() failed: %s\n"),
246 progname
, strerror(errno
));
250 for (i
= 0; i
< count
; i
++) {
251 if (strcmp(stats
[i
].f_fstypename
, "xfs") != 0)
254 ((strcmp(path
, stats
[i
].f_mntonname
) != 0) &&
255 (strcmp(path
, stats
[i
].f_mntfromname
) != 0)))
258 dir
= strdup(stats
[i
].f_mntonname
);
259 fsname
= strdup(stats
[i
].f_mntfromname
);
260 if (!dir
|| !fsname
) {
264 /* TODO: external log and realtime device? */
265 if ((error
= fs_table_insert(dir
, 0, FS_MOUNT_POINT
,
266 fsname
, fslog
, fsrt
)))
269 if (!error
&& path
&& !found
)
273 if (fsrt
) free(fsrt
);
274 if (fslog
) free(fslog
);
275 if (fsname
) free(fsname
);
281 # error "How do I extract info about mounted filesystems on this platform?"
285 * Given a directory, match it up to a filesystem mount point.
287 static struct fs_path
*
288 fs_mount_point_from_path(
295 if (fs_device_number(dir
, &dev
))
298 fs_cursor_initialise(NULL
, FS_MOUNT_POINT
, &cursor
);
299 while ((fs
= fs_cursor_next_entry(&cursor
))) {
300 if (fs
->fs_datadev
== dev
)
307 fs_table_initialise_projects(
310 fs_project_path_t
*path
;
313 char *dir
= NULL
, *fsname
= NULL
;
314 int error
= 0, found
= 0;
317 prid
= prid_from_string(project
);
320 while ((path
= getprpathent()) != NULL
) {
321 if (project
&& prid
!= path
->pp_prid
)
323 if ((fs
= fs_mount_point_from_path(path
->pp_pathname
)) == NULL
) {
324 fprintf(stderr
, _("%s: cannot find mount point for path `%s': %s\n"),
325 progname
, path
->pp_pathname
, strerror(errno
));
329 dir
= strdup(path
->pp_pathname
);
330 fsname
= strdup(fs
->fs_name
);
331 if (!dir
|| !fsname
) {
335 if ((error
= fs_table_insert(dir
, path
->pp_prid
,
336 FS_PROJECT_PATH
, fsname
, NULL
, NULL
)))
341 if (!error
&& project
&& !found
)
345 if (fsname
) free(fsname
);
351 fs_table_initialise(void)
355 error
= fs_table_initialise_mounts(NULL
);
357 error
= fs_table_initialise_projects(NULL
);
360 fprintf(stderr
, _("%s: cannot initialise path table: %s\n"),
361 progname
, strerror(error
));
367 fs_table_insert_mount(
372 error
= fs_table_initialise_mounts(mount
);
375 fprintf(stderr
, _("%s: cannot setup path for mount %s: %s\n"),
376 progname
, mount
, strerror(error
));
382 fs_table_insert_project(
388 fprintf(stderr
, _("%s: no mount table yet, so no projects\n"),
392 error
= fs_table_initialise_projects(project
);
395 fprintf(stderr
, _("%s: cannot setup path for project %s: %s\n"),
396 progname
, project
, strerror(error
));
402 fs_table_insert_project_path(
407 char *dir
= NULL
, *fsname
= NULL
;
410 if ((fs
= fs_mount_point_from_path(udir
)) != NULL
) {
412 fsname
= strdup(fs
->fs_name
);
414 error
= fs_table_insert(dir
, prid
,
415 FS_PROJECT_PATH
, fsname
, NULL
, NULL
);
426 fprintf(stderr
, _("%s: cannot setup path for project dir %s: %s\n"),
427 progname
, udir
, strerror(error
));
432 * Table iteration (cursor-based) interfaces
436 fs_cursor_initialise(
443 memset(cur
, 0, sizeof(*cur
));
445 if ((path
= fs_table_lookup(dir
, flags
)) == NULL
)
449 cur
->table
= &cur
->local
;
451 cur
->count
= fs_count
;
452 cur
->table
= fs_table
;
458 fs_cursor_next_entry(
461 fs_path_t
*next
= NULL
;
463 while (cur
->index
< cur
->count
) {
464 next
= &cur
->table
[cur
->index
++];
465 if (cur
->flags
& next
->fs_flags
)