[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