[Pkg-privacy-commits] [libgsecuredelete] 01/168: First checkin.
Ulrike Uhlig
u-guest at moszumanska.debian.org
Thu Jul 7 20:06:31 UTC 2016
This is an automated email from the git hooks/post-receive script.
u-guest pushed a commit to branch master
in repository libgsecuredelete.
commit e216269a554f4279f31c67523d4dc1fa30f65132
Author: Colomban Wendling <ban at herbesfolles.org>
Date: Tue Sep 29 01:39:46 2009 +0200
First checkin.
There is:
* An autotools build system that seems be working;
* A SecureDelete.DeleteOperation;
* Some utilities;
* A test application.
---
Makefile.am | 3 +
autogen.sh | 8 +
configure.ac | 31 ++++
gsecuredelete/Makefile.am | 21 +++
gsecuredelete/delete-operation.vala | 289 ++++++++++++++++++++++++++++++++++++
gsecuredelete/fill-operation.vala | 0
gsecuredelete/main.vala | 69 +++++++++
gsecuredelete/utils.vala | 108 ++++++++++++++
8 files changed, 529 insertions(+)
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..c67e4c4
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = gsecuredelete
+
+ACLOCAL_AMFLAGS = -I build/m4
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..7ff3181
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+mkdir -p build/aux || exit 1
+mkdir -p build/m4 || exit 1
+#gtkdocize --flavour no-tmpl || exit 1
+autoreconf -vfi || exit 1
+
+#~ ./configure "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..b531b5a
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,31 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.64])
+AC_INIT([libgsecuredelete], [0.1], [ban at herbesfolles.org])
+AC_CONFIG_SRCDIR([gsecuredelete/delete-operation.vala])
+AC_CONFIG_AUX_DIR([build/aux])
+AC_CONFIG_MACRO_DIR([build/m4])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AC_CONFIG_HEADERS([config.h])
+
+# Checks for programs.
+AM_PROG_VALAC
+AC_PROG_LIBTOOL
+
+# Checks for libraries.
+VALA_PACKAGES="glib-2.0 posix"
+AC_SUBST([VALA_PACKAGES])
+
+PKG_CHECK_MODULES([LIBGSECUREDELETE], [glib-2.0 \
+ gobject-2.0])
+
+# Checks for header files.
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+# Checks for library functions.
+
+AC_CONFIG_FILES([Makefile
+ gsecuredelete/Makefile])
+AC_OUTPUT
diff --git a/gsecuredelete/Makefile.am b/gsecuredelete/Makefile.am
new file mode 100644
index 0000000..151c3a1
--- /dev/null
+++ b/gsecuredelete/Makefile.am
@@ -0,0 +1,21 @@
+noinst_PROGRAMS = test
+lib_LTLIBRARIES = libgsecuredelete.la
+
+AM_VALAFLAGS = $(VALA_PACKAGES:%=--pkg=%)
+AM_CFLAGS = $(LIBGSECUREDELETE_CFLAGS)
+AM_LDFLAGS = $(LIBGSECUREDELETE_LIBS)
+
+libgsecuredelete_la_includedir=$(includedir)/gsecuredelete
+
+libgsecuredelete_la_VALAFLAGS = $(AM_VALAFLAGS) --library=libgsecuredelete -H libgsecuredelete.h
+libgsecuredelete_la_SOURCES = delete-operation.vala \
+ fill-operation.vala \
+ utils.vala
+libgsecuredelete_la_include_HEADERS = libgsecuredelete.h \
+ libgsecuredelete.vapi
+
+test_VALAFLAGS = $(AM_VALAFLAGS) --vapidir=. --pkg=libgsecuredelete
+test_SOURCES = main.vala
+test_LDADD = libgsecuredelete.la
+
+
diff --git a/gsecuredelete/delete-operation.vala b/gsecuredelete/delete-operation.vala
new file mode 100644
index 0000000..24147d1
--- /dev/null
+++ b/gsecuredelete/delete-operation.vala
@@ -0,0 +1,289 @@
+
+using GLib;
+
+namespace SecureDelete
+{
+ public errordomain DeleteOperationError {
+ CHILD_FAILED,
+ NO_FILES
+ }
+
+ public class DeleteOperation : Object
+ {
+ private List<string> pathes;
+ /* fields for async deletion */
+ private size_t n_passes;
+ private size_t passes;
+ private Pid pid;
+ private int fd_out;
+ private int fd_err;
+
+ /* signals */
+ public signal void finished (bool success,
+ string? message);
+ public signal void progress (double fraction);
+
+ /* properties */
+ /* whether the operation object is busy */
+ public bool busy {
+ public get;
+ private set;
+ default = false;
+ }
+ /* whether to use fast and insecure mode */
+ public bool fast {
+ get; set; default = false;
+ }
+
+ /* adds a path to the list of pathes to remove */
+ public void add_path (string path)
+ requires (! this.busy)
+ {
+ this.pathes.append (path);
+ }
+
+ /* removes a path from the list of pathes to remove */
+ public void remove_path (string path)
+ requires (! this.busy)
+ {
+ /* FIXME: support for canonical names?
+ * (e.g. /aa/../bb is the same as /bb) */
+ weak List<string> link;
+
+ link = this.pathes.find_custom (path,
+ (a, b) => {
+ return (string)a == (string)b ? 0 : 1;
+ });
+ if (link != null) {
+ this.pathes.delete_link (link);
+ }
+ }
+
+ /* builds the command's arguments (argv) */
+ private string?[] build_args (out size_t n_files)
+ throws DeleteOperationError
+ {
+ size_t n = 0;
+ string?[] args = {
+ "srm",
+ "-rv"
+ };
+
+ if (this.fast) {
+ args += "-f";
+ }
+ foreach (string path in this.pathes) {
+ args += path;
+ n++;
+ }
+ args += null;
+
+ n_files = n;
+ if (n == 0) {
+ throw new DeleteOperationError.NO_FILES ("Nothing to remove");
+ }
+
+ return args;
+ }
+
+ /* gets the progress status of the child process */
+ private uint get_progress (int fd,
+ size_t bufisze = 16)
+ throws FDError
+ {
+ uint progress = 0;
+
+ try {
+ if (FD.read_ready (fd)) {
+ char[] buf = new char[bufisze];
+ ssize_t read_rv = 0;
+
+ do {
+ read_rv = Posix.read (fd, buf, bufisze);
+ if (read_rv < 0) {
+ throw new FDError.READ_ERROR ("read(): %s", strerror (errno));
+ } else {
+ for (uint i = 0; i < read_rv; i++) {
+ if (buf[i] == '*')
+ progress ++;
+ }
+ }
+ } while (read_rv == bufisze);
+ }
+ } catch (FDError e) {
+ throw e;
+ }
+
+ return progress;
+ }
+
+ /* updates the progress status and emit DeleteOperation::progress if
+ * changed */
+ private void update_progress ()
+ {
+ uint progress = 0;
+
+ try {
+ progress = this.get_progress (this.fd_out);
+ } catch (FDError e) {
+ warning ("Progression check failed: %s", e.message);
+ }
+ if (progress > 0) {
+ this.passes += progress;
+ this.progress (this.passes / (this.n_passes * 1.0));
+ }
+ }
+
+ /* checks if the chils finished, and disatches related things.
+ *
+ * It is meant to be called as a timeout function.
+ */
+ private bool do_wait_child ()
+ {
+ bool finished = true;
+ bool success = false;
+ int exit_status;
+ Posix.pid_t wait_rv;
+ string? message = null;
+
+ /* FIXME: 1 = WNOHANG, buf WNOHANG doesn't seems to be accessible from
+ * Vala */
+ wait_rv = Posix.waitpid ((Posix.pid_t)this.pid, out exit_status, 1);
+ if ((int)wait_rv < 0) {
+ critical ("waitpid() failed: %s", strerror (errno));
+ /* if we cannot watch the child, try to kill it */
+ if (Posix.kill ((Posix.pid_t)this.pid, 15) < 0) {
+ critical ("kill() failed: %s", strerror (errno));
+ }
+ } else if ((int)wait_rv == 0) {
+ /* nothing to do, just wait until next call */
+ this.update_progress ();
+ finished = false;
+ } else {
+ if (! Process.if_exited (exit_status)) {
+ message = "Subprocess crashed";
+ } else if (Process.exit_status (exit_status) != 0) {
+ /* get errors reported by the child */
+ message = FD.read_string (this.fd_err);
+ } else {
+ success = true;
+ }
+ }
+
+ if (finished) {
+ this.finished (success, message);
+
+ Process.close_pid (this.pid);
+ Posix.close (this.fd_err);
+ Posix.close (this.fd_out);
+ /*lock (this.busy)*/ {
+ this.busy = false;
+ }
+ }
+
+ return ! finished;
+ }
+
+ /** delete_async:
+ * @watch_interval: time (in milliseconds) between two check for subprocess
+ * status. A too short value may use too much CPU and a too
+ * big may be less responsive.
+ *
+ * Launches a secure deletion asynchronously.
+ *
+ * Returns: whether asynchronous deletion was successfully started.
+ */
+ public bool delete_async (uint watch_interval = 100)
+ throws SpawnError, DeleteOperationError
+ requires (! this.busy)
+ {
+ bool success = true;
+ string?[] args;
+ size_t n_files;
+
+ /*lock (this.busy)*/ {
+ this.busy = true;
+ }
+ try {
+ args = this.build_args (out n_files);
+ } catch (DeleteOperationError e) {
+ throw e;
+ }
+ this.fd_err = -1;
+ this.fd_out = -1;
+ /* FIXME: 38 is the standard SRM pass number, but may change with options
+ * like -l. If we support it one day, we need to fix this value (by
+ * getting the one SRM reports) in order to get a meaningful progress
+ * information */
+ this.n_passes = 38 * n_files;
+ this.passes = 0;
+ try {
+ Process.spawn_async_with_pipes (null, args, null,
+ SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
+ null,
+ out this.pid,
+ null, out this.fd_out, out this.fd_err);
+ } catch (SpawnError e) {
+ success = false;
+ throw e;
+ }
+ if (success) {
+ Timeout.add (watch_interval, this.do_wait_child);
+ }
+
+ return success;
+ }
+
+ /** delete_sync:
+ * Launches a secure deletion synchronously.
+ *
+ * Returns: whether deletion was successful.
+ */
+ public bool delete_sync ()
+ throws SpawnError, DeleteOperationError
+ requires (! this.busy)
+ {
+ bool success = true;
+ string error_output;
+ int exit_status;
+ string?[] args;
+
+ /*lock (this.busy)*/ {
+ this.busy = true;
+ }
+ try {
+ /* FIXME: how to make an out parameter optional? */
+ size_t n_files;
+
+ args = this.build_args (out n_files);
+ } catch (DeleteOperationError e) {
+ throw e;
+ }
+ try {
+ Process.spawn_sync (null, args, null,
+ SpawnFlags.SEARCH_PATH, null,
+ null, out error_output, out exit_status);
+ } catch (SpawnError e) {
+ success = false;
+ throw e;
+ }
+ if (success) {
+ string? message = null;
+
+ if (! Process.if_exited (exit_status) ||
+ Process.exit_status (exit_status) != 0) {
+ message = error_output;
+ }
+ this.finished (success, message);
+ if (message != null) {
+ throw new DeleteOperationError.CHILD_FAILED ("%s", message);
+ }
+ }
+ /*lock (this.busy)*/ {
+ this.busy = false;
+ }
+
+ return success;
+ }
+ }
+}
diff --git a/gsecuredelete/fill-operation.vala b/gsecuredelete/fill-operation.vala
new file mode 100644
index 0000000..e69de29
diff --git a/gsecuredelete/main.vala b/gsecuredelete/main.vala
new file mode 100644
index 0000000..484fb2e
--- /dev/null
+++ b/gsecuredelete/main.vala
@@ -0,0 +1,69 @@
+
+using SecureDelete;
+
+public class Test
+{
+ private MainLoop main_loop;
+
+ public Test ()
+ {
+ this.main_loop = new MainLoop (null, false);
+ }
+
+ ~Test ()
+ {
+ if (main_loop.is_running ()) {
+ main_loop.quit ();
+ }
+ }
+
+ void finished_handler (bool success,
+ string? message)
+ {
+ if (success) {
+ stdout.printf ("Success!\n");
+ } else {
+ stderr.printf ("Failure: %s\n", message);
+ }
+ this.main_loop.quit ();
+ }
+
+ static void progress_handler (double progress)
+ {
+ stdout.printf ("%.0f%%\n", progress * 100);
+ }
+
+ public bool run (string[] args)
+ {
+ if (args.length < 2) {
+ return false;
+ }
+
+ var op = new SecureDelete.DeleteOperation ();
+
+ op.finished.connect (finished_handler);
+ op.progress.connect (progress_handler);
+ foreach (var arg in args) {
+ /* hack to skip the first argument */
+ if (arg != args[0])
+ op.add_path (arg);
+ }
+ try {
+ op.delete_async ();
+
+ this.main_loop = new MainLoop (null, false);
+ main_loop.run ();
+ } catch (Error e) {
+ stderr.printf ("failed to start deletion: %s\n", e.message);
+ }
+
+ return true;
+ }
+}
+
+public static int main (string[] args)
+{
+ var test = new Test ();
+
+ return test.run (args) ? 0 : 1;
+}
diff --git a/gsecuredelete/utils.vala b/gsecuredelete/utils.vala
new file mode 100644
index 0000000..28856fc
--- /dev/null
+++ b/gsecuredelete/utils.vala
@@ -0,0 +1,108 @@
+
+namespace SecureDelete
+{
+
+ public errordomain FDError {
+ KILL_ERROR,
+ READ_ERROR,
+ SELECT_ERROR,
+ WAITPID_ERROR,
+ }
+
+ namespace FD {
+ /** read_ready:
+ * @fd: a file descriptor
+ * @error: return location for an error string on error, or NULL to ignore
+ * errors.
+ *
+ * Gets whether a file descriptor is ready to be read or not. Ready means that
+ * rading data from it would not be blocking, as there is data to be read.
+ *
+ * Returns: %TRUE if the file is read, %FALSE otherwise.
+ */
+ public bool read_ready (int fd)
+ throws FDError
+ {
+ bool ready = false;
+
+ if (fd > 0) {
+ Posix.fd_set rfds = {};
+ Posix.timeval tv = {0, 0};
+
+ Posix.FD_ZERO (rfds);
+ Posix.FD_SET (fd, rfds);
+ var rv = Posix.select (fd + 1, rfds, null, null, tv);
+ if (rv == -1) {
+ throw new FDError.SELECT_ERROR ("select(): %s", strerror (errno));
+ } else if (rv > 0) {
+ ready = true;
+ }
+ }
+
+ return ready;
+ }
+
+ /** read_string:
+ *
+ * @fd: a file descriptor
+ * @n_bytes: number of bytes to read from @fd, or -1 to read all @fd
+ *
+ * Reads content of a file as a C string (0-terminated).
+ *
+ * Returns: a newly allocated string containing data in @fd.
+ */
+ public static string? read_string (int fd,
+ ssize_t n_bytes = -1)
+ throws FDError
+ {
+ char* buf = null;
+
+ if (n_bytes > 0) {
+ ssize_t n_read;
+
+ buf = new char[n_bytes + 1];
+ n_read = Posix.read (fd, buf, n_bytes);
+ if (n_read < 0) {
+ int errn = errno;
+
+ delete buf;
+ buf = null;
+ throw new FDError.READ_ERROR ("read(): %s", strerror (errn));
+ } else {
+ buf[n_read] = 0;
+ }
+ } else {
+ size_t packet_size = 64;
+ size_t n_read = 0;
+ ssize_t read_rv = 0;
+
+ n_bytes = 0;
+ do {
+ /* no realloc in Vala, but should be safe */
+ buf = realloc (buf, n_bytes + packet_size + 1);
+
+ read_rv = Posix.read (fd, &buf[n_bytes], packet_size);
+ if (read_rv >= 0) {
+ n_read += read_rv;
+ }
+
+ n_bytes += (ssize_t)packet_size;
+ } while (n_bytes > 0 /* don't underflow */ &&
+ read_rv >= 0 &&
+ read_rv == packet_size);
+ if (read_rv < 0) {
+ int errn = errno;
+
+ delete buf;
+ buf = null;
+ throw new FDError.READ_ERROR ("read(): %s", strerror (errn));
+ } else {
+ buf[n_read] = 0;
+ }
+ }
+
+ /* pass ownership to the caller */
+ return (string?) (owned) buf;
+ }
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/libgsecuredelete.git
More information about the Pkg-privacy-commits
mailing list