static int lofs_mount(am_node *am, mntfs *mf) { int on_autofs = mf->mf_flags & MFF_ON_AUTOFS; int error; error = mount_lofs(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs); if (error) { errno = error; plog(XLOG_ERROR, "mount_lofs: %m"); return error; } return 0; }
int autofs_mount_fs(am_node *mp, mntfs *mf) { char *target, *target2 = NULL; int err = 0; if (mf->mf_flags & MFF_ON_AUTOFS) { if ((err = mkdir(mp->am_path, 0555))) return errno; } /* * For sublinks, we could end up here with an already mounted f/s. * Don't do anything in that case. */ if (!(mf->mf_flags & MFF_MOUNTED)) err = mf->mf_ops->mount_fs(mp, mf); if (err) { if (mf->mf_flags & MFF_ON_AUTOFS) rmdir(mp->am_path); return err; } if (mf->mf_flags & MFF_ON_AUTOFS) /* Nothing else to do */ return 0; if (mp->am_link) target = mp->am_link; else target = mf->mf_fo->opt_fs; #ifdef MNT2_GEN_OPT_BIND if (bind_works && gopt.flags & CFM_AUTOFS_USE_LOFS) { struct stat buf; /* * HACK ALERT! * * Since the bind mount mechanism doesn't allow mountpoint crossing, * we _must_ use symlinks for the host mount case. Otherwise we end up * with a bunch of empty mountpoints... */ if (mf->mf_ops == &amfs_host_ops) goto use_symlink; if (target[0] != '/') target2 = str3cat(NULL, mp->am_parent->am_path, "/", target); else target2 = strdup(target); /* * We need to stat() the destination, because the bind mount does not * follow symlinks and/or allow for non-existent destinations. * We fall back to symlinks if there are problems. * * We also need to temporarily change pgrp, otherwise our stat() won't * trigger whatever cascading mounts are needed. * * WARNING: we will deadlock if this function is called from the master * amd process and it happens to trigger another auto mount. Therefore, * this function should be called only from a child amd process, or * at the very least it should not be called from the parent unless we * know for sure that it won't cause a recursive mount. We refuse to * cause the recursive mount anyway if called from the parent amd. */ if (!foreground) { pid_t pgrp = getpgrp(); setpgrp(); err = stat(target2, &buf); if ((err = setpgid(0, pgrp))) { plog(XLOG_ERROR, "autofs: cannot restore pgrp: %s", strerror(errno)); plog(XLOG_ERROR, "autofs: aborting the mount"); goto out; } if (err) goto use_symlink; } if ((err = lstat(target2, &buf))) goto use_symlink; if (S_ISLNK(buf.st_mode)) goto use_symlink; plog(XLOG_INFO, "autofs: bind-mounting %s -> %s", mp->am_path, target2); mkdir(mp->am_path, 0555); err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1); if (err) { rmdir(mp->am_path); plog(XLOG_INFO, "autofs: bind-mounting %s -> %s failed", mp->am_path, target2); goto use_symlink; } goto out; } #endif /* MNT2_GEN_OPT_BIND */ use_symlink: plog(XLOG_INFO, "autofs: symlinking %s -> %s", mp->am_path, target); err = symlink(target, mp->am_path); out: if (target2) XFREE(target2); if (err) return errno; return 0; }
int autofs_mount_fs(am_node *mp, mntfs *mf) { int err = 0; char *target, *target2 = NULL; char *space_hack = autofs_strdup_space_hack(mp->am_path); struct stat buf; if (mf->mf_flags & MFF_ON_AUTOFS) { if ((err = mkdir(space_hack, 0555))) goto out; } /* * For sublinks, we could end up here with an already mounted f/s. * Don't do anything in that case. */ if (!(mf->mf_flags & MFF_MOUNTED)) err = mf->mf_ops->mount_fs(mp, mf); if (err) { if (mf->mf_flags & MFF_ON_AUTOFS) rmdir(space_hack); errno = err; goto out; } /* * Autofs v1 doesn't support symlinks, * so we ignore the CFM_AUTOFS_USE_LOFS flag */ if (mf->mf_flags & MFF_ON_AUTOFS) /* Nothing to do */ goto out; if (mp->am_link) target = mp->am_link; else target = mf->mf_mount; if (target[0] != '/') target2 = str3cat(NULL, mp->am_parent->am_path, "/", target); else target2 = xstrdup(target); plog(XLOG_INFO, "autofs: converting from link to lofs (%s -> %s)", mp->am_path, target2); /* * we need to stat() the destination, because the bind mount does not * follow symlinks and/or allow for non-existent destinations. * * WARNING: we will deadlock if this function is called from the master * amd process and it happens to trigger another auto mount. Therefore, * this function should be called only from a child amd process, or * at the very least it should not be called from the parent unless we * know for sure that it won't cause a recursive mount. We refuse to * cause the recursive mount anyway if called from the parent amd. */ if (!foreground) { if ((err = stat(target2, &buf))) goto out; } if ((err = lstat(target2, &buf))) goto out; if ((err = mkdir(space_hack, 0555))) goto out; if ((err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1))) { errno = err; goto out; } out: XFREE(space_hack); if (target2) XFREE(target2); if (err) return errno; return 0; }