]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxcmd/paths.c
bd84cde97f0a19e22abbb5a5c700fd61f225c855
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>
32 extern char *progname
;
35 struct fs_path
*fs_table
;
36 struct fs_path
*fs_path
;
39 #define PROC_MOUNTS "/proc/self/mounts"
48 if (stat64(name
, &sbuf
) < 0)
51 * We want to match st_rdev if the path provided is a device
52 * special file. Otherwise we are looking for the the
53 * device id for the containing filesystem, in st_dev.
55 if (S_ISBLK(sbuf
.st_mode
) || S_ISCHR(sbuf
.st_mode
))
56 *devnum
= sbuf
.st_rdev
;
58 *devnum
= sbuf
.st_dev
;
64 * Find the FS table entry for the given path. The "flags" argument
65 * is a mask containing FS_MOUNT_POINT or FS_PROJECT_PATH (or both)
66 * to indicate the type of table entry sought.
76 if (fs_device_number(dir
, &dev
))
79 for (i
= 0; i
< fs_count
; i
++) {
80 if (flags
&& !(flags
& fs_table
[i
].fs_flags
))
82 if (fs_table
[i
].fs_datadev
== dev
)
97 dev_t datadev
, logdev
, rtdev
;
98 struct fs_path
*tmp_fs_table
;
101 datadev
= logdev
= rtdev
= 0;
102 error
= fs_device_number(dir
, &datadev
);
106 error
= fs_device_number(fslog
, &logdev
);
111 error
= fs_device_number(fsrt
, &rtdev
);
117 * Make copies of the directory and data device path.
118 * The log device and real-time device, if non-null,
119 * are already the result of strdup() calls so we
120 * don't need to duplicate those. In fact, this
121 * function is assumed to "consume" both of those
122 * pointers, meaning if an error occurs they will
129 fsname
= strdup(fsname
);
133 tmp_fs_table
= realloc(fs_table
, sizeof(fs_path_t
) * (fs_count
+ 1));
136 fs_table
= tmp_fs_table
;
138 fs_path
= &fs_table
[fs_count
];
139 fs_path
->fs_dir
= dir
;
140 fs_path
->fs_prid
= prid
;
141 fs_path
->fs_flags
= flags
;
142 fs_path
->fs_name
= fsname
;
143 fs_path
->fs_log
= fslog
;
144 fs_path
->fs_rt
= fsrt
;
145 fs_path
->fs_datadev
= datadev
;
146 fs_path
->fs_logdev
= logdev
;
147 fs_path
->fs_rtdev
= rtdev
;
157 /* "Consume" fslog and fsrt even if there's an error */
165 * Table iteration (cursor-based) interfaces
169 * Initialize an fs_table cursor. If a directory path is supplied,
170 * the cursor is set up to appear as though the table contains only
171 * a single entry which represents the directory specified.
172 * Otherwise it is set up to prepare for visiting all entries in the
173 * global table, starting with the first. "flags" can be either
174 * FS_MOUNT_POINT or FS_PROJECT_PATH to limit what type of entries
175 * will be selected by fs_cursor_next_entry(). 0 can be used as a
176 * wild card (selecting either type).
179 fs_cursor_initialise(
186 memset(cur
, 0, sizeof(*cur
));
188 if ((path
= fs_table_lookup(dir
, flags
)) == NULL
)
192 cur
->table
= &cur
->local
;
194 cur
->count
= fs_count
;
195 cur
->table
= fs_table
;
201 * Use the cursor to find the next entry in the table having the
202 * type specified by the cursor's "flags" field.
205 fs_cursor_next_entry(
208 while (cur
->index
< cur
->count
) {
209 fs_path_t
*next
= &cur
->table
[cur
->index
++];
211 if (!cur
->flags
|| (cur
->flags
& next
->fs_flags
))
218 #if defined(HAVE_GETMNTENT)
222 * Determines whether the "logdev" or "rtdev" mount options are
223 * present for the given mount point. If so, the value for each (a
224 * device path) is returned in the pointers whose addresses are
225 * provided. The pointers are assigned NULL for an option not
226 * present. Note that the path buffers returned are allocated
227 * dynamically and it is the caller's responsibility to free them.
230 fs_extract_mount_options(
237 /* Extract log device and realtime device from mount options */
238 if ((fslog
= hasmntopt(mnt
, "logdev=")))
240 if ((fsrt
= hasmntopt(mnt
, "rtdev=")))
243 /* Do this only after we've finished processing mount options */
245 fslog
= strndup(fslog
, strcspn(fslog
, " ,"));
250 fsrt
= strndup(fsrt
, strcspn(fsrt
, " ,"));
264 fprintf(stderr
, _("%s: unable to extract mount options for \"%s\"\n"),
265 progname
, mnt
->mnt_dir
);
270 fs_table_initialise_mounts(
283 mtab_file
= PROC_MOUNTS
;
284 if (access(mtab_file
, R_OK
) != 0)
288 if ((mtp
= setmntent(mtab_file
, "r")) == NULL
)
292 if ((rpath
= realpath(path
, NULL
)) == NULL
)
295 while ((mnt
= getmntent(mtp
)) != NULL
) {
296 if (strcmp(mnt
->mnt_type
, "xfs") != 0)
299 ((strcmp(rpath
, mnt
->mnt_dir
) != 0) &&
300 (strcmp(rpath
, mnt
->mnt_fsname
) != 0)))
302 if (fs_extract_mount_options(mnt
, &fslog
, &fsrt
))
304 (void) fs_table_insert(mnt
->mnt_dir
, 0, FS_MOUNT_POINT
,
305 mnt
->mnt_fsname
, fslog
, fsrt
);
320 #elif defined(HAVE_GETMNTINFO)
321 #include <sys/mount.h>
324 fs_table_initialise_mounts(
327 struct statfs
*stats
;
328 int i
, count
, error
, found
;
332 if ((count
= getmntinfo(&stats
, 0)) < 0) {
333 fprintf(stderr
, _("%s: getmntinfo() failed: %s\n"),
334 progname
, strerror(errno
));
339 if ((rpath
= realpath(path
, NULL
)) == NULL
)
342 for (i
= 0; i
< count
; i
++) {
343 if (strcmp(stats
[i
].f_fstypename
, "xfs") != 0)
346 ((strcmp(rpath
, stats
[i
].f_mntonname
) != 0) &&
347 (strcmp(rpath
, stats
[i
].f_mntfromname
) != 0)))
349 /* TODO: external log and realtime device? */
350 (void) fs_table_insert(stats
[i
].f_mntonname
, 0,
351 FS_MOUNT_POINT
, stats
[i
].f_mntfromname
,
368 # error "How do I extract info about mounted filesystems on this platform?"
372 * Given a directory, match it up to a filesystem mount point.
374 static struct fs_path
*
375 fs_mount_point_from_path(
382 if (fs_device_number(dir
, &dev
))
385 fs_cursor_initialise(NULL
, FS_MOUNT_POINT
, &cursor
);
386 while ((fs
= fs_cursor_next_entry(&cursor
))) {
387 if (fs
->fs_datadev
== dev
)
394 fs_table_insert_mount(
399 error
= fs_table_initialise_mounts(mount
);
401 fprintf(stderr
, _("%s: cannot setup path for mount %s: %s\n"),
402 progname
, mount
, strerror(error
));
406 fs_table_initialise_projects(
409 fs_project_path_t
*path
;
412 int error
= 0, found
= 0;
415 prid
= prid_from_string(project
);
418 while ((path
= getprpathent()) != NULL
) {
419 if (project
&& prid
!= path
->pp_prid
)
421 fs
= fs_mount_point_from_path(path
->pp_pathname
);
423 fprintf(stderr
, _("%s: cannot find mount point for path `%s': %s\n"),
424 progname
, path
->pp_pathname
, strerror(errno
));
427 (void) fs_table_insert(path
->pp_pathname
, path
->pp_prid
,
428 FS_PROJECT_PATH
, fs
->fs_name
,
437 if (project
&& !found
)
444 fs_table_insert_project(
449 error
= fs_table_initialise_projects(project
);
451 fprintf(stderr
, _("%s: cannot setup path for project %s: %s\n"),
452 progname
, project
, strerror(error
));
456 * Initialize fs_table to contain the given set of mount points and
457 * projects. If mount_count is zero, mounts is ignored and the
458 * table is populated with mounted filesystems. If project_count is
459 * zero, projects is ignored and the table is populated with all
460 * projects defined in the projects file.
473 for (i
= 0; i
< mount_count
; i
++)
474 fs_table_insert_mount(mounts
[i
]);
476 error
= fs_table_initialise_mounts(NULL
);
481 for (i
= 0; i
< project_count
; i
++)
482 fs_table_insert_project(projects
[i
]);
484 error
= fs_table_initialise_projects(NULL
);
492 fprintf(stderr
, _("%s: cannot initialise path table: %s\n"),
493 progname
, strerror(error
));
497 fs_table_insert_project_path(
504 fs
= fs_mount_point_from_path(dir
);
506 error
= fs_table_insert(dir
, prid
, FS_PROJECT_PATH
,
507 fs
->fs_name
, NULL
, NULL
);
512 fprintf(stderr
, _("%s: cannot setup path for project dir %s: %s\n"),
513 progname
, dir
, strerror(error
));