bind_mount_recursive: Use lstat instead of d_type of readdir

Change-Id: I0eb8d6c7e1fa5df6dbc5962a639901546a159d04
This commit is contained in:
Masamichi Takagi
2018-07-24 09:43:17 +09:00
parent f01a883971
commit 6999d0a3f9

View File

@ -1782,51 +1782,75 @@ static struct option mcexec_options[] = {
};
#ifdef ENABLE_MCOVERLAYFS
/* bind-mount files under <root>/<prefix> over <prefix> recursively */
void bind_mount_recursive(const char *root, char *prefix)
{
DIR *dir;
struct dirent *entry;
char path[PATH_MAX];
int len;
len = snprintf(path, sizeof(path) - 1, "%s/%s", root, prefix);
path[len] = 0;
snprintf(path, sizeof(path), "%s/%s", root, prefix);
path[sizeof(path) - 1] = 0;
if (!(dir = opendir(path))) {
return;
}
while ((entry = readdir(dir))) {
len = snprintf(path, sizeof(path) - 1,
"%s/%s", prefix, entry->d_name);
path[len] = 0;
char fullpath[PATH_MAX];
char shortpath[PATH_MAX];
struct stat st;
/* Use lstat instead of checking dt_type of readdir
result because the latter reports DT_UNKNOWN for
files on some file systems */
snprintf(fullpath, sizeof(fullpath),
"%s/%s/%s", root, prefix, entry->d_name);
fullpath[sizeof(fullpath) - 1] = 0;
if (lstat(fullpath, &st)) {
fprintf(stderr, "%s: error: lstat %s: %s\n",
__func__, fullpath, strerror(errno));
continue;
}
/* Traverse target or mount point */
snprintf(shortpath, sizeof(shortpath),
"%s/%s", prefix, entry->d_name);
shortpath[sizeof(shortpath) - 1] = 0;
if (S_ISDIR(st.st_mode)) {
__dprintf("dir found: %s\n", fullpath);
if (entry->d_type == DT_DIR) {
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0)
continue;
bind_mount_recursive(root, path);
bind_mount_recursive(root, shortpath);
}
else if (entry->d_type == DT_REG) {
else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
int ret;
struct sys_mount_desc mount_desc;
memset(&mount_desc, '\0', sizeof mount_desc);
char bind_path[PATH_MAX];
len = snprintf(bind_path, sizeof(bind_path) - 1,
"%s/%s/%s", root, prefix, entry->d_name);
bind_path[len] = 0;
__dprintf("reg/symlink found: %s\n", fullpath);
mount_desc.dev_name = bind_path;
mount_desc.dir_name = path;
if (lstat(shortpath, &st)) {
fprintf(stderr, "%s: warning: lstat of mount point (%s) failed: %s\n",
__func__, shortpath, strerror(errno));
continue;
}
memset(&mount_desc, '\0', sizeof(mount_desc));
mount_desc.dev_name = fullpath;
mount_desc.dir_name = shortpath;
mount_desc.type = NULL;
mount_desc.flags = MS_BIND | MS_PRIVATE;
mount_desc.data = NULL;
if ((ret = ioctl(fd, MCEXEC_UP_SYS_MOUNT,
(unsigned long)&mount_desc)) != 0) {
fprintf(stderr, "WARNING: failed to bind mount %s over %s: %d\n",
bind_path, path, ret);
fprintf(stderr, "%s: warning: failed to bind mount %s over %s: %d\n",
__func__, fullpath, shortpath, ret);
}
}
}