/** * Create an empty directory and bind mount something there. * * The empty directory is created at destdir. The bind mount is * done from srcdir to destdir. The bind mount is performed with * caller-defined flags. **/ static void sc_quirk_mkdir_bind(const char *src_dir, const char *dest_dir, unsigned flags) { flags |= MS_BIND; debug("creating empty directory at %s", dest_dir); if (sc_nonfatal_mkpath(dest_dir, 0755) < 0) { die("cannot create empty directory at %s", dest_dir); } const char *flags_str = sc_mount_opt2str(flags); debug("performing operation: mount %s %s -o %s", src_dir, dest_dir, flags_str); if (mount(src_dir, dest_dir, NULL, flags, NULL) != 0) { die("cannot perform operation: mount %s %s -o %s", src_dir, dest_dir, flags_str); } }
* GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ #include "mount-opt.h" #include "mount-opt.c" #include <sys/mount.h> #include <glib.h> static void test_sc_mount_opt2str() { g_assert_cmpstr(sc_mount_opt2str(0), ==, ""); g_assert_cmpstr(sc_mount_opt2str(MS_RDONLY), ==, "ro"); g_assert_cmpstr(sc_mount_opt2str(MS_NOSUID), ==, "nosuid"); g_assert_cmpstr(sc_mount_opt2str(MS_NODEV), ==, "nodev"); g_assert_cmpstr(sc_mount_opt2str(MS_NOEXEC), ==, "noexec"); g_assert_cmpstr(sc_mount_opt2str(MS_SYNCHRONOUS), ==, "sync"); g_assert_cmpstr(sc_mount_opt2str(MS_REMOUNT), ==, "remount"); g_assert_cmpstr(sc_mount_opt2str(MS_MANDLOCK), ==, "mand"); g_assert_cmpstr(sc_mount_opt2str(MS_DIRSYNC), ==, "dirsync"); g_assert_cmpstr(sc_mount_opt2str(MS_NOATIME), ==, "noatime"); g_assert_cmpstr(sc_mount_opt2str(MS_NODIRATIME), ==, "nodiratime"); g_assert_cmpstr(sc_mount_opt2str(MS_BIND), ==, "bind"); g_assert_cmpstr(sc_mount_opt2str(MS_REC | MS_BIND), ==, "rbind"); g_assert_cmpstr(sc_mount_opt2str(MS_MOVE), ==, "move"); g_assert_cmpstr(sc_mount_opt2str(MS_SILENT), ==, "silent"); g_assert_cmpstr(sc_mount_opt2str(MS_POSIXACL), ==, "acl");
const char *sc_mount_cmd(char *buf, size_t buf_size, const char *source, const char *target, const char *fs_type, unsigned long mountflags, const void *data) { sc_string_init(buf, buf_size); sc_string_append(buf, buf_size, "mount"); // Add filesysystem type if it's there and doesn't have the special value "none" if (fs_type != NULL && strncmp(fs_type, "none", 5) != 0) { sc_string_append(buf, buf_size, " -t "); sc_string_append(buf, buf_size, fs_type); } // Check for some special, dedicated options, that aren't represented with // the generic mount option argument (mount -o ...), by collecting those // options that we will display as command line arguments in // used_special_flags. This is used below to filter out these arguments // from mount_flags when calling sc_mount_opt2str(). int used_special_flags = 0; // Bind-ounts (bind) if (mountflags & MS_BIND) { if (mountflags & MS_REC) { sc_string_append(buf, buf_size, " --rbind"); used_special_flags |= MS_REC; } else { sc_string_append(buf, buf_size, " --bind"); } used_special_flags |= MS_BIND; } // Moving mount point location (move) if (mountflags & MS_MOVE) { sc_string_append(buf, buf_size, " --move"); used_special_flags |= MS_MOVE; } // Shared subtree operations (shared, slave, private, unbindable). if (MS_SHARED & mountflags) { if (mountflags & MS_REC) { sc_string_append(buf, buf_size, " --make-rshared"); used_special_flags |= MS_REC; } else { sc_string_append(buf, buf_size, " --make-shared"); } used_special_flags |= MS_SHARED; } if (MS_SLAVE & mountflags) { if (mountflags & MS_REC) { sc_string_append(buf, buf_size, " --make-rslave"); used_special_flags |= MS_REC; } else { sc_string_append(buf, buf_size, " --make-slave"); } used_special_flags |= MS_SLAVE; } if (MS_PRIVATE & mountflags) { if (mountflags & MS_REC) { sc_string_append(buf, buf_size, " --make-rprivate"); used_special_flags |= MS_REC; } else { sc_string_append(buf, buf_size, " --make-private"); } used_special_flags |= MS_PRIVATE; } if (MS_UNBINDABLE & mountflags) { if (mountflags & MS_REC) { sc_string_append(buf, buf_size, " --make-runbindable"); used_special_flags |= MS_REC; } else { sc_string_append(buf, buf_size, " --make-unbindable"); } used_special_flags |= MS_UNBINDABLE; } // If regular option syntax exists then use it. if (mountflags & ~used_special_flags) { char opts_buf[1000] = { 0 }; sc_mount_opt2str(opts_buf, sizeof opts_buf, mountflags & ~used_special_flags); sc_string_append(buf, buf_size, " -o "); sc_string_append(buf, buf_size, opts_buf); } // Add source and target locations if (source != NULL && strncmp(source, "none", 5) != 0) { sc_string_append(buf, buf_size, " "); sc_string_append(buf, buf_size, source); } if (target != NULL && strncmp(target, "none", 5) != 0) { sc_string_append(buf, buf_size, " "); sc_string_append(buf, buf_size, target); } return buf; }