diff --git a/Makefile-libostree.am b/Makefile-libostree.am index eca57ea5..1b756001 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -49,6 +49,8 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-lzma-decompressor.h \ src/libostree/ostree-varint.h \ src/libostree/ostree-varint.c \ + src/libostree/ostree-linuxfsutil.h \ + src/libostree/ostree-linuxfsutil.c \ src/libostree/ostree-diff.c \ src/libostree/ostree-mutable-tree.c \ src/libostree/ostree-repo.c \ diff --git a/configure.ac b/configure.ac index 74094c9c..1b3916bb 100644 --- a/configure.ac +++ b/configure.ac @@ -48,6 +48,9 @@ PKG_CHECK_MODULES(OT_DEP_GIO_UNIX, $GIO_DEPENDENCY) dnl 5.1.0 is an arbitrary version here PKG_CHECK_MODULES(OT_DEP_LZMA, liblzma >= 5.1.1alpha) +dnl We're not actually linking to this, just using the header +PKG_CHECK_MODULES(OT_DEP_E2P, e2p) + SOUP_DEPENDENCY="libsoup-2.4 >= 2.39.1" AC_ARG_WITH(soup, AS_HELP_STRING([--with-soup], [Use libsoup @<:@default=yes@:>@]), diff --git a/src/libostree/ostree-linuxfsutil.c b/src/libostree/ostree-linuxfsutil.c new file mode 100644 index 00000000..8e11d2cf --- /dev/null +++ b/src/libostree/ostree-linuxfsutil.c @@ -0,0 +1,128 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2014 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "ostree-linuxfsutil.h" +#include "otutil.h" +#include "libgsystem.h" + +#include +#include +#include + +/** + * _ostree_linuxfs_fd_alter_immutable_flag: + * @fd: A file descriptor + * @new_immutable_state: Set this to %TRUE to make the file immutable, %FALSE to unset the flag + * @cancellable: Cancellable + * @error: GError + * + * Alter the immutable flag of object referred to by @fd; may be a + * regular file or a directory. + * + * If the operation is not supported by the underlying filesystem, + * this function will silently do nothing. + */ +gboolean +_ostree_linuxfs_fd_alter_immutable_flag (int fd, + gboolean new_immutable_state, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + unsigned long flags; + int r; + + r = ioctl (fd, EXT2_IOC_GETFLAGS, &flags); + if (r == -1) + { + int errsv = errno; + if (errsv == EOPNOTSUPP || errsv == ENOTTY) + ; + else + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "ioctl(EXT2_IOC_GETFLAGS): %s", + g_strerror (errsv)); + goto out; + } + } + else + { + if (new_immutable_state) + flags |= EXT2_IMMUTABLE_FL; + else + flags &= ~EXT2_IMMUTABLE_FL; + r = ioctl (fd, EXT2_IOC_SETFLAGS, &flags); + if (r == -1) + { + int errsv = errno; + if (errsv == EOPNOTSUPP || errsv == ENOTTY) + ; + else + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "ioctl(EXT2_IOC_GETFLAGS): %s", + g_strerror (errsv)); + goto out; + } + } + } + + ret = TRUE; + out: + return ret; +} + +gboolean +_ostree_linuxfs_alter_immutable_flag (GFile *path, + gboolean new_immutable_state, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + int fd = -1; + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return FALSE; + + fd = open (gs_file_get_path_cached (path), O_RDONLY|O_NONBLOCK|O_LARGEFILE); + if (fd == -1) + { + int errsv = errno; + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "open(%s): %s", + gs_file_get_path_cached (path), + g_strerror (errsv)); + goto out; + } + + if (!_ostree_linuxfs_fd_alter_immutable_flag (fd, new_immutable_state, + cancellable, error)) + goto out; + + ret = TRUE; + out: + if (fd != -1) + (void) close (fd); + return ret; +} + diff --git a/src/libostree/ostree-linuxfsutil.h b/src/libostree/ostree-linuxfsutil.h new file mode 100644 index 00000000..566717c5 --- /dev/null +++ b/src/libostree/ostree-linuxfsutil.h @@ -0,0 +1,40 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2014 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include "ostree-types.h" + +G_BEGIN_DECLS + +gboolean +_ostree_linuxfs_fd_alter_immutable_flag (int fd, + gboolean new_immutable_state, + GCancellable *cancellable, + GError **error); + +gboolean +_ostree_linuxfs_alter_immutable_flag (GFile *path, + gboolean new_immutable_state, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index ade75bba..825d6c4d 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -22,6 +22,7 @@ #include "otutil.h" #include "libgsystem.h" +#include "ostree-linuxfsutil.h" #include "ostree-sysroot-private.h" @@ -341,6 +342,9 @@ cleanup_old_deployments (OstreeSysroot *self, if (device == root_device && inode == root_inode) continue; + if (!_ostree_linuxfs_alter_immutable_flag (deployment_path, FALSE, + cancellable, error)) + goto out; if (!gs_shutil_rm_rf (deployment_path, cancellable, error)) goto out; if (!gs_shutil_rm_rf (origin_path, cancellable, error)) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index f74fd922..d5456c05 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -25,6 +25,7 @@ #include "ostree-sysroot-private.h" #include "ostree-core-private.h" +#include "ostree-linuxfsutil.h" #include "otutil.h" #include "libgsystem.h" @@ -1715,6 +1716,10 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, cancellable, error)) goto out; + if (!_ostree_linuxfs_alter_immutable_flag (new_deployment_path, TRUE, + cancellable, error)) + goto out; + /* After this, install_deployment_kernel() will set the other boot * options and write it out to disk. */