Exemplo n.º 1
0
static int
path_is_on_readonly_fs (char *path)
{
  struct statvfs stvfsbuf;

  if (statvfs (path, &stvfsbuf) == -1)
    {
      perrorv ("statvfs(%s): ", path);
      exit (1);
    }

  return (stvfsbuf.f_flag & ST_RDONLY) != 0;
}
Exemplo n.º 2
0
int
main(int argc, char *argv[])
{
  const char *remounts[] = { "/sysroot", "/etc", "/home", "/root", "/tmp", "/var", NULL };
  struct stat stbuf;
  int i;

  if (path_is_on_readonly_fs ("/"))
    {
      /* If / isn't writable, don't do any remounts; we don't want
       * to clear the readonly flag in that case.
       */

      maybe_mount_tmpfs_on_var ();

      exit (0);
    }

  for (i = 0; remounts[i] != NULL; i++)
    {
      const char *target = remounts[i];
      if (lstat (target, &stbuf) < 0)
        continue;
      /* Silently ignore symbolic links; we expect these to point to
       * /sysroot, and thus there isn't a bind mount there.
       */
      if (S_ISLNK (stbuf.st_mode))
        continue;
      if (mount (target, target, NULL, MS_REMOUNT | MS_SILENT, NULL) < 0)
	{
          /* Also ignore ENINVAL - if the target isn't a mountpoint
           * already, then assume things are OK.
           */
          if (errno != EINVAL)
            {
              perrorv ("failed to remount %s", target);
              exit (1);
            }
	}
    }

  maybe_mount_tmpfs_on_var ();

  exit (0);
}
Exemplo n.º 3
0
int
main(int argc, char *argv[])
{
  const char *readonly_bind_mounts[] = { "/usr", NULL };
  const char *root_mountpoint = NULL;
  char *ostree_target = NULL;
  char *deploy_path = NULL;
  char srcpath[PATH_MAX];
  char destpath[PATH_MAX];
  struct stat stbuf;
  int i;

  if (argc < 2)
    {
      fprintf (stderr, "usage: ostree-prepare-root SYSROOT\n");
      exit (1);
    }

  root_mountpoint = argv[1];

  ostree_target = parse_ostree_cmdline ();
  if (!ostree_target)
    {
      fprintf (stderr, "No OSTree target; expected ostree=/ostree/boot.N/...\n");
      exit (1);
    }

  snprintf (destpath, sizeof(destpath), "%s/%s", root_mountpoint, ostree_target);
  fprintf (stderr, "Examining %s\n", destpath);
  if (lstat (destpath, &stbuf) < 0)
    {
      perrorv ("Couldn't find specified OSTree root '%s': ", destpath);
      exit (1);
    }
  if (!S_ISLNK (stbuf.st_mode))
    {
      fprintf (stderr, "OSTree target is not a symbolic link: %s\n", destpath);
      exit (1);
    }
  deploy_path = realpath (destpath, NULL);
  if (deploy_path == NULL)
    {
      perrorv ("realpath(%s) failed: ", destpath);
      exit (1);
    }
  fprintf (stderr, "Resolved OSTree target to: %s\n", deploy_path);
  
  /* Work-around for a kernel bug: for some reason the kernel
   * refuses switching root if any file systems are mounted
   * MS_SHARED. Hence remount them MS_PRIVATE here as a
   * work-around.
   *
   * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
  if (mount (NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
    {
      perrorv ("Failed to make \"/\" private mount: %m");
      exit (1);
    }

  /* Make deploy_path a bind mount, so we can move it later */
  if (mount (deploy_path, deploy_path, NULL, MS_BIND, NULL) < 0)
    {
      perrorv ("failed to initial bind mount %s", deploy_path);
      exit (1);
    }

  snprintf (destpath, sizeof(destpath), "%s/sysroot", deploy_path);
  if (mount (root_mountpoint, destpath, NULL, MS_BIND, NULL) < 0)
    {
      perrorv ("Failed to bind mount %s to '%s'", root_mountpoint, destpath);
      exit (1);
    }

  snprintf (srcpath, sizeof(srcpath), "%s/../../var", deploy_path);
  snprintf (destpath, sizeof(destpath), "%s/var", deploy_path);
  if (mount (srcpath, destpath, NULL, MS_MGC_VAL|MS_BIND, NULL) < 0)
    {
      perrorv ("failed to bind mount %s to %s", srcpath, destpath);
      exit (1);
    }

  for (i = 0; readonly_bind_mounts[i] != NULL; i++)
    {
      snprintf (destpath, sizeof(destpath), "%s%s", deploy_path, readonly_bind_mounts[i]);
      if (mount (destpath, destpath, NULL, MS_BIND, NULL) < 0)
	{
	  perrorv ("failed to bind mount (class:readonly) %s", destpath);
	  exit (1);
	}
      if (mount (destpath, destpath, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
	{
	  perrorv ("failed to bind mount (class:readonly) %s", destpath);
	  exit (1);
	}
    }

  /* This is a bit hacky - move our deployment to /sysroot, since
   * systemd's initrd-switch-root target hardcodes looking for it
   * there.
   */
  if (mount (deploy_path, root_mountpoint, NULL, MS_MOVE, NULL) < 0)
    {
      perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint);
      exit (1);
    }
  
  exit (0);
}