summaryrefslogtreecommitdiff
path: root/libmount/src/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmount/src/fs.c')
-rw-r--r--libmount/src/fs.c222
1 files changed, 176 insertions, 46 deletions
diff --git a/libmount/src/fs.c b/libmount/src/fs.c
index c95cdc7e7..3ab614503 100644
--- a/libmount/src/fs.c
+++ b/libmount/src/fs.c
@@ -21,6 +21,9 @@
/**
* mnt_new_fs:
*
+ * The initial refcount is 1, and needs to be decremented to
+ * release the resources of the filesystem.
+ *
* Returns: newly allocated struct libmnt_fs.
*/
struct libmnt_fs *mnt_new_fs(void)
@@ -29,8 +32,9 @@ struct libmnt_fs *mnt_new_fs(void)
if (!fs)
return NULL;
- /*DBG(FS, mnt_debug_h(fs, "alloc"));*/
+ fs->refcount = 1;
INIT_LIST_HEAD(&fs->ents);
+ /*DBG(FS, mnt_debug_h(fs, "alloc"));*/
return fs;
}
@@ -38,7 +42,10 @@ struct libmnt_fs *mnt_new_fs(void)
* mnt_free_fs:
* @fs: fs pointer
*
- * Deallocates the fs.
+ * Deallocates the fs. This function does not care about reference count. Don't
+ * use this function directly -- it's better to use use mnt_unref_fs().
+ *
+ * The reference counting is supported since util-linux v2.24.
*/
void mnt_free_fs(struct libmnt_fs *fs)
{
@@ -47,6 +54,7 @@ void mnt_free_fs(struct libmnt_fs *fs)
list_del(&fs->ents);
/*DBG(FS, mnt_debug_h(fs, "free"));*/
+ WARN_REFCOUNT(FS, fs, fs->refcount);
free(fs->source);
free(fs->bindsrc);
@@ -62,6 +70,7 @@ void mnt_free_fs(struct libmnt_fs *fs)
free(fs->user_optstr);
free(fs->attrs);
free(fs->opt_fields);
+ free(fs->comment);
free(fs);
}
@@ -74,8 +83,46 @@ void mnt_free_fs(struct libmnt_fs *fs)
*/
void mnt_reset_fs(struct libmnt_fs *fs)
{
- if (fs)
- memset(fs, 0, sizeof(*fs));
+ int ref;
+
+ if (!fs)
+ return;
+
+ ref = fs->refcount;
+ memset(fs, 0, sizeof(*fs));
+ INIT_LIST_HEAD(&fs->ents);
+ fs->refcount = ref;
+}
+
+/**
+ * mnt_ref_fs:
+ * @fs: fs pointer
+ *
+ * Increments reference counter.
+ */
+void mnt_ref_fs(struct libmnt_fs *fs)
+{
+ if (fs) {
+ fs->refcount++;
+ /*DBG(FS, mnt_debug_h(fs, "ref=%d", fs->refcount));*/
+ }
+}
+
+/**
+ * mnt_unref_fs:
+ * @fs: fs pointer
+ *
+ * De-increments reference counter, on zero the @fs is automatically
+ * deallocated by mnt_free_fs().
+ */
+void mnt_unref_fs(struct libmnt_fs *fs)
+{
+ if (fs) {
+ fs->refcount--;
+ /*DBG(FS, mnt_debug_h(fs, "unref=%d", fs->refcount));*/
+ if (fs->refcount <= 0)
+ mnt_free_fs(fs);
+ }
}
static inline int update_str(char **dest, const char *src)
@@ -106,7 +153,7 @@ static inline int cpy_str_at_offset(void *new, const void *old, size_t offset)
char **n = (char **) (new + offset);
if (*n)
- return 0; /* already set, not overwrite */
+ return 0; /* already set, don't overwrite */
return update_str(n, *o);
}
@@ -117,7 +164,7 @@ static inline int cpy_str_at_offset(void *new, const void *old, size_t offset)
* @src: source FS
*
* If @dest is NULL, then a new FS is allocated, if any @dest field is already
- * set then the field is NOT overwrited.
+ * set, then the field is NOT overwritten.
*
* This function does not copy userdata (se mnt_fs_set_userdata()). A new copy is
* not linked with any existing mnt_tab.
@@ -250,7 +297,12 @@ err:
void *mnt_fs_get_userdata(struct libmnt_fs *fs)
{
assert(fs);
- return fs ? fs->userdata : NULL;
+
+ if (!fs)
+ return NULL;
+
+ /*DBG(FS, mnt_debug_h(fs, "get userdata [%p]", fs->userdata));*/
+ return fs->userdata;
}
/**
@@ -267,6 +319,8 @@ int mnt_fs_set_userdata(struct libmnt_fs *fs, void *data)
assert(fs);
if (!fs)
return -EINVAL;
+
+ /*DBG(FS, mnt_debug_h(fs, "set userdata [%p]", fs->userdata));*/
fs->userdata = data;
return 0;
}
@@ -310,7 +364,7 @@ const char *mnt_fs_get_source(struct libmnt_fs *fs)
}
/*
- * Used by parser ONLY (@source has to be freed on error)
+ * Used by the parser ONLY (@source has to be freed on error)
*/
int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source)
{
@@ -318,9 +372,12 @@ int __mnt_fs_set_source_ptr(struct libmnt_fs *fs, char *source)
assert(fs);
- if (source && *source != '/' && strchr(source, '=')) {
- if (blkid_parse_tag_string(source, &t, &v) != 0)
- return -1;
+ if (source && blkid_parse_tag_string(source, &t, &v) == 0 &&
+ !mnt_valid_tagname(t)) {
+ /* parsable but unknown tag -- ignore */
+ free(t);
+ free(v);
+ t = v = NULL;
}
if (fs->source != source)
@@ -370,7 +427,7 @@ int mnt_fs_set_source(struct libmnt_fs *fs, const char *source)
* @fs: fs
* @path: source path
*
- * Compares @fs source path with @path. The tailing slash is ignored.
+ * Compares @fs source path with @path. The trailing slash is ignored.
* See also mnt_fs_match_source().
*
* Returns: 1 if @fs source path equal to @path, otherwise 0.
@@ -399,7 +456,7 @@ int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
* @fs: fs
* @path: mount point
*
- * Compares @fs target path with @path. The tailing slash is ignored.
+ * Compares @fs target path with @path. The trailing slash is ignored.
* See also mnt_fs_match_target().
*
* Returns: 1 if @fs target path equal to @path, otherwise 0.
@@ -418,8 +475,8 @@ int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path)
*
* "TAG" is NAME=VALUE (e.g. LABEL=foo)
*
- * The TAG is the first column in the fstab file. The TAG or "srcpath" has to
- * be always set for all entries.
+ * The TAG is the first column in the fstab file. The TAG or "srcpath" always has
+ * to be set for all entries.
*
* See also mnt_fs_get_source().
*
@@ -441,7 +498,7 @@ int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path)
* </programlisting>
* </informalexample>
*
- * Returns: 0 on success or negative number in case that a TAG is not defined.
+ * Returns: 0 on success or negative number in case a TAG is not defined.
*/
int mnt_fs_get_tag(struct libmnt_fs *fs, const char **name, const char **value)
{
@@ -502,10 +559,10 @@ static int mnt_fs_get_flags(struct libmnt_fs *fs)
/**
* mnt_fs_get_propagation:
* @fs: mountinfo entry
- * @flags: returns propagation MS_* flags as present in mountinfo file
+ * @flags: returns propagation MS_* flags as present in the mountinfo file
*
- * Note that this function set @flags to zero if not found any propagation flag
- * in mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored
+ * Note that this function sets @flags to zero if no propagation flags are found
+ * in the mountinfo file. The kernel default is MS_PRIVATE, this flag is not stored
* in the mountinfo file.
*
* Returns: 0 on success or negative number in case of error.
@@ -594,7 +651,7 @@ const char *mnt_fs_get_fstype(struct libmnt_fs *fs)
return fs ? fs->fstype : NULL;
}
-/* Used by struct libmnt_file parser only */
+/* Used by the struct libmnt_file parser only */
int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype)
{
assert(fs);
@@ -670,7 +727,7 @@ static char *merge_optstr(const char *vfs, const char *fs)
if (!strcmp(vfs, fs))
return strdup(vfs); /* e.g. "aaa" and "aaa" */
- /* leave space for leading "r[ow],", "," and trailing zero */
+ /* leave space for the leading "r[ow],", "," and the trailing zero */
sz = strlen(vfs) + strlen(fs) + 5;
res = malloc(sz);
if (!res)
@@ -701,7 +758,7 @@ static char *merge_optstr(const char *vfs, const char *fs)
* mnt_fs_strdup_options:
* @fs: fstab/mtab/mountinfo entry pointer
*
- * Merges all mount options (VFS, FS and userspace) to the one options string
+ * Merges all mount options (VFS, FS and userspace) to one options string
* and returns the result. This function does not modigy @fs.
*
* Returns: pointer to string (can be freed by free(3)) or NULL in case of error.
@@ -757,10 +814,10 @@ const char *mnt_fs_get_optional_fields(struct libmnt_fs *fs)
* @fs: fstab/mtab/mountinfo entry pointer
* @optstr: options string
*
- * Splits @optstr to VFS, FS and userspace mount options and update relevat
+ * Splits @optstr to VFS, FS and userspace mount options and updates relevant
* parts of @fs.
*
- * Returns: 0 on success, or negative number icase of error.
+ * Returns: 0 on success, or negative number in case of error.
*/
int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr)
{
@@ -774,8 +831,12 @@ int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr)
if (rc)
return rc;
n = strdup(optstr);
- if (!n)
+ if (!n) {
+ free(u);
+ free(v);
+ free(f);
return -ENOMEM;
+ }
}
free(fs->fs_optstr);
@@ -799,7 +860,7 @@ int mnt_fs_set_options(struct libmnt_fs *fs, const char *optstr)
* Parses (splits) @optstr and appends results to VFS, FS and userspace lists
* of options.
*
- * If @optstr is NULL then @fs is not modified and 0 is returned.
+ * If @optstr is NULL, then @fs is not modified and 0 is returned.
*
* Returns: 0 on success or negative number in case of error.
*/
@@ -815,6 +876,9 @@ int mnt_fs_append_options(struct libmnt_fs *fs, const char *optstr)
return 0;
rc = mnt_split_optstr((char *) optstr, &u, &v, &f, 0, 0);
+ if (rc)
+ return rc;
+
if (!rc && v)
rc = mnt_optstr_append_option(&fs->vfs_optstr, v, NULL);
if (!rc && f)
@@ -836,10 +900,10 @@ int mnt_fs_append_options(struct libmnt_fs *fs, const char *optstr)
* @fs: fstab/mtab/mountinfo entry
* @optstr: mount options
*
- * Parses (splits) @optstr and prepands results to VFS, FS and userspace lists
+ * Parses (splits) @optstr and prepends the results to VFS, FS and userspace lists
* of options.
*
- * If @optstr is NULL then @fs is not modified and 0 is returned.
+ * If @optstr is NULL, then @fs is not modified and 0 is returned.
*
* Returns: 0 on success or negative number in case of error.
*/
@@ -855,6 +919,9 @@ int mnt_fs_prepend_options(struct libmnt_fs *fs, const char *optstr)
return 0;
rc = mnt_split_optstr((char *) optstr, &u, &v, &f, 0, 0);
+ if (rc)
+ return rc;
+
if (!rc && v)
rc = mnt_optstr_prepend_option(&fs->vfs_optstr, v, NULL);
if (!rc && f)
@@ -925,10 +992,10 @@ const char *mnt_fs_get_attributes(struct libmnt_fs *fs)
* @optstr: options string
*
* Sets mount attributes. The attributes are mount(2) and mount(8) independent
- * options, these options are not send to kernel and are not interpreted by
+ * options, these options are not sent to the kernel and are not interpreted by
* libmount. The attributes are stored in /run/mount/utab only.
*
- * The atrtributes are managed by libmount in userspace only. It's possible
+ * The attributes are managed by libmount in userspace only. It's possible
* that information stored in userspace will not be available for libmount
* after CLONE_FS unshare. Be careful, and don't use attributes if possible.
*
@@ -1221,7 +1288,7 @@ dev_t mnt_fs_get_devno(struct libmnt_fs *fs)
* mnt_fs_get_tid:
* @fs: /proc/tid/mountinfo entry
*
- * Returns: TID (task ID) for filesystems read from mountinfo file
+ * Returns: TID (task ID) for filesystems read from the mountinfo file
*/
pid_t mnt_fs_get_tid(struct libmnt_fs *fs)
{
@@ -1233,10 +1300,10 @@ pid_t mnt_fs_get_tid(struct libmnt_fs *fs)
* mnt_fs_get_option:
* @fs: fstab/mtab/mountinfo entry pointer
* @name: option name
- * @value: returns pointer to the begin of the value (e.g. name=VALUE) or NULL
+ * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
* @valsz: returns size of options value or 0
*
- * Returns: 0 on success, 1 when not found the @name or negative number in case of error.
+ * Returns: 0 on success, 1 when @name not found or negative number in case of error.
*/
int mnt_fs_get_option(struct libmnt_fs *fs, const char *name,
char **value, size_t *valsz)
@@ -1259,10 +1326,10 @@ int mnt_fs_get_option(struct libmnt_fs *fs, const char *name,
* mnt_fs_get_attribute:
* @fs: fstab/mtab/mountinfo entry pointer
* @name: option name
- * @value: returns pointer to the begin of the value (e.g. name=VALUE) or NULL
+ * @value: returns pointer to the beginning of the value (e.g. name=VALUE) or NULL
* @valsz: returns size of options value or 0
*
- * Returns: 0 on success, 1 when not found the @name or negative number in case of error.
+ * Returns: 0 on success, 1 when @name not found or negative number in case of error.
*/
int mnt_fs_get_attribute(struct libmnt_fs *fs, const char *name,
char **value, size_t *valsz)
@@ -1278,6 +1345,67 @@ int mnt_fs_get_attribute(struct libmnt_fs *fs, const char *name,
}
/**
+ * mnt_fs_get_comment:
+ * @fs: fstab/mtab/mountinfo entry pointer
+ *
+ * Returns: 0 on success, 1 when not found the @name or negative number in case of error.
+ */
+const char *mnt_fs_get_comment(struct libmnt_fs *fs)
+{
+ assert(fs);
+ if (!fs)
+ return NULL;
+ return fs->comment;
+}
+
+/**
+ * mnt_fs_set_comment:
+ * @fs: fstab entry pointer
+ * @comm: comment string
+ *
+ * Note that the comment has to be terminated by '\n' (new line), otherwise
+ * the whole filesystem entry will be written as a comment to the tabfile (e.g.
+ * fstab).
+ *
+ * Returns: 0 on success or <0 in case of error.
+ */
+int mnt_fs_set_comment(struct libmnt_fs *fs, const char *comm)
+{
+ char *p = NULL;
+
+ assert(fs);
+ if (!fs)
+ return -EINVAL;
+ if (comm) {
+ p = strdup(comm);
+ if (!p)
+ return -ENOMEM;
+ }
+
+ free(fs->comment);
+ fs->comment = p;
+ return 0;
+}
+
+/**
+ * mnt_fs_append_comment:
+ * @fs: fstab entry pointer
+ * @comm: comment string
+ *
+ * See also mnt_fs_set_comment().
+ *
+ * Returns: 0 on success or <0 in case of error.
+ */
+int mnt_fs_append_comment(struct libmnt_fs *fs, const char *comm)
+{
+ assert(fs);
+ if (!fs)
+ return -EINVAL;
+
+ return append_string(&fs->comment, comm);
+}
+
+/**
* mnt_fs_match_target:
* @fs: filesystem
* @target: mountpoint path
@@ -1291,7 +1419,7 @@ int mnt_fs_get_attribute(struct libmnt_fs *fs, const char *name,
*
* The 2nd and 3rd attempts are not performed when @cache is NULL.
*
- * Returns: 1 if @fs target is equal to @target else 0.
+ * Returns: 1 if @fs target is equal to @target, else 0.
*/
int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
struct libmnt_cache *cache)
@@ -1326,7 +1454,7 @@ int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
* @source: tag or path (device or so) or NULL
* @cache: tags/paths cache or NULL
*
- * Possible are four attempts:
+ * Four attempts are possible:
* 1) compare @source with @fs->source
* 2) compare realpath(@source) with @fs->source
* 3) compare realpath(@source) with realpath(@fs->source)
@@ -1335,7 +1463,7 @@ int mnt_fs_match_target(struct libmnt_fs *fs, const char *target,
* The 2nd, 3rd and 4th attempts are not performed when @cache is NULL. The
* 2nd and 3rd attempts are not performed if @fs->source is tag.
*
- * Returns: 1 if @fs source is equal to @source else 0.
+ * Returns: 1 if @fs source is equal to @source, else 0.
*/
int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
struct libmnt_cache *cache)
@@ -1379,14 +1507,14 @@ int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
return 1;
}
if (src || mnt_fs_get_tag(fs, &t, &v))
- /* src path does not match and tag is not defined */
+ /* src path does not match and the tag is not defined */
return 0;
/* read @source's tags to the cache */
if (mnt_cache_read_tags(cache, cn) < 0) {
if (errno == EACCES) {
/* we don't have permissions to read TAGs from
- * @source, but can translate @fs tag to devname.
+ * @source, but can translate the @fs tag to devname.
*
* (because libblkid uses udev symlinks and this is
* accessible for non-root uses)
@@ -1398,7 +1526,7 @@ int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
return 0;
}
- /* 4) has the @source a tag that matches with tag from @fs ? */
+ /* 4) has the @source a tag that matches with the tag from @fs ? */
if (mnt_cache_device_has_tag(cache, cn, t, v))
return 1;
@@ -1412,7 +1540,7 @@ int mnt_fs_match_source(struct libmnt_fs *fs, const char *source,
*
* For more details see mnt_match_fstype().
*
- * Returns: 1 if @fs type is matching to @types else 0. The function returns
+ * Returns: 1 if @fs type is matching to @types, else 0. The function returns
* 0 when types is NULL.
*/
int mnt_fs_match_fstype(struct libmnt_fs *fs, const char *types)
@@ -1428,7 +1556,7 @@ int mnt_fs_match_fstype(struct libmnt_fs *fs, const char *types)
*
* For more details see mnt_match_options().
*
- * Returns: 1 if @fs type is matching to @options else 0. The function returns
+ * Returns: 1 if @fs type is matching to @options, else 0. The function returns
* 0 when types is NULL.
*/
int mnt_fs_match_options(struct libmnt_fs *fs, const char *options)
@@ -1493,6 +1621,8 @@ int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file)
minor(mnt_fs_get_devno(fs)));
if (mnt_fs_get_tid(fs))
fprintf(file, "tid: %d\n", mnt_fs_get_tid(fs));
+ if (mnt_fs_get_comment(fs))
+ fprintf(file, "comment: '%s'\n", mnt_fs_get_comment(fs));
return 0;
}
@@ -1501,7 +1631,7 @@ int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file)
* mnt_free_mntent:
* @mnt: mount entry
*
- * Deallocates "mntent.h" mount entry.
+ * Deallocates the "mntent.h" mount entry.
*/
void mnt_free_mntent(struct mntent *mnt)
{
@@ -1519,11 +1649,11 @@ void mnt_free_mntent(struct mntent *mnt)
* @fs: filesystem
* @mnt: mount description (as described in mntent.h)
*
- * Copies information from @fs to struct mntent @mnt. If @mnt is already set
+ * Copies the information from @fs to struct mntent @mnt. If @mnt is already set,
* then the struct mntent items are reallocated and updated. See also
* mnt_free_mntent().
*
- * Returns: 0 on success and negative number in case of error.
+ * Returns: 0 on success and a negative number in case of error.
*/
int mnt_fs_to_mntent(struct libmnt_fs *fs, struct mntent **mnt)
{