]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libmount/src/utils.c
2 * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
11 * @short_description: misc utils.
20 #include "pathnames.h"
23 #include "canonicalize.h"
26 #include "statfs_magic.h"
28 int append_string(char **a
, const char *b
)
39 return !*a
? -ENOMEM
: 0;
45 tmp
= realloc(*a
, al
+ bl
+ 1);
49 memcpy((*a
) + al
, b
, bl
+ 1);
54 * Return 1 if the file is not accessible or empty
56 int is_file_empty(const char *name
)
61 return (stat(name
, &st
) != 0 || st
.st_size
== 0);
64 int mnt_valid_tagname(const char *tagname
)
66 if (tagname
&& *tagname
&& (
67 strcmp("UUID", tagname
) == 0 ||
68 strcmp("LABEL", tagname
) == 0 ||
69 strcmp("PARTUUID", tagname
) == 0 ||
70 strcmp("PARTLABEL", tagname
) == 0))
78 * @tag: NAME=value string
80 * Returns: 1 if the @tag is parsable and tag NAME= is supported by libmount, or 0.
82 int mnt_tag_is_valid(const char *tag
)
85 int rc
= tag
&& blkid_parse_tag_string(tag
, &t
, NULL
) == 0
86 && mnt_valid_tagname(t
);
92 int mnt_parse_offset(const char *str
, size_t len
, uintmax_t *res
)
100 p
= strndup(str
, len
);
104 if (strtosize(p
, res
))
110 /* used as a callback by bsearch in mnt_fstype_is_pseudofs() */
111 static int fstype_cmp(const void *v1
, const void *v2
)
113 const char *s1
= *(const char **)v1
;
114 const char *s2
= *(const char **)v2
;
116 return strcmp(s1
, s2
);
119 /* returns basename and keeps dirname in the @path, if @path is "/" (root)
120 * then returns empty string */
121 char *stripoff_last_component(char *path
)
123 char *p
= path
? strrchr(path
, '/') : NULL
;
132 * Note that the @target has to be an absolute path (so at least "/"). The
133 * @filename returns an allocated buffer with the last path component, for example:
135 * mnt_chdir_to_parent("/mnt/test", &buf) ==> chdir("/mnt"), buf="test"
137 int mnt_chdir_to_parent(const char *target
, char **filename
)
139 char *buf
, *parent
, *last
= NULL
;
143 if (!target
|| *target
!= '/')
146 DBG(UTILS
, ul_debug("moving to %s parent", target
));
148 buf
= strdup(target
);
152 if (*(buf
+ 1) != '\0') {
153 last
= stripoff_last_component(buf
);
158 parent
= buf
&& *buf
? buf
: "/";
160 if (chdir(parent
) == -1) {
161 DBG(UTILS
, ul_debug("failed to chdir to %s: %m", parent
));
165 if (!getcwd(cwd
, sizeof(cwd
))) {
166 DBG(UTILS
, ul_debug("failed to obtain current directory: %m"));
170 if (strcmp(cwd
, parent
) != 0) {
172 "unexpected chdir (expected=%s, cwd=%s)", parent
, cwd
));
177 "current directory moved to %s [last_component='%s']",
184 memcpy(*filename
, ".", 2);
186 memmove(*filename
, last
, strlen(last
) + 1);
196 * Check if @path is on a read-only filesystem independently of file permissions.
198 int mnt_is_readonly(const char *path
)
200 if (access(path
, W_OK
) == 0)
209 * access(2) returns EACCES on read-only FS:
211 * - for set-uid application if one component of the path is not
212 * accessible for the current rUID. (Note that euidaccess(2) does not
213 * check for EROFS at all).
215 * - for a read-write filesystem with a read-only VFS node (aka -o remount,ro,bind)
218 struct timespec times
[2];
220 times
[0].tv_nsec
= UTIME_NOW
; /* atime */
221 times
[1].tv_nsec
= UTIME_OMIT
; /* mtime */
223 if (utimensat(AT_FDCWD
, path
, times
, 0) == -1)
224 return errno
== EROFS
;
234 * Encode @str to be compatible with fstab/mtab
236 * Returns: newly allocated string or NULL in case of error.
238 char *mnt_mangle(const char *str
)
247 * Decode @str from fstab/mtab
249 * Returns: newly allocated string or NULL in case of error.
251 char *mnt_unmangle(const char *str
)
253 return unmangle(str
, NULL
);
257 * mnt_fstype_is_pseudofs:
258 * @type: filesystem name
260 * Returns: 1 for filesystems like proc, sysfs, ... or 0.
262 int mnt_fstype_is_pseudofs(const char *type
)
264 /* This array must remain sorted when adding new fstypes */
265 static const char *pseudofs
[] = {
280 "fuse.gvfs-fuse-daemon",
300 return !(bsearch(&type
, pseudofs
, ARRAY_SIZE(pseudofs
),
301 sizeof(char*), fstype_cmp
) == NULL
);
305 * mnt_fstype_is_netfs:
306 * @type: filesystem name
308 * Returns: 1 for filesystems like cifs, nfs, ... or 0.
310 int mnt_fstype_is_netfs(const char *type
)
314 if (strcmp(type
, "cifs") == 0 ||
315 strcmp(type
, "smbfs") == 0 ||
316 strncmp(type
,"nfs", 3) == 0 ||
317 strcmp(type
, "afs") == 0 ||
318 strcmp(type
, "ncpfs") == 0 ||
319 strncmp(type
,"9p", 2) == 0)
324 const char *mnt_statfs_get_fstype(struct statfs
*vfs
)
328 switch (vfs
->f_type
) {
329 case STATFS_ADFS_MAGIC
: return "adfs";
330 case STATFS_AFFS_MAGIC
: return "affs";
331 case STATFS_AFS_MAGIC
: return "afs";
332 case STATFS_AUTOFS_MAGIC
: return "autofs";
333 case STATFS_BDEVFS_MAGIC
: return "bdev";
334 case STATFS_BEFS_MAGIC
: return "befs";
335 case STATFS_BFS_MAGIC
: return "befs";
336 case STATFS_BINFMTFS_MAGIC
: return "binfmt_misc";
337 case STATFS_BTRFS_MAGIC
: return "btrfs";
338 case STATFS_CEPH_MAGIC
: return "ceph";
339 case STATFS_CGROUP_MAGIC
: return "cgroup";
340 case STATFS_CIFS_MAGIC
: return "cifs";
341 case STATFS_CODA_MAGIC
: return "coda";
342 case STATFS_CONFIGFS_MAGIC
: return "configfs";
343 case STATFS_CRAMFS_MAGIC
: return "cramfs";
344 case STATFS_DEBUGFS_MAGIC
: return "debugfs";
345 case STATFS_DEVPTS_MAGIC
: return "devpts";
346 case STATFS_ECRYPTFS_MAGIC
: return "ecryptfs";
347 case STATFS_EFIVARFS_MAGIC
: return "efivarfs";
348 case STATFS_EFS_MAGIC
: return "efs";
349 case STATFS_EXOFS_MAGIC
: return "exofs";
350 case STATFS_EXT4_MAGIC
: return "ext4"; /* all extN use the same magic */
351 case STATFS_F2FS_MAGIC
: return "f2fs";
352 case STATFS_FUSE_MAGIC
: return "fuse";
353 case STATFS_FUTEXFS_MAGIC
: return "futexfs";
354 case STATFS_GFS2_MAGIC
: return "gfs2";
355 case STATFS_HFSPLUS_MAGIC
: return "hfsplus";
356 case STATFS_HOSTFS_MAGIC
: return "hostfs";
357 case STATFS_HPFS_MAGIC
: return "hpfs";
358 case STATFS_HPPFS_MAGIC
: return "hppfs";
359 case STATFS_HUGETLBFS_MAGIC
: return "hugetlbfs";
360 case STATFS_ISOFS_MAGIC
: return "iso9660";
361 case STATFS_JFFS2_MAGIC
: return "jffs2";
362 case STATFS_JFS_MAGIC
: return "jfs";
363 case STATFS_LOGFS_MAGIC
: return "logfs";
364 case STATFS_MINIX2_MAGIC
:
365 case STATFS_MINIX2_MAGIC2
:
366 case STATFS_MINIX3_MAGIC
:
367 case STATFS_MINIX_MAGIC
:
368 case STATFS_MINIX_MAGIC2
: return "minix";
369 case STATFS_MQUEUE_MAGIC
: return "mqueue";
370 case STATFS_MSDOS_MAGIC
: return "vfat";
371 case STATFS_NCP_MAGIC
: return "ncp";
372 case STATFS_NFS_MAGIC
: return "nfs";
373 case STATFS_NILFS_MAGIC
: return "nilfs2";
374 case STATFS_NTFS_MAGIC
: return "ntfs";
375 case STATFS_OCFS2_MAGIC
: return "ocfs2";
376 case STATFS_OMFS_MAGIC
: return "omfs";
377 case STATFS_OPENPROMFS_MAGIC
: return "openpromfs";
378 case STATFS_PIPEFS_MAGIC
: return "pipefs";
379 case STATFS_PROC_MAGIC
: return "proc";
380 case STATFS_PSTOREFS_MAGIC
: return "pstore";
381 case STATFS_QNX4_MAGIC
: return "qnx4";
382 case STATFS_QNX6_MAGIC
: return "qnx6";
383 case STATFS_RAMFS_MAGIC
: return "ramfs";
384 case STATFS_REISERFS_MAGIC
: return "reiser4";
385 case STATFS_ROMFS_MAGIC
: return "romfs";
386 case STATFS_SECURITYFS_MAGIC
: return "securityfs";
387 case STATFS_SELINUXFS_MAGIC
: return "selinuxfs";
388 case STATFS_SMACKFS_MAGIC
: return "smackfs";
389 case STATFS_SMB_MAGIC
: return "smb";
390 case STATFS_SOCKFS_MAGIC
: return "sockfs";
391 case STATFS_SQUASHFS_MAGIC
: return "squashfs";
392 case STATFS_SYSFS_MAGIC
: return "sysfs";
393 case STATFS_TMPFS_MAGIC
: return "tmpfs";
394 case STATFS_UBIFS_MAGIC
: return "ubifs";
395 case STATFS_UDF_MAGIC
: return "udf";
396 case STATFS_UFS2_MAGIC
:
397 case STATFS_UFS_MAGIC
: return "ufs";
398 case STATFS_V9FS_MAGIC
: return "9p";
399 case STATFS_VXFS_MAGIC
: return "vxfs";
400 case STATFS_XENFS_MAGIC
: return "xenfs";
401 case STATFS_XFS_MAGIC
: return "xfs";
412 * @type: filesystem type
413 * @pattern: filesystem name or comma delimited list of names
415 * The @pattern list of filesystems can be prefixed with a global
416 * "no" prefix to invert matching of the whole list. The "no" could
417 * also be used for individual items in the @pattern list. So,
418 * "nofoo,bar" has the same meaning as "nofoo,nobar".
420 * "bar" : "nofoo,bar" -> False (global "no" prefix)
422 * "bar" : "foo,bar" -> True
424 * "bar" : "foo,nobar" -> False
426 * Returns: 1 if type is matching, else 0. This function also returns
427 * 0 if @pattern is NULL and @type is non-NULL.
429 int mnt_match_fstype(const char *type
, const char *pattern
)
431 return match_fstype(type
, pattern
);
435 /* Returns 1 if needle found or noneedle not found in haystack
436 * Otherwise returns 0
438 static int check_option(const char *haystack
, size_t len
,
439 const char *needle
, size_t needle_len
)
444 if (needle_len
>= 1 && *needle
== '+') {
447 } else if (needle_len
>= 2 && !strncmp(needle
, "no", 2)) {
453 for (p
= haystack
; p
&& p
< haystack
+ len
; p
++) {
454 char *sep
= strchr(p
, ',');
455 size_t plen
= sep
? (size_t) (sep
- p
) :
456 len
- (p
- haystack
);
458 if (plen
== needle_len
) {
459 if (!strncmp(p
, needle
, plen
))
460 return !no
; /* foo or nofoo was found */
465 return no
; /* foo or nofoo was not found */
470 * @optstr: options string
471 * @pattern: comma delimited list of options
473 * The "no" could be used for individual items in the @options list. The "no"
474 * prefix does not have a global meaning.
476 * Unlike fs type matching, nonetdev,user and nonetdev,nouser have
477 * DIFFERENT meanings; each option is matched explicitly as specified.
479 * The "no" prefix interpretation could be disabled by the "+" prefix, for example
480 * "+noauto" matches if @optstr literally contains the "noauto" string.
482 * "xxx,yyy,zzz" : "nozzz" -> False
484 * "xxx,yyy,zzz" : "xxx,noeee" -> True
486 * "bar,zzz" : "nofoo" -> True
488 * "nofoo,bar" : "+nofoo" -> True
490 * "bar,zzz" : "+nofoo" -> False
493 * Returns: 1 if pattern is matching, else 0. This function also returns 0
494 * if @pattern is NULL and @optstr is non-NULL.
496 int mnt_match_options(const char *optstr
, const char *pattern
)
499 size_t len
, optstr_len
= 0;
501 if (!pattern
&& !optstr
)
506 len
= strlen(pattern
);
508 optstr_len
= strlen(optstr
);
510 for (p
= pattern
; p
< pattern
+ len
; p
++) {
511 char *sep
= strchr(p
, ',');
512 size_t plen
= sep
? (size_t) (sep
- p
) :
516 continue; /* if two ',' appear in a row */
518 if (!check_option(optstr
, optstr_len
, p
, plen
))
519 return 0; /* any match failure means failure */
524 /* no match failures in list means success */
528 void mnt_free_filesystems(char **filesystems
)
534 for (p
= filesystems
; *p
; p
++)
539 static int add_filesystem(char ***filesystems
, char *name
)
548 for (n
= 0, p
= *filesystems
; *p
; p
++, n
++) {
549 if (strcmp(*p
, name
) == 0)
556 if (n
== 0 || !((n
+ 1) % MYCHUNK
)) {
557 size_t items
= ((n
+ 1 + MYCHUNK
) / MYCHUNK
) * MYCHUNK
;
558 char **x
= realloc(*filesystems
, items
* sizeof(char *));
567 (*filesystems
)[n
] = name
;
568 (*filesystems
)[n
+ 1] = NULL
;
571 mnt_free_filesystems(*filesystems
);
575 static int get_filesystems(const char *filename
, char ***filesystems
, const char *pattern
)
581 f
= fopen(filename
, "r" UL_CLOEXECSTR
);
585 DBG(UTILS
, ul_debug("reading filesystems list from: %s", filename
));
587 while (fgets(line
, sizeof(line
), f
)) {
588 char name
[sizeof(line
)];
590 if (*line
== '#' || strncmp(line
, "nodev", 5) == 0)
592 if (sscanf(line
, " %128[^\n ]\n", name
) != 1)
594 if (strcmp(name
, "*") == 0) {
596 break; /* end of the /etc/filesystems */
598 if (pattern
&& !mnt_match_fstype(name
, pattern
))
600 rc
= add_filesystem(filesystems
, name
);
610 * Always check the @filesystems pointer!
614 * ...mount will try to read the file /etc/filesystems, or, if that does not
615 * exist, /proc/filesystems. All of the filesystem types listed there will
616 * be tried, except for those that are labeled "nodev" (e.g., devpts,
617 * proc and nfs). If /etc/filesystems ends in a line with a single * only,
618 * mount will read /proc/filesystems afterwards.
620 int mnt_get_filesystems(char ***filesystems
, const char *pattern
)
629 rc
= get_filesystems(_PATH_FILESYSTEMS
, filesystems
, pattern
);
633 rc
= get_filesystems(_PATH_PROC_FILESYSTEMS
, filesystems
, pattern
);
634 if (rc
== 1 && *filesystems
)
635 rc
= 0; /* /proc/filesystems not found */
640 static size_t get_pw_record_size(void)
642 #ifdef _SC_GETPW_R_SIZE_MAX
643 long sz
= sysconf(_SC_GETPW_R_SIZE_MAX
);
651 * Returns an allocated string with username or NULL.
653 char *mnt_get_username(const uid_t uid
)
657 size_t sz
= get_pw_record_size();
658 char *buf
, *username
= NULL
;
664 if (!getpwuid_r(uid
, &pwd
, buf
, sz
, &res
) && res
)
665 username
= strdup(pwd
.pw_name
);
671 int mnt_get_uid(const char *username
, uid_t
*uid
)
676 size_t sz
= get_pw_record_size();
679 if (!username
|| !uid
)
686 if (!getpwnam_r(username
, &pwd
, buf
, sz
, &pw
) && pw
) {
691 "cannot convert '%s' username to UID", username
));
692 rc
= errno
? -errno
: -EINVAL
;
699 int mnt_get_gid(const char *groupname
, gid_t
*gid
)
704 size_t sz
= get_pw_record_size();
707 if (!groupname
|| !gid
)
714 if (!getgrnam_r(groupname
, &grp
, buf
, sz
, &gr
) && gr
) {
719 "cannot convert '%s' groupname to GID", groupname
));
720 rc
= errno
? -errno
: -EINVAL
;
727 int mnt_in_group(gid_t gid
)
735 n
= getgroups(0, NULL
);
739 grps
= malloc(n
* sizeof(*grps
));
743 if (getgroups(n
, grps
) == n
) {
744 for (i
= 0; i
< n
; i
++) {
745 if (grps
[i
] == gid
) {
756 static int try_write(const char *filename
)
763 fd
= open(filename
, O_RDWR
|O_CREAT
|O_CLOEXEC
,
764 S_IWUSR
|S_IRUSR
|S_IRGRP
|S_IROTH
);
773 * mnt_has_regular_mtab:
774 * @mtab: returns path to mtab
775 * @writable: returns 1 if the file is writable
777 * If the file does not exist and @writable argument is not NULL, then it will
778 * try to create the file.
780 * Returns: 1 if /etc/mtab is a regular file, and 0 in case of error (check
781 * errno for more details).
783 int mnt_has_regular_mtab(const char **mtab
, int *writable
)
787 const char *filename
= mtab
&& *mtab
? *mtab
: mnt_get_mtab_path();
794 DBG(UTILS
, ul_debug("mtab: %s", filename
));
796 rc
= lstat(filename
, &st
);
800 if (S_ISREG(st
.st_mode
)) {
802 *writable
= !try_write(filename
);
808 /* try to create the file */
810 *writable
= !try_write(filename
);
816 DBG(UTILS
, ul_debug("%s: irregular/non-writable", filename
));
821 * Don't export this to libmount API -- utab is private library stuff.
823 * If the file does not exist and @writable argument is not NULL, then it will
824 * try to create the directory (e.g. /run/mount) and the file.
826 * Returns: 1 if utab is a regular file, and 0 in case of
827 * error (check errno for more details).
829 int mnt_has_regular_utab(const char **utab
, int *writable
)
833 const char *filename
= utab
&& *utab
? *utab
: mnt_get_utab_path();
840 DBG(UTILS
, ul_debug("utab: %s", filename
));
842 rc
= lstat(filename
, &st
);
846 if (S_ISREG(st
.st_mode
)) {
848 *writable
= !try_write(filename
);
851 goto done
; /* it's not a regular file */
855 char *dirname
= strdup(filename
);
860 stripoff_last_component(dirname
); /* remove filename */
862 rc
= mkdir(dirname
, S_IWUSR
|
863 S_IRUSR
|S_IRGRP
|S_IROTH
|
864 S_IXUSR
|S_IXGRP
|S_IXOTH
);
866 if (rc
&& errno
!= EEXIST
)
867 goto done
; /* probably EACCES */
869 *writable
= !try_write(filename
);
874 DBG(UTILS
, ul_debug("%s: irregular/non-writable file", filename
));
879 * mnt_get_swaps_path:
881 * Returns: path to /proc/swaps or $LIBMOUNT_SWAPS.
883 const char *mnt_get_swaps_path(void)
885 const char *p
= safe_getenv("LIBMOUNT_SWAPS");
886 return p
? : _PATH_PROC_SWAPS
;
890 * mnt_get_fstab_path:
892 * Returns: path to /etc/fstab or $LIBMOUNT_FSTAB.
894 const char *mnt_get_fstab_path(void)
896 const char *p
= safe_getenv("LIBMOUNT_FSTAB");
897 return p
? : _PATH_MNTTAB
;
903 * This function returns the *default* location of the mtab file. The result does
904 * not have to be writable. See also mnt_has_regular_mtab().
906 * Returns: path to /etc/mtab or $LIBMOUNT_MTAB.
908 const char *mnt_get_mtab_path(void)
910 const char *p
= safe_getenv("LIBMOUNT_MTAB");
911 return p
? : _PATH_MOUNTED
;
915 * Don't export this to libmount API -- utab is private library stuff.
917 * Returns: path to /run/mount/utab (or /dev/.mount/utab) or $LIBMOUNT_UTAB.
919 const char *mnt_get_utab_path(void)
922 const char *p
= safe_getenv("LIBMOUNT_UTAB");
927 if (stat(MNT_RUNTIME_TOPDIR
, &st
) == 0)
928 return MNT_PATH_UTAB
;
930 return MNT_PATH_UTAB_OLD
;
934 /* returns file descriptor or -errno, @name returns a unique filename
936 int mnt_open_uniq_filename(const char *filename
, char **name
)
947 rc
= asprintf(&n
, "%s.XXXXXX", filename
);
951 /* This is for very old glibc and for compatibility with Posix, which says
952 * nothing about mkstemp() mode. All sane glibc use secure mode (0600).
954 oldmode
= umask(S_IRGRP
|S_IWGRP
|S_IXGRP
|
955 S_IROTH
|S_IWOTH
|S_IXOTH
);
956 fd
= mkostemp(n
, O_RDWR
|O_CREAT
|O_EXCL
|O_CLOEXEC
);
970 * mnt_get_mountpoint:
973 * This function finds the mountpoint that a given path resides in. @path
974 * should be canonicalized. The returned pointer should be freed by the caller.
976 * Returns: allocated string with the target of the mounted device or NULL on error
978 char *mnt_get_mountpoint(const char *path
)
989 if (*mnt
== '/' && *(mnt
+ 1) == '\0')
997 char *p
= stripoff_last_component(mnt
);
1001 if (stat(*mnt
? mnt
: "/", &st
))
1010 } while (mnt
&& *(mnt
+ 1) != '\0');
1012 memcpy(mnt
, "/", 2);
1014 DBG(UTILS
, ul_debug("%s mountpoint is %s", path
, mnt
));
1021 char *mnt_get_fs_root(const char *path
, const char *mnt
)
1023 char *m
= (char *) mnt
, *res
;
1028 m
= mnt_get_mountpoint(path
);
1033 p
= sz
> 1 ? path
+ sz
: path
;
1038 res
= *p
? strdup(p
) : strdup("/");
1039 DBG(UTILS
, ul_debug("%s fs-root is %s", path
, res
));
1044 * Search for @name kernel command parametr.
1046 * Returns newly allocated string with a parameter argument if the @name is
1047 * specified as "name=" or returns pointer to @name or returns NULL if not
1050 * For example cmdline: "aaa bbb=BBB ccc"
1052 * @name is "aaa" --returns--> "aaa" (pointer to @name)
1053 * @name is "bbb=" --returns--> "BBB" (allocated)
1054 * @name is "foo" --returns--> NULL
1056 char *mnt_get_kernel_cmdline_option(const char *name
)
1061 char *p
, *res
= NULL
;
1062 char buf
[BUFSIZ
]; /* see kernel include/asm-generic/setup.h: COMMAND_LINE_SIZE */
1063 const char *path
= _PATH_PROC_CMDLINE
;
1069 path
= getenv("LIBMOUNT_KERNEL_CMDLINE");
1071 path
= _PATH_PROC_CMDLINE
;
1073 f
= fopen(path
, "r" UL_CLOEXECSTR
);
1077 p
= fgets(buf
, sizeof(buf
), f
);
1080 if (!p
|| !*p
|| *p
== '\n')
1084 *(buf
+ len
- 1) = '\0'; /* remove last '\n' */
1087 if (len
&& *(name
+ len
- 1) == '=')
1090 for ( ; p
&& *p
; p
++) {
1091 if (!(p
= strstr(p
, name
)))
1092 break; /* not found the option */
1093 if (p
!= buf
&& !isblank(*(p
- 1)))
1094 continue; /* no space before the option */
1095 if (!val
&& *(p
+ len
) != '\0' && !isblank(*(p
+ len
)))
1096 continue; /* no space after the option */
1100 while (*p
&& !isblank(*p
)) /* jump to the end of the argument */
1106 res
= (char *) name
; /* option without '=' */
1113 int mkdir_p(const char *path
, mode_t mode
)
1118 if (!path
|| !*path
)
1121 dir
= p
= strdup(path
);
1129 char *e
= strchr(p
, '/');
1133 rc
= mkdir(dir
, mode
);
1134 if (rc
&& errno
!= EEXIST
)
1144 DBG(UTILS
, ul_debug("%s mkdir %s", path
, rc
? "FAILED" : "SUCCESS"));
1151 int test_match_fstype(struct libmnt_test
*ts
, int argc
, char *argv
[])
1153 char *type
= argv
[1];
1154 char *pattern
= argv
[2];
1156 printf("%s\n", mnt_match_fstype(type
, pattern
) ? "MATCH" : "NOT-MATCH");
1160 int test_match_options(struct libmnt_test
*ts
, int argc
, char *argv
[])
1162 char *optstr
= argv
[1];
1163 char *pattern
= argv
[2];
1165 printf("%s\n", mnt_match_options(optstr
, pattern
) ? "MATCH" : "NOT-MATCH");
1169 int test_startswith(struct libmnt_test
*ts
, int argc
, char *argv
[])
1171 char *optstr
= argv
[1];
1172 char *pattern
= argv
[2];
1174 printf("%s\n", startswith(optstr
, pattern
) ? "YES" : "NOT");
1178 int test_endswith(struct libmnt_test
*ts
, int argc
, char *argv
[])
1180 char *optstr
= argv
[1];
1181 char *pattern
= argv
[2];
1183 printf("%s\n", endswith(optstr
, pattern
) ? "YES" : "NOT");
1187 int test_appendstr(struct libmnt_test
*ts
, int argc
, char *argv
[])
1189 char *str
= strdup(argv
[1]);
1190 const char *ap
= argv
[2];
1192 append_string(&str
, ap
);
1193 printf("new string: '%s'\n", str
);
1199 int test_mountpoint(struct libmnt_test
*ts
, int argc
, char *argv
[])
1201 char *path
= canonicalize_path(argv
[1]),
1202 *mnt
= path
? mnt_get_mountpoint(path
) : NULL
;
1204 printf("%s: %s\n", argv
[1], mnt
? : "unknown");
1210 int test_fsroot(struct libmnt_test
*ts
, int argc
, char *argv
[])
1212 char *path
= canonicalize_path(argv
[1]),
1213 *mnt
= path
? mnt_get_fs_root(path
, NULL
) : NULL
;
1215 printf("%s: %s\n", argv
[1], mnt
? : "unknown");
1221 int test_filesystems(struct libmnt_test
*ts
, int argc
, char *argv
[])
1223 char **filesystems
= NULL
;
1226 rc
= mnt_get_filesystems(&filesystems
, argc
? argv
[1] : NULL
);
1229 for (p
= filesystems
; *p
; p
++)
1231 mnt_free_filesystems(filesystems
);
1236 int test_chdir(struct libmnt_test
*ts
, int argc
, char *argv
[])
1239 char *path
= canonicalize_path(argv
[1]),
1245 rc
= mnt_chdir_to_parent(path
, &last
);
1247 printf("path='%s', abs='%s', last='%s'\n",
1248 argv
[1], path
, last
);
1255 int test_kernel_cmdline(struct libmnt_test
*ts
, int argc
, char *argv
[])
1257 char *name
= argv
[1];
1260 res
= mnt_get_kernel_cmdline_option(name
);
1262 printf("'%s' not found\n", name
);
1263 else if (res
== name
)
1264 printf("'%s' found\n", name
);
1266 printf("'%s' found, argument: '%s'\n", name
, res
);
1273 int test_mkdir(struct libmnt_test
*ts
, int argc
, char *argv
[])
1277 rc
= mkdir_p(argv
[1], S_IRWXU
|
1281 printf("mkdir %s failed\n", argv
[1]);
1285 int test_statfs_type(struct libmnt_test
*ts
, int argc
, char *argv
[])
1290 rc
= statfs(argv
[1], &vfs
);
1292 printf("%s: statfs failed: %m\n", argv
[1]);
1294 printf("%-30s: statfs type: %-12s [0x%lx]\n", argv
[1],
1295 mnt_statfs_get_fstype(&vfs
),
1301 int main(int argc
, char *argv
[])
1303 struct libmnt_test tss
[] = {
1304 { "--match-fstype", test_match_fstype
, "<type> <pattern> FS types matching" },
1305 { "--match-options", test_match_options
, "<options> <pattern> options matching" },
1306 { "--filesystems", test_filesystems
, "[<pattern>] list /{etc,proc}/filesystems" },
1307 { "--starts-with", test_startswith
, "<string> <prefix>" },
1308 { "--ends-with", test_endswith
, "<string> <prefix>" },
1309 { "--append-string", test_appendstr
, "<string> <appendix>" },
1310 { "--mountpoint", test_mountpoint
, "<path>" },
1311 { "--fs-root", test_fsroot
, "<path>" },
1312 { "--cd-parent", test_chdir
, "<path>" },
1313 { "--kernel-cmdline",test_kernel_cmdline
, "<option> | <option>=" },
1314 { "--mkdir", test_mkdir
, "<path>" },
1315 { "--statfs-type", test_statfs_type
, "<path>" },
1320 return mnt_run_test(tss
, argc
, argv
);
1323 #endif /* TEST_PROGRAM */