static gboolean
update_current (const char         *deploy_target,
                GCancellable       *cancellable,
                GError            **error)
{
  gboolean ret = FALSE;
  ot_lfree char *tmp_symlink = NULL;
  ot_lfree char *current_name = NULL;

  tmp_symlink = g_build_filename (opt_ostree_dir, "tmp-current", NULL);
  (void) unlink (tmp_symlink);

  if (symlink (deploy_target, tmp_symlink) < 0)
    {
      ot_util_set_error_from_errno (error, errno);
      goto out;
    }

  current_name = g_build_filename (opt_ostree_dir, "current", NULL);
  if (rename (tmp_symlink, current_name) < 0)
    {
      ot_util_set_error_from_errno (error, errno);
      goto out;
    }

  g_print ("%s set to %s\n", current_name, deploy_target);

  ret = TRUE;
 out:
  return ret;
}
Exemple #2
0
gboolean
ostree_get_xattrs_for_file (GFile         *f,
                            GVariant     **out_xattrs,
                            GCancellable  *cancellable,
                            GError       **error)
{
  gboolean ret = FALSE;
  const char *path;
  ssize_t bytes_read;
  ot_lvariant GVariant *ret_xattrs = NULL;
  ot_lfree char *xattr_names = NULL;
  ot_lfree char *xattr_names_canonical = NULL;
  GVariantBuilder builder;
  gboolean builder_initialized = FALSE;

  path = ot_gfile_get_path_cached (f);

  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)"));
  builder_initialized = TRUE;

  bytes_read = llistxattr (path, NULL, 0);

  if (bytes_read < 0)
    {
      if (errno != ENOTSUP)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
    }
  else if (bytes_read > 0)
    {
      xattr_names = g_malloc (bytes_read);
      if (llistxattr (path, xattr_names, bytes_read) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
      xattr_names_canonical = canonicalize_xattrs (xattr_names, bytes_read);
      
      if (!read_xattr_name_array (path, xattr_names_canonical, bytes_read, &builder, error))
        goto out;
    }

  ret_xattrs = g_variant_builder_end (&builder);
  g_variant_ref_sink (ret_xattrs);
  
  ret = TRUE;
  ot_transfer_out_value (out_xattrs, &ret_xattrs);
 out:
  if (!builder_initialized)
    g_variant_builder_clear (&builder);
  return ret;
}
Exemple #3
0
static gboolean
read_xattr_name_array (const char *path,
                       const char *xattrs,
                       size_t      len,
                       GVariantBuilder *builder,
                       GError  **error)
{
  gboolean ret = FALSE;
  const char *p;

  p = xattrs;
  while (p < xattrs+len)
    {
      ssize_t bytes_read;
      char *buf;

      bytes_read = lgetxattr (path, p, NULL, 0);
      if (bytes_read < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
      if (bytes_read == 0)
        continue;

      buf = g_malloc (bytes_read);
      if (lgetxattr (path, p, buf, bytes_read) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          g_free (buf);
          goto out;
        }
      
      g_variant_builder_add (builder, "(@ay@ay)",
                             g_variant_new_bytestring (p),
                             g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
                                                      buf, bytes_read, FALSE, g_free, buf));

      p = p + strlen (p) + 1;
    }
  
  ret = TRUE;
 out:
  return ret;
}
Exemple #4
0
/**
 * ot_gfile_unlink:
 * @path: Path to file
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * Like g_file_delete(), except this function does not follow Unix
 * symbolic links, and will delete a symbolic link even if it's
 * pointing to a nonexistent file.  In other words, this function
 * merely wraps the raw Unix function unlink().
 *
 * Returns: %TRUE on success, %FALSE on error
 */
gboolean
ot_gfile_unlink (GFile          *path,
                 GCancellable   *cancellable,
                 GError        **error)
{
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  if (unlink (ot_gfile_get_path_cached (path)) < 0)
    {
      ot_util_set_error_from_errno (error, errno);
      return FALSE;
    }
  return TRUE;
}
Exemple #5
0
/**
 * ot_gfile_rename:
 * @from: Current path
 * @to: New path
 * @cancellable: a #GCancellable
 * @error: a #GError
 *
 * This function wraps the raw Unix function rename().
 *
 * Returns: %TRUE on success, %FALSE on error
 */
gboolean
ot_gfile_rename (GFile          *from,
                 GFile          *to,
                 GCancellable   *cancellable,
                 GError        **error)
{
  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  if (rename (ot_gfile_get_path_cached (from),
              ot_gfile_get_path_cached (to)) < 0)
    {
      ot_util_set_error_from_errno (error, errno);
      return FALSE;
    }
  return TRUE;

}
Exemple #6
0
gboolean
ostree_content_file_parse (gboolean                compressed,
                           GFile                  *content_path,
                           gboolean                trusted,
                           GInputStream          **out_input,
                           GFileInfo             **out_file_info,
                           GVariant              **out_xattrs,
                           GCancellable           *cancellable,
                           GError                **error)
{
  gboolean ret = FALSE;
  guint64 length;
  struct stat stbuf;
  ot_lobj GInputStream *file_input = NULL;
  ot_lobj GInputStream *ret_input = NULL;
  ot_lobj GFileInfo *content_file_info = NULL;
  ot_lobj GFileInfo *ret_file_info = NULL;
  ot_lvariant GVariant *ret_xattrs = NULL;

  file_input = (GInputStream*)gs_file_read_noatime (content_path, cancellable, error);
  if (!file_input)
    goto out;

  if (fstat (g_file_descriptor_based_get_fd ((GFileDescriptorBased*)file_input), &stbuf) < 0)
    {
      ot_util_set_error_from_errno (error, errno);
      goto out;
    }

  length = stbuf.st_size;

  if (!ostree_content_stream_parse (compressed, file_input, length, trusted,
                                    out_input ? &ret_input : NULL,
                                    &ret_file_info, &ret_xattrs,
                                    cancellable, error))
    goto out;

  ret = TRUE;
  ot_transfer_out_value (out_input, &ret_input);
  ot_transfer_out_value (out_file_info, &ret_file_info);
  ot_transfer_out_value (out_xattrs, &ret_xattrs);
 out:
  return ret;
}
Exemple #7
0
gboolean
ostree_set_xattrs (GFile  *f, 
                   GVariant *xattrs, 
                   GCancellable *cancellable, 
                   GError **error)
{
  const char *path;
  gboolean ret = FALSE;
  int i, n;

  path = ot_gfile_get_path_cached (f);

  n = g_variant_n_children (xattrs);
  for (i = 0; i < n; i++)
    {
      const guint8* name;
      GVariant *value;
      const guint8* value_data;
      gsize value_len;
      gboolean loop_err;

      g_variant_get_child (xattrs, i, "(^&ay@ay)",
                           &name, &value);
      value_data = g_variant_get_fixed_array (value, &value_len, 1);
      
      loop_err = lsetxattr (path, (char*)name, (char*)value_data, value_len, XATTR_REPLACE) < 0;
      g_clear_pointer (&value, (GDestroyNotify) g_variant_unref);
      if (loop_err)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
    }

  ret = TRUE;
 out:
  return ret;
}
Exemple #8
0
gboolean
ot_util_variant_map_fd (GFileDescriptorBased  *stream,
                        goffset                start,
                        const GVariantType    *type,
                        gboolean               trusted,
                        GVariant             **out_variant,
                        GError               **error)
{
  gboolean ret = FALSE;
  gpointer map;
  struct stat stbuf;
  VariantMapData *mdata = NULL;
  gsize len;

  if (!gs_stream_fstat (stream, &stbuf, NULL, error))
    goto out;

  len = stbuf.st_size - start;
  map = mmap (NULL, len, PROT_READ, MAP_PRIVATE, 
              g_file_descriptor_based_get_fd (stream), start);
  if (!map)
    {
      ot_util_set_error_from_errno (error, errno);
      goto out;
    }

  mdata = g_new (VariantMapData, 1);
  mdata->addr = map;
  mdata->len = len;

  ret = TRUE;
  *out_variant = g_variant_new_from_data (type, map, len, trusted,
                                          variant_map_data_destroy, mdata);
 out:
  return ret;
}
Exemple #9
0
static gboolean
cp_internal (GFile         *src,
             GFile         *dest,
             gboolean       use_hardlinks,
             GCancellable  *cancellable,
             GError       **error)
{
  gboolean ret = FALSE;
  ot_lobj GFileEnumerator *enumerator = NULL;
  ot_lobj GFileInfo *file_info = NULL;
  GError *temp_error = NULL;

  enumerator = g_file_enumerate_children (src, OSTREE_GIO_FAST_QUERYINFO,
                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                          cancellable, error);
  if (!enumerator)
    goto out;

  if (!ot_gfile_ensure_directory (dest, FALSE, error))
    goto out;

  while ((file_info = g_file_enumerator_next_file (enumerator, cancellable, &temp_error)) != NULL)
    {
      const char *name = g_file_info_get_name (file_info);
      ot_lobj GFile *src_child = g_file_get_child (src, name);
      ot_lobj GFile *dest_child = g_file_get_child (dest, name);

      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
        {
          if (!ot_gfile_ensure_directory (dest_child, FALSE, error))
            goto out;

          /* Can't do this even though we'd like to; it fails with an error about
           * setting standard::type not being supported =/
           *
           if (!g_file_set_attributes_from_info (dest_child, file_info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
           cancellable, error))
           goto out;
          */
          if (chmod (ot_gfile_get_path_cached (dest_child),
                     g_file_info_get_attribute_uint32 (file_info, "unix::mode")) == -1)
            {
              ot_util_set_error_from_errno (error, errno);
              goto out;
            }

          if (!cp_internal (src_child, dest_child, use_hardlinks, cancellable, error))
            goto out;
        }
      else
        {
          gboolean did_link = FALSE;
          (void) unlink (ot_gfile_get_path_cached (dest_child));
          if (use_hardlinks)
            {
              if (link (ot_gfile_get_path_cached (src_child), ot_gfile_get_path_cached (dest_child)) == -1)
                {
                  if (!(errno == EMLINK || errno == EXDEV))
                    {
                      ot_util_set_error_from_errno (error, errno);
                      goto out;
                    }
                  use_hardlinks = FALSE;
                }
              else
                did_link = TRUE;
            }
          if (!did_link)
            {
              if (!g_file_copy (src_child, dest_child,
                                G_FILE_COPY_OVERWRITE | G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS,
                                cancellable, NULL, NULL, error))
                goto out;
            }
        }
      g_clear_object (&file_info);
    }
  if (temp_error)
    {
      g_propagate_error (error, temp_error);
      goto out;
    }

  ret = TRUE;
 out:
  return ret;
}
Exemple #10
0
gboolean
ostree_create_file_from_input (GFile            *dest_file,
                               GFileInfo        *finfo,
                               GVariant         *xattrs,
                               GInputStream     *input,
                               GCancellable     *cancellable,
                               GError          **error)
{
  gboolean ret = FALSE;
  const char *dest_path;
  guint32 uid, gid, mode;
  ot_lobj GFileOutputStream *out = NULL;

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return FALSE;

  if (finfo != NULL)
    {
      mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode");
    }
  else
    {
      mode = S_IFREG | 0664;
    }
  dest_path = ot_gfile_get_path_cached (dest_file);

  if (S_ISDIR (mode))
    {
      if (mkdir (ot_gfile_get_path_cached (dest_file), mode) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
    }
  else if (S_ISREG (mode))
    {
      out = g_file_create (dest_file, 0, cancellable, error);
      if (!out)
        goto out;

      if (input)
        {
          if (g_output_stream_splice ((GOutputStream*)out, input, 0,
                                      cancellable, error) < 0)
            goto out;
        }

      if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
        goto out;
    }
  else if (S_ISLNK (mode))
    {
      const char *target = g_file_info_get_attribute_byte_string (finfo, "standard::symlink-target");
      if (symlink (target, dest_path) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
    }
  else if (S_ISCHR (mode) || S_ISBLK (mode))
    {
      guint32 dev = g_file_info_get_attribute_uint32 (finfo, "unix::rdev");
      if (mknod (dest_path, mode, dev) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
    }
  else if (S_ISFIFO (mode))
    {
      if (mkfifo (dest_path, mode) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          goto out;
        }
    }
  else
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Invalid mode %u", mode);
      goto out;
    }

  if (finfo != NULL)
    {
      uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
      gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
      
      if (lchown (dest_path, uid, gid) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          g_prefix_error (error, "lchown(%u, %u) failed: ", uid, gid);
          goto out;
        }
    }

  if (!S_ISLNK (mode))
    {
      if (chmod (dest_path, mode) < 0)
        {
          ot_util_set_error_from_errno (error, errno);
          g_prefix_error (error, "chmod(%u) failed: ", mode);
          goto out;
        }
    }

  if (xattrs != NULL)
    {
      if (!ostree_set_xattrs (dest_file, xattrs, cancellable, error))
        goto out;
    }

  ret = TRUE;
 out:
  if (!ret && !S_ISDIR(mode))
    {
      (void) unlink (dest_path);
    }
  return ret;
}