Checkin of 0.2.98 upstream source 0.2.98
authorRalf Ertzinger <ralf@skytale.net>
Wed, 12 Feb 2014 12:55:05 +0000 (13:55 +0100)
committerRalf Ertzinger <ralf@skytale.net>
Wed, 12 Feb 2014 12:55:05 +0000 (13:55 +0100)
119 files changed:
Authors [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile [new file with mode: 0644]
VERSION [new file with mode: 0644]
data/Makefile [new file with mode: 0644]
data/time-slider.desktop [new file with mode: 0644]
data/time-slider.desktop.in [new file with mode: 0644]
etc/dbus-1/system.d/time-slider.conf [new file with mode: 0644]
etc/xdg/autostart/time-slider-notify.desktop [new file with mode: 0644]
lib/svc/method/time-slider [new file with mode: 0755]
lib/svc/method/time-slider-plugin [new file with mode: 0755]
lib/svc/method/time-slider-rsync [new file with mode: 0755]
po/.intltool-merge-cache [new file with mode: 0644]
po/ChangeLog [new file with mode: 0644]
po/LINGUAS [new file with mode: 0644]
po/Makefile [new file with mode: 0644]
po/POTFILES.in [new file with mode: 0644]
po/ar.gmo [new file with mode: 0644]
po/ar.po [new file with mode: 0644]
po/ca.gmo [new file with mode: 0644]
po/ca.po [new file with mode: 0644]
po/cs.gmo [new file with mode: 0644]
po/cs.po [new file with mode: 0644]
po/de.gmo [new file with mode: 0644]
po/de.po [new file with mode: 0644]
po/es.gmo [new file with mode: 0644]
po/es.po [new file with mode: 0644]
po/fr.gmo [new file with mode: 0644]
po/fr.po [new file with mode: 0644]
po/hu.gmo [new file with mode: 0644]
po/hu.po [new file with mode: 0644]
po/id.gmo [new file with mode: 0644]
po/id.po [new file with mode: 0644]
po/it.gmo [new file with mode: 0644]
po/it.po [new file with mode: 0644]
po/ja.gmo [new file with mode: 0644]
po/ja.po [new file with mode: 0644]
po/ko.gmo [new file with mode: 0644]
po/ko.po [new file with mode: 0644]
po/nl.gmo [new file with mode: 0644]
po/nl.po [new file with mode: 0644]
po/pl.gmo [new file with mode: 0644]
po/pl.po [new file with mode: 0644]
po/pt_BR.gmo [new file with mode: 0644]
po/pt_BR.po [new file with mode: 0644]
po/ru.gmo [new file with mode: 0644]
po/ru.po [new file with mode: 0644]
po/sv.gmo [new file with mode: 0644]
po/sv.po [new file with mode: 0644]
po/zh_CN.gmo [new file with mode: 0644]
po/zh_CN.po [new file with mode: 0644]
po/zh_HK.gmo [new file with mode: 0644]
po/zh_HK.po [new file with mode: 0644]
po/zh_TW.gmo [new file with mode: 0644]
po/zh_TW.po [new file with mode: 0644]
py-compile.py [new file with mode: 0644]
usr/bin/time-slider-setup [new file with mode: 0755]
usr/lib/time-slider-delete [new file with mode: 0755]
usr/lib/time-slider-notify [new file with mode: 0755]
usr/lib/time-slider-snapshot [new file with mode: 0755]
usr/lib/time-slider-version [new file with mode: 0755]
usr/lib/time-slider/plugins/rsync/rsync-backup [new file with mode: 0755]
usr/lib/time-slider/plugins/rsync/rsync-trigger [new file with mode: 0755]
usr/lib/time-slider/plugins/zfssend/zfssend [new file with mode: 0755]
usr/lib/time-sliderd [new file with mode: 0755]
usr/share/applications/time-slider.desktop [new file with mode: 0644]
usr/share/icons/hicolor/16x16/apps/time-slider-setup.png [new file with mode: 0644]
usr/share/icons/hicolor/24x24/apps/time-slider-setup.png [new file with mode: 0644]
usr/share/icons/hicolor/32x32/apps/time-slider-setup.png [new file with mode: 0644]
usr/share/icons/hicolor/36x36/apps/time-slider-setup.png [new file with mode: 0644]
usr/share/icons/hicolor/48x48/apps/time-slider-setup.png [new file with mode: 0644]
usr/share/icons/hicolor/72x72/apps/time-slider-setup.png [new file with mode: 0644]
usr/share/icons/hicolor/96x96/apps/time-slider-setup.png [new file with mode: 0644]
usr/share/time-slider/glade/time-slider-delete.glade [new file with mode: 0644]
usr/share/time-slider/glade/time-slider-setup.glade [new file with mode: 0644]
usr/share/time-slider/glade/time-slider-snapshot.glade [new file with mode: 0644]
usr/share/time-slider/glade/time-slider-version.glade [new file with mode: 0644]
usr/share/time-slider/lib/plugin/__init__.py [new file with mode: 0644]
usr/share/time-slider/lib/plugin/plugin.py [new file with mode: 0644]
usr/share/time-slider/lib/plugin/pluginsmf.py [new file with mode: 0644]
usr/share/time-slider/lib/plugin/pluginsmf.py~ [new file with mode: 0644]
usr/share/time-slider/lib/plugin/rsync/__init__.py [new file with mode: 0644]
usr/share/time-slider/lib/plugin/rsync/backup.py [new file with mode: 0644]
usr/share/time-slider/lib/plugin/rsync/backup.py.orig [new file with mode: 0644]
usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py [new file with mode: 0755]
usr/share/time-slider/lib/plugin/rsync/trigger.py [new file with mode: 0644]
usr/share/time-slider/lib/plugin/zfssend/__init__.py [new file with mode: 0644]
usr/share/time-slider/lib/plugin/zfssend/zfssend.py [new file with mode: 0644]
usr/share/time-slider/lib/time_slider/.swp [new file with mode: 0644]
usr/share/time-slider/lib/time_slider/__init__.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/applet.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/applet.py~ [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/autosnapsmf.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/dbussvc.py [new file with mode: 0644]
usr/share/time-slider/lib/time_slider/deletegui.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/deletegui.py.bak [new file with mode: 0644]
usr/share/time-slider/lib/time_slider/deletegui.py~ [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/fileversion.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/rbac.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/setupgui.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/setupgui.py~ [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/smf.py [new file with mode: 0644]
usr/share/time-slider/lib/time_slider/snapnowui.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/snapnowui.py~ [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/timesliderd.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/timesliderd.py~ [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/timeslidersmf.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/tmp.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/tmp.py~ [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/tmp2.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/tmp2.py~ [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/util.py [new file with mode: 0644]
usr/share/time-slider/lib/time_slider/util.py~ [new file with mode: 0644]
usr/share/time-slider/lib/time_slider/zfs.py [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/zfs.py.safe [new file with mode: 0755]
usr/share/time-slider/lib/time_slider/zfs.py~ [new file with mode: 0755]
var/svc/manifest/application/time-slider-plugin.xml [new file with mode: 0644]
var/svc/manifest/application/time-slider.xml [new file with mode: 0644]
var/svc/manifest/system/filesystem/auto-snapshot.xml [new file with mode: 0644]

diff --git a/Authors b/Authors
new file mode 100644 (file)
index 0000000..4670b17
--- /dev/null
+++ b/Authors
@@ -0,0 +1,2 @@
+2008-09-11 Niall Power - <niall.power@sun.com>
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..69803fe
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,952 @@
+2011-04-27 Erwann Chenede - <erwann.chenede@oracle.com>
+
+       * VERSION: Bump to 0.2.98
+       * usr/share/time-slider/lib/time_slider/applet.py
+         usr/share/time-slider/lib/time_slider/deletegui.py
+         usr/share/time-slider/lib/time_slider/setupgui.py
+         usr/share/time-slider/lib/time_slider/snapnowui.py
+         usr/share/time-slider/lib/time_slider/timesliderd.py :
+         Fix for 7038498 removed Primary Administrator references
+
+       * usr/share/time-slider/lib/time_slider/util.py
+         usr/share/time-slider/lib/time_slider/zfs.py : 
+         Fix for 6996354 gracefully handle snapshot failure
+
+2010-07-29 Niall Power - <niall.power@oracle.com>
+
+       * VERSION: Bump to 0.2.97
+
+2010-07-08 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/timesliderd.py:
+         Fix typo when raising exception. Defect #16361
+         RunTimeError -> RuntimeError
+
+2010-07-05 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Don't set filesystem tree view size request based on 
+         number of filesystems: Doesn't scale well. Set fixed
+         initial size instead. Fixes defect  #16319
+         Correct misspellings of "writable and "administrator".
+         Fixes defect #16388
+
+       * usr/share/time-slider/lib/time_slider/zfs.py:
+         Check returned value of bisect.bisect_left() is within
+         index range of list before trying to dereference it and
+         causing IndexError exceptions. Fixes defect #16377. 
+         Thanks to Tim Foster for this fix.
+
+2010-06-16 Niall Power - <niall.power@oracle.com>
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Remove accidental clobbering of tempSchedule list so
+         that non-archived backups can be expired as per normal
+         schedule retention rules. Opensolaris defect #16280
+
+2010-06-04 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/applet.py:
+         Register menu callback in Note class instantiation to
+         avoid multiple registration of same callback.
+
+2010-05-24 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Fix minor function spelling typo
+
+2010-05-24 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/glade/time-slider-setup.glade:
+         Replace GtkFileChooser combo widget with standard
+         GtkComboBox
+
+       * usr/share/time-slider/lib/time_slider/applet.py:
+         User path_tol_volume() from util library instead of
+         private copy
+
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Replace standard GtkFileChooser logic with custom combo
+         box implementation that is more tailored towards selecting
+         a backup device rather than a generic path. Is able to 
+         handle an offline/unmounted previously configured backup
+         device gracefully (impossible with stock widget). Doesn't
+         show meaningless shortcuts like Home, Documents, etc. either
+         Cleanup of code, renamed variables to use camel case and 
+         made unnecessarily public class variables private.
+         Changed order of target validation tests to check if the
+         device supports posix style links before checking if it's
+         empty. Means user doesn't have to delete everything on a
+         PCFS/FAT32 device only then to find out it's still unsuitable.
+
+       * usr/share/time-slider/lib/time_slider/util.py: Move previously
+         private function path_to_volume(path) here so it can be shared.
+
+2010-05-14 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/applet.py:
+         Use icon list hinted by gio.Volume instead of hardcoded
+         harddisk icon when possible when displaying notifications.
+         Makes icon more context specific to type of backup device.
+
+2010-05-14 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/applet.py:
+         Determine volume name of rsync target if available and
+         display that instead of the raw mount point in 
+         notifications. More user friendly.
+
+2010-05-14 Erwann Chenede - <erwann.chenede@sun.com>
+
+       * usr/share/time-slider/glade/time-slider-delete.glade:
+         Added Type combobox
+       * usr/share/time-slider/lib/plugin/pluginsmf.py:
+         fix import to call this class from a non standard 
+         location
+       * usr/share/time-slider/lib/time_slider/deletegui.py:
+         implemented rsync backup visualization and deletion
+       * usr/share/time-slider/lib/time_slider/zfs.py: 
+         renamed member function destroy_snapshot to destroy 
+         to reflect allow polymorphic call in deletegui.py
+         as the list of backup to delete can now be snapshots
+         or rsync backups.
+       * usr/share/time-slider/lib/time_slider/timesliderd.py:
+         propagated member function destroy name change.
+
+2010-05-14 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Fix list ValueError in list_pending_snapshots() caused
+         when rsync plugin is enabled but no fileystems are 
+         selected for backup. Check that zfs returns something
+         more than a blank in such cases.
+
+2010-05-14 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/glade/time-slider-setup.glade:
+         Fix resizing issue that prevented list view from expanding
+         to occupy all extra space when window gets vertically
+         extended.
+
+2010-05-14 Niall Power - <niall.power@oracle.com>
+
+       * etc/dbus-1/system.d/time-slider.conf:
+         Add service and policy definitions for TimSlider.config
+         service.
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Deal with backup device being mounted under variable
+         removable media mount points if not found in it's expected
+         location. Find and validate alternate mount points.
+
+       * usr/share/time-slider/lib/time_slider/applet.py:
+         Refactored to allow more modular notification management.
+         Improved rsync device monitoring by implementing both gio.File
+         and gio.Volume monitors so we can track mounting/unmounting of
+         static mounts like nfs/zfs and variable mount points for 
+         hotpluggable devices. Validate rsync target is correct using
+         SMF configuration key. Listen to TimeSlider.Config D-Bus events
+         and refresh configuration when D-Bus notification is received.
+         Add menu item to enable launching of setup GUI from the applet.
+
+       * usr/share/time-slider/lib/time_slider/dbussvc.py:
+         Add class and method definition for TimeSlider Config service
+         notifications.
+
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Register with system D-Bus and send notification of changes
+         to time-slider and rsync plugin services so the applet can
+         refresh.
+
+2010-05-13 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Fix list IndexError exception caused by looking
+         for non-existent backups on an empty device.
+       
+2010-05-11 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Tweak the space management of the rsync device for better
+         performance:
+         - don't scan for deleteables unless the device starts to 
+           exceed threshhold capacity.
+         - Rescan capacity periodically during rsync backup thread
+           lifecycle and rescan for deleteable backups only if
+           device exceeds threshold capacity level.
+
+2010-05-11 Niall Power - <niall.power@oracle.com>
+
+       * var/svc/manifest/system/filesystem/auto-snapshot.xml:
+         Update service bundle name and version number to 
+         SUNWtime-slider and 0.2.96 respectively.
+
+       * var/svc/manifest/application/time-slider-plugin.xml:
+         Add 2 new properties to define cleanup threshhold level of
+         rsync backup device and verbosity of rsync output for
+         debugging purposes.
+
+       * usr/share/time-slider/lib/time_slider/util.py: Adjust
+         signature of util.debug() to make the verbose argument 
+         mandatory instead of automatic.
+
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py:
+         Add 2 new methods to retrieve cleanup threshhold and rsync
+         verbosity properties from the rsync SMF service instance.
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Cleanup variable naming, making class private variables
+         actually private using leading "_" character.
+         Rename RsyncBackup class to RsyncProcess to me more descriptive.
+         Add support for rsync verbosity in RsyncProcess class.
+         Implement better cleanup and space management mechanism:
+         - Removes old backups in parallel to new rsync backups running
+           in a separate thread if space falls below threshhold level.
+         - Identifies what backups can and can't be deleted for a given
+           new rsync backup based on age and number of backups left for
+           the associated filesystem.
+         - Cleanup threshhold tuneable via SMF atic.
+
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py:
+         Add 2 new methods to retrieve cleanup threshhold and rsync
+         verbosity properties from the rsync SMF service instance.
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Add check to make sure config key on target device matches that
+         stored in SMF before commencing backups.
+         Cleanup variable naming, making class private variables
+         actually private using leading "_" character.
+         Rename RsyncBackup class to RsyncProcess to me more descriptive.
+         Add support for rsync verbosity in RsyncProcess class.
+         Implement better cleanup and space management mechanism:
+         - Removes old backups in parallel to new rsync backups running
+           in a separate thread if space falls below threshhold level.
+           Avoids having to make rough, inaccurate guesses about size 
+           required for new backups because it responds in real time.
+         - Identifies what backups can and can't be deleted for a given
+           new rsync backup based on age and number of backups left for
+           the associated filesystem.
+         - Cleanup threshhold tuneable via SMF.
+         - Doesn't try to backup snapshots older than what's already on
+           the backup device if device is almost full.
+2010-05-05 Niall Power - <niall.power@oracle.com>
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Redesigned queue management and backlog mechanism. Backs up
+         most recent snapshot set first, then works backwards through
+         the queue. Stops backup mechanism falling too far behind while
+         still allowing backup of older snapshots to take place if
+         time and space permit.
+         Enhancements to filesystem layout of backups - added seperate
+         folders for partial transfers, log files, trash folder and lock
+         files. Added file locking mechanism to prevent deletion by other
+         tools of backups in use (eg during incremental backups).
+         Added trash mechanism, replaces in place deletion of snapshots
+         which messes up directory mtimes and incremental backups.
+         Instead, expired backups are moved to a .trash folder and a new
+         method: empty_trash_folders() cleans it up after before starting
+         the next snapshot set backup.
+         Fix bug in list_pending_snapshots() where ctime of snapshots was
+         returned as a string instead of a long.
+
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py: Add new 
+         filesystem suffix definitions for partial backups, trash
+         folders, backup lock files and backup log files.
+
+2010-05-03 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/timesliderd.py:
+         Determine if <zpool/remedial-cleanup> SMF property is set to true.
+         Do not perform remedial cleanups if it's value is false.
+
+       * usr/share/time-slider/lib/time_slider/timeslidersmf.py:
+         Add new method: get_remedial_cleanup() to indicate the value of
+         property <zpool/remedial-cleanup>
+
+       * var/svc/manifest/application/time-slider.xml:
+         Add new SMF property: <zpool/remedial-cleanup> as boolean with
+         default value of 'true'. Indicates that time-sliderd should
+         perform remedial cleanups when snapshotted pool runs low on
+         space.
+
+2010-05-03 Niall Power - <niall.power@oracle.com>
+
+       * Makefile:
+         Install/uninstall time-slider.desktop into 
+         $(DESTDIR)/usr/share/applications/
+
+2010-05-02 Niall Power - <niall.power@oracle.com>
+
+       * lib/svc/method/time-slider:
+         Remove any legacy zfs-auto-snapshot cron jobs in
+         zfssnap's crontab that may not have been removed
+         if the old auto-snapshot services were not stopped
+         cleanly.
+
+2010-05-02 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/timesliderd.py:
+         Fix incorrect invocation of util.debug() that caused
+         unconditional verbose output.
+2010-05-02 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/timesliderd.py:
+         Fix small typo in monthly calculation.
+
+2010-05-02 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Instantiate RsyncBackup objects with verbose flag
+         passed through. Remove "--progress" argument from
+         rsync and add "-vv" argument instead if verbose
+         flag is set.
+
+2010-05-01 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/plugin.py: Fix some
+         incorrect invocations that didn't pass verbose
+         parameter (and were therefore no-ops)
+
+       * usr/share/time-slider/lib/time_slider/timesliderd.py:
+         Fix monthly period calculation. Now handles period
+         increments > 12 months and period increments that
+         land on december (originally logged as bugster
+         CR #6904417)
+
+2010-05-01 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Cache all GUI configuration values at startup and
+         use them later to compare changes in configuration
+         state. Only apply the minimum set of configuration
+         changes necessary instead of previous method of
+         blindly applying everything, even if unchanged.
+         Configuration is much much faster now, especially
+         for minor configuration changes.
+         Recognise previously configured backup devices and
+         ask the user if they want to start using it again
+         instead of rejecting it as belonging to another 
+         system.
+         Remove duplicate import of os.path modules.
+
+2010-04-28 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Add removal of partial backups missing a  matching 
+         snapshot in the backup queue. They are zombies.
+         When catching an rsync exception, change directory
+         to "/" so that pfexec doesn't freak out when trying
+         to release the snapshot. pfexec bails out when it
+         tries to add cwd to it's path if cwd is non-existent 
+         which can be the case if the backup device suddenly
+         goes offline.
+
+2010-04-27 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Remember to also delete log files when deleting backups.
+
+2010-04-27 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Exit if effective UID of process is not 0 (root)
+
+2010-04-27 Niall Power - <niall.power@oracle.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py:
+         Send rsync loggint to individual log files on the backup
+         device. Delete log files when corresponding backup gets
+         deleted.
+         Create rsync backups in a temporary directory first and
+         move to permanent location when completed. Prevents 
+         incomplete backups appearing in backup view in Nautilus.
+         Also use "--inplace" rsync option to allow resumption of
+         partial (interrupted) backups.
+
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py:
+         Add shared key get/set methods for rsync SMF instance.
+         Use new "set_string_prop" Smf class method for setting
+         rsync target directory so that path names containing 
+         spaces can be correctly set. Conversely, strip out '\ '
+         space formatting characters returned by SMF in 
+         get_target_dir() method.
+
+       * usr/share/time-slider/lib/plugin/rsync/trigger.py:
+         Don't tag new snapshots whose filesystems are not mounted
+         Prevents piling up of snapshots from unmounted BEs. Might
+         be best to make this behaviour configurable via SMF.
+
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Clean up OK button clicked callback by farming out several
+         validation checks to separate methods. Add rsync config
+         checking method to chek configuration/selection of rsync
+         target device. Implement shared key checking to validate/
+         identify pre-configured backup devices. Rejects devices
+         configured for use on other systems. Add checks to ensure
+         target device is writable by root and supports hard links
+         as required for rsync incremental backups. Add a random
+         key generation function. Perform basic space checking on
+         rsync target device to see if it's big enough.
+
+       * usr/share/time-slider/lib/time_slider/smf.py:
+         Implement set_string_prop() method that allows white space
+         string characters.
+
+       * var/svc/manifest/application/time-slider-plugin.xml:
+         Remove rsync plugin's property override of
+         <plugin/trigger_on> and inherit defaults instead. Backing
+         up frequent snapshots caused near constant backup disk
+         churn.
+
+2010-04-16 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/zfs.py: Fix bug in 
+         method "create_auto_snapshot_set() where it would skip
+         the entire pool if the root of the pool was tagged and 
+         all datastets under the root inherited from it. Also,
+         use sorted lists and binary searching to speed up the
+         operation and avoid making repeated unnecessary calls
+         to Dataset.list_children() (the data is already provided)
+
+2010-04-15 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py: Clean up 
+         dangling holds on snapshots left by abnormally terminated
+         rsync transfers from previous invocations. Also, release
+         snapshot holds if an Rsync exception is caught during
+         transfer. Allows time-sliderd to delete snapshots when they
+         naturally expire.
+
+2010-04-13 Niall Power - <niall.power@sun.com>
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Fix broken target directory retrieval from FileChooser button
+
+2010-04-13 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py: Create a
+         RsyncBackup class to run rsync backup commands in a 
+         separate thread. Define Rsync exception clases and map
+         to expected rsync exit codes.
+         Modify toplevel backup path for backups to begin with:
+         <SMF defined target dir>/TIMESLIDER/<nodename>/
+         Deal with rsync exceptions raised and place into maintenance
+         state if non recoverable.
+         Try to recover space on target directory (work in progress)
+         Add debugging and error logging output.
+
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py: define
+         backup RSYNCDIRPREFIX to "TIMESLIDER".
+
+       * usr/share/time-slider/lib/time_slider/applet.py:
+         Use new backup path format as described above.
+
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Use new backup path format as described above.
+
+       * usr/share/time-slider/lib/time_slider/util.py:
+         Add general purpose syslog wrapper function.
+
+       * var/svc/manifest/application/time-slider-plugin.xml:
+         remove accidental definition of <plugin/target_dir>
+         Set to empty string value "" instead of a directory on my
+         own system. Doh.
+
+2010-04-01 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/timesliderd.py: insert a
+         'h' character between hour and minute values of auto snapshot
+         labels as a subsitute for the previously removed ':' character
+         used in time stamps. Makes life easier for nautilus component
+         and plays nicely with strptime()
+
+2010-04-01 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/applet.py: gio FileMonitor
+         events are inconsistent between UFS/ZFS filesystem mounting.
+         Ignore event type from gio FileMonitor and verify backup target
+         status manually using os.stat()
+
+2010-04-01 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/applet.py: Improve string
+         formatting on notifications and tooltips. Stop the status icon
+         blinking once the notification has been closed.
+       * usr/share/time-slider/lib/time_slider/setupgui.py: Forgot to
+         connect rsync folder selection to rsync SMF instance
+         configuration. Added. Also use get_current_folder() instead of
+         get_filename() to get correct folder from FileChooserButton
+         widget.
+
+2010-03-31 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/applet.py: Restrict manual
+         synchronisation menu item to priviliged users only (root or
+         users assigned Primary Administrator profile). Also, don't
+         bother popping up a right click menu if it's empty.
+
+2010-03-31 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/plugin/rsync/backup.py: Implement cleanup
+         of expired backups on rsync target directory. Uses same rules as
+         time-slider as defined by each auto-snapshot schedule's SMF instance
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py: Add a method to
+         return the list of archived schedules (ie. ones that don't get 
+         cleaned according to the normal schedule retention rules)
+       * usr/share/time-slider/lib/time_slider/applet.py: add a 
+         'Synchronize Now' menu item to the applet. Added gio based file
+         monitoring to keep track of when the rsync backup target directory
+         is mounted/unmounted and adjust menu sensitivty accordingly.
+       * usr/share/time-slider/lib/time_slider/autosnapsmf.py: Define 
+         SNAPLABELPREFIX as a constant for snapshot label names
+       * usr/share/time-slider/lib/time_slider/setupgui.py: Modify RBAC
+         rules to ensure that setup GUI is run with euid of root which is
+         necessary for validation and initialisation of rsync backup target
+         directory
+       * usr/share/time-slider/lib/time_slider/timesliderd.py: use 
+         SNAPLABELPREFIX constant instead of local multiply defined values.
+       * var/svc/manifest/application/time-slider-plugin.xml: Override
+         "plugin/trigger_on" value in rsync plugin manifest. Add a new
+         property "rsync/archived_schedules" to define snapshot schedules
+         that are archived as long as possible and not purged according
+         to the normal schule retention rules.
+
+2010-03-25 Niall Power - <niall.power@sun.com>
+
+       * etc/dbus-1/system.d/time-slider.conf: add policies for
+         rsync plugin's dbus service and methods.
+       * usr/share/time-slider/lib/plugin/rsync/backup.py: restructure script
+         to perform backups via a Gobject mainloop which is necessary to allow
+         it to send dbus notifications correctly. Adjust backup target dir
+         to use a rsync plugin specific subdirectory on the target dir
+         (.time-slider/rsync) - prevents borkage of mount points with 
+         unmounted filesystems. Use "-a" option with rsync command which 
+         covers all the desired arguments fo our rsync usage case (archival)
+         Add dbus method invocations. General cleanup and removal of commented
+         out code. Use lockfile to prevent multiple instances running at once.
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py: Add definitions
+         for backup subdirectory and filesystem property tag constants.
+       * usr/share/time-slider/lib/plugin/rsync/trigger.py: Use constants as
+         defined in rsyncsmf.py
+       * usr/share/time-slider/lib/time_slider/applet.py: Incorporate new 
+         RsyncNote class and other pieces from Krishnan Parthasarathi. Thanks
+         Krishan. Added signal handlers and tooltips/popups for dbus events 
+         sent from rsync plugin.
+       * usr/share/time-slider/lib/time_slider/dbussvc.py: New dbus signal
+         definitions added, including a few from Krishnan.
+       * usr/share/time-slider/lib/time_slider/setupgui.py: Perform validation
+         on target directory for rsync. Not exhaustive yet. Checks that target
+         directory isn't on a file system or pool that's been selected for
+         automatic snapshots.
+
+2010-03-11 Niall Power - <niall.power@sun.com>
+
+       Add rsync plugin (WORK IN PROGRESS), restructure SMF related code
+       and restructure file/directory layout to provide seperate 
+       subdirectories for plugins.
+
+       * Makefile: Add/remove files to (un)install rules.
+       * usr/lib/time-sliderd: Fix script invocation to invoke python2.6
+         explicitly (ie. do not use /usr/bin/env to source it)
+       * usr/share/time-slider/glade/time-slider-setup.glade: Add in UI
+         features to enable rsync backup configuration
+       * usr/share/time-slider/lib/time_slider/__init__.py: adjust sys.path
+         to allow importation from the plugin directory
+       * usr/share/time-slider/lib/time_slider/autosnapsmf.py: Refactor to
+         inehrit from the smf base object class (smf.py)
+       * usr/share/time-slider/lib/time_slider/deletegui.py: Remove import
+         of smfmanager module.
+       * usr/share/time-slider/lib/time_slider/setupgui.py: Remove import of
+         smfmanager module. Implement UI logic and view for rsync
+         configuration (filechooser, list view check buttons etc.)
+         Tie in with rsync plugin SMF backend. WORK IN  PROGRESS.
+       * usr/share/time-slider/lib/time_slider/timesliderd.py: Drop use of old
+         smfmanager class and replace with new smf and timeslidersmf  modules
+       * usr/share/time-slider/lib/time_slider/zfs.py: Misc. cleanups. Define
+         proper Exception classes for ZFS and ZPool errors and raise them when
+         appropriate. Old style string based exceptions not supported in python
+         2.6
+       * var/svc/manifest/application/time-slider-plugin.xml: Define rsync
+         plugin SMF instance and properties.
+       * usr/lib/time-slider-zfssend: Removed. Replaced by:
+         usr/lib/time-slider/plugins/zfssend/zfssend
+       * usr/share/time-slider/lib/time_slider/plugin.py: Removed. Replaced by:
+         usr/share/time-slider/lib/plugin/plugin.py
+       * usr/share/time-slider/lib/time_slider/zfssend.py: Removed. Replaced by:
+         usr/share/time-slider/lib/plugin/zfssend/zfssend.py
+       * lib/svc/method/time-slider-rsync: Added. Starts stops rsync plugin SMF
+         instance and sets up cron job for rsync-backup script.
+       * usr/lib/time-slider/plugins/rsync/rsync-backup: Added. Performs
+         asynchronouse rsync backup of zfs snapshots previously tagged for backup.
+         WORK IN PROGRESS
+       * usr/lib/time-slider/plugins/rsync/rsync-trigger: Provides trigger
+         mechanisem for time-slider to call when snapshots created. Queues up
+         zfs snapshots for later backup using rsync-backup script.
+       * usr/lib/time-slider/plugins/zfssend/zfssend: Replacement of
+         usr/lib/time-slider-zfssend
+       * usr/share/time-slider/lib/plugin/__init__.py: Added. Initialises new
+         plugin module
+       * usr/share/time-slider/lib/plugin/plugin.py: Replacement of:
+         usr/share/time-slider/lib/time_slider/plugin.py
+       * usr/share/time-slider/lib/plugin/pluginsmf.py: Added. Defines plugin
+         SMF class specialised for time-slider plugin SMF instances
+       * usr/share/time-slider/lib/plugin/rsync/__init__.py: Added. Initialises
+         new rsync plugin module.
+       * usr/share/time-slider/lib/plugin/rsync/backup.py: Added. Main code
+         block for rsync-backup script.
+       * usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py: Added. Defines
+         SMF class specialised for rsync plugin SMF instance.
+       * usr/share/time-slider/lib/plugin/rsync/trigger.py: Added. Main code
+         block for rsync-trigger script.
+       * usr/share/time-slider/lib/plugin/zfssend/__init__.py: Added.
+         Initialises zfssend plugin module.
+       * usr/share/time-slider/lib/plugin/zfssend/zfssend.py: Replacement for
+         usr/share/time-slider/lib/time_slider/zfssend.py
+       * usr/share/time-slider/lib/time_slider/smf.py: Added. Provides cleaner
+         and more structured base class for generic SMF instances and and is
+         inherited by timeslidersmf, pluginsmf, rsyncsmf derived classes.
+         Provides common methods to enable/disable and get/set property values
+         and refresh and query service state.
+       * usr/share/time-slider/lib/time_slider/timeslidersmf.py: Defines
+         SMF class and methods specific to the time-slider SMF instances.
+
+2010-02-04 Niall Power - <niall.power@sun.com>
+
+       * Makefike: Add lib/svc/method/time-slider-plugin to
+         install/uninstall rules.
+       * lib/svc/method/time-slider-plugin: Added.
+         Provides simple, generic plugin start method.
+       * var/svc/manifest/application/time-slider-plugin.xml:
+         Added comments for time-slider-plugin method, advising
+         that non trivial plugin instances should provide their
+         own specific methods.
+
+2010-02-03 Niall Power - <niall.power@sun.com>
+
+       * var/svc/manifest/application/time-slider.xml:
+         Define new property "zfs/sep". Taken for zfs-auto-snapshot,
+         allows custom definition of a separator character for snapshot
+         datestamps that can work on filesystems that previously choked
+         on the ":" characted such as CIFS, PCFS.
+       * usr/share/time-slider/lib/time_slider/smfmanager.py: Added new
+         method to get zfs/sep property.
+       * usr/share/time-slider/lib/time_slider/timesliderd.py: modify
+         snapshot creation and listing operations to use the new zfs/sep
+         property, while maintaining compatibility with old snapshot
+         datestamps that used the ":" character.
+
+2010-02-02 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/plugin.py:
+         Fix invalid function call "debug()" should be "util.debug()" when
+         reporting disabled plugin in PluginManager.refresh()
+         Missing "()" in method call Plugin.is_running() in Plugin.refresh()
+
+2010-01-26 Niall Power - <niall.power@sun.com>
+
+       * VERSION: bump to 0.2.96
+       * Use explicit path: "/usr/bin/python2.6" to reference python interpreter
+         instead of relying on "/usr/bin/env" to find it.
+       * Add plugin framework to enable user defined plugins to be executed after
+         snapshots get taken by time-sliderd. Plugins are based on the SMF service
+         framework and plugins are defined as instances of the base SMV service:
+         svc:/application/time-slider/plugin
+       * Provide a "zfs-send" plugin as a replacement for the zfs-auto-snapshot
+         provided "backup-save-cmd" property.
+       * Add util.py to define two commoonly used utility functions: debug/logging
+         and command spawning. Reduces lines of code and duplication.
+       * Refactor all python files to use util.run_command() convenience function
+         where possible.
+       * Fix a bug where time-sliderd emits warnings and tries to cleanup pools
+         upon which it creates no snapshots. Also make time-sliderd more descriminating
+         in general and able to identify snapshots it created from backups of snapshots
+         it create (via zfs send/receive) by checking for the auto-snapshot property
+         corresponding to the filesystem/volume of snapshots.
+       * TODO: SMF code is a bit all over the place and could do with proper stucturing
+
+2009-11-27 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/timesliderd.py: fixed a date
+         calculation bug whereby a schedule with a period in months next falls
+         due on December. Was getting incorrectly modulused to 0.
+
+2009-11-04 Niall Power - <niall.power@sun.com>
+
+       * VERSION: bump to 0.2.95
+       * Move to python2.6
+       * Drop dependency on zfs-auto-snapshot methods and implement our own
+         snapshotting mechanism in the form of time-sliderd
+       * Add dbus system bus notification and notification applet, replacing
+         the previous ugly hack of su to logged in user ID and running
+         notify-send.
+       * Enhance all .py modules to use python subprocess module when spawning
+         commands instead of os.popen.
+       * Add SMF manifest for system/filesystem/auto-snapshot to replace 
+         systems snapshot configuration previously supplied by
+         zfs-auto-snapshot. Generally compatible but cleaned up by dropping
+         some of zfs-auto-snapshot's more quirky or deprecated configuration
+         options.
+
+2009-07-08 Niall Power - <niall.power@sun.com>
+
+       * VERSION: bump to 0.2.10
+       * Fix defect 8667 in following source files:
+       * usr/share/time-slider/lib/time_slider/cleanupmanager.py: Refactor
+         code to modified zfs.py APIs, remove some dead code, make capacity
+         checks conditional where possible.
+       * usr/share/time-slider/lib/time_slider/deletegui.py: minor code 
+         refactoring to match zfs.py API changes.
+       * usr/share/time-slider/lib/time_slider/setupgui.py: Remove references
+         to zfscontroller module which has been removed. Uses zfs.py 
+         exclusively now. Refactor for zfs.py changes
+       * usr/share/time-slider/lib/time_slider/zfscontroller.py: removed.
+         Very little functionality and nothing that shouldn't be in zfs.py
+       * usr/share/time-slider/lib/time_slider/zfs/py: New class definition
+         for "Datasets" which stores all system snapshots, filesystems and
+         volumes in a cache. Existing Dataset, Filesystem, Snapshot and Volume
+         class methods now use the global Datasets cache for querying and
+         listing instead of making zfs(1m) spawned commands.
+
+2009-05-18 Niall Power - <niall.power@sun.com>
+
+        * usr/share/time-slider/lib/time_slider/cleanupmanager.py
+          Cleanup both Filesystem and Volume snapshots. Fixes d.o.o 8454
+        * usr/share/time-slider/lib/time_slider/setupgui.py: Prepend private
+          class methods with "__" in accordance with python coding standards.
+        * usr/share/time-slider/lib/time_slider/smfmanager.py: Use predefined
+          macros for ZFS commands instead of hardcoding path in the code.
+        * usr/share/time-slider/lib/time_slider/zfs.py: Improve object
+          hierarchy and inheritance tree. Rename some methods for improved
+          clarity of purpose. Improve method and function documentation.
+          Add capability to deal with ZFS volumes. Fixes d.o.o 8454 & 8685
+2009-05-13 Harry Fu - <harry.fu@sun.com>
+
+       * VERSION: bump to 0.2.9
+
+2009-04-10 Erwann Chenede - <erwann.chenede@sun.com>
+
+       * /usr/share/time-slider/lib/time_slider/fileversion.py:
+         used gobject.idle_add instead of gtk.gdk.threads_* fixes
+         7319
+
+2009-04-09 Erwann Chenede - <erwann.chenede@sun.com>
+
+       * /usr/share/time-slider/lib/time_slider/fileversion.py:
+         removed hard dependency on external thumbnailer and meld 
+         fixes #7502
+
+2009-04-07  Niall Power <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/cleanupmanager.py
+       * usr/share/time-slider/lib/time_slider/deletegui.py
+       * usr/share/time-slider/lib/time_slider/smfmanager.py
+       * usr/share/time-slider/lib/time_slider/zfs.py
+       * usr/share/time-slider/lib/time_slider/zfscontroller.py:
+         Use macro substitution to specify full paths to all spawned
+         commands (zfs, zpool, svcadm, svccfg, svcprop, pfexec) so that
+         commands work independently of user's PATH environment.
+         Fixes opensolaris defect #7396
+
+2009-03-01  Niall Power <niall.power@sun.com>
+
+       * VERSION: bump to 0.2.6
+       * Makefile: Pick up PYTHON environment variable. Enhancement for
+         fix to 6754650
+       * usr/share/time-slider/lib/time_slider/setupgui.py: Allow filesystems
+         to inherit properties from their parent instead of locally tagging
+         every filesystem with the required property setting.
+       * usr/share/time-slider/lib/time_slider/zfs.py: Add an "inherit" argument
+         to Filesystem.commit_state() to allow the fileystem to inherit from
+         it's parent when setting the auto-snapshot property.
+
+2009-02-19  Takao Fujiwara  <takao.fujiwara@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/deletegui.py: updated
+       the comments because translators are confused it.
+       * usr/share/time-slider/lib/time_slider/snapnowui.py: updated
+       the gettext "%s" so that translators can change the oder of "%s".
+
+2009-02-05 Niall Power - <niall.power@sun.com>
+
+       * VERSION: bump to 0.2.5
+       * Makefile: don't install .pyc files, but generate them as part
+         of "install:" rule. Fixes bugster: 6754650
+       * py-compile.py: Prepend "DESTDIR" to compile python bytecode
+         within the installed directory tree.
+       * usr/share/time-slider/lib/time_slider/__init__.pyc: removed
+       * usr/share/time-slider/lib/time_slider/cleanupmanager.pyc: removed
+       * usr/share/time-slider/lib/time_slider/deletegui.pyc: removed
+       * usr/share/time-slider/lib/time_slider/fileversion.pyc: removed
+       * usr/share/time-slider/lib/time_slider/notification.pyc: removed
+       * usr/share/time-slider/lib/time_slider/rbac.pyc: removed
+       * usr/share/time-slider/lib/time_slider/setupgui.pyc: removed
+       * usr/share/time-slider/lib/time_slider/smfmanager.pyc: removed
+       * usr/share/time-slider/lib/time_slider/snapnowui.pyc: removed
+       * usr/share/time-slider/lib/time_slider/zfs.pyc: removed
+       * usr/share/time-slider/lib/time_slider/zfscontroller.pyc: removed
+
+
+2009-01-23 Erwann Chenede - <erwann.chenede@sun.com>
+
+       * VERSION: bump version to 0.2.4
+       * Makefile : added new files
+       * usr/lib/time-slider-version
+       * usr/share/time-slider/glade/time-slider-version.glade
+       * usr/share/time-slider/lib/time_slider/fileversion.py
+       * usr/share/time-slider/lib/time_slider/fileversion.pyc :
+         Initial implementation of the file version explorer app
+       
+2009-01-16  Takao Fujiwara  <takao.fujiwara@sun.com>
+
+       * po/POTFILES.in: Update with the latest files.
+       * usr/share/time-slider/glade/time-slider-delete.glade:
+       * usr/share/time-slider/glade/time-slider-setup.glade:
+       * usr/share/time-slider/glade/time-slider-snapshot.glade:
+         Update to remove "translatable" tag for GTK textdomain.
+       * usr/share/time-slider/lib/time_slider/deletegui.py:
+         Update to localize date and add the encoding conversion.
+       * usr/share/time-slider/lib/time_slider/setupgui.py:
+         Update to localize "legacy".
+       * usr/share/time-slider/lib/time_slider/snapnowui.py:
+         Update to add gettext.
+
+2009-01-09 Niall Power - <niall.power@sun.com>
+
+       * VERSION: bump version to 0.2.3
+       * usr/share/time-slider/glade/time-slider-delete.glade:
+         add progress dialog for snapshot scanning feedback
+       * usr/share/time-slider/lib/time_slider/deletegui.py:
+         restructure initialisation code and run snapshot scanning in it's
+         own thread so that feedback can be give to user via a progress dialog
+         Prevents the app appearing dead when dealing with huge numbers of
+         snapshots.
+
+2009-01-09 Erwann Chenede - <erwann.chenede@sun.com>
+
+       * Makefile: added newly introduced file
+       * usr/share/time-slider/lib/time_slider/snapnowui.py: removed print
+
+2009-01-09 Erwann Chenede - <erwann.chenede@sun.com>
+
+       * usr/lib/time-slider-snapshot:
+       * usr/share/time-slider/glade/time-slider-snapshot.glade:
+       * usr/share/time-slider/lib/time_slider/snapnowui.py:
+         Initial implementation of the snapshot now dialog
+
+2008-12-17 Niall Power - <niall.powr@sun.com>
+
+       * VERSION: bump version to 0.2.2
+       * lib/svc/method/time-slider: remove "set -x" command which errantly turns
+         on debug mode. Fixes bugzilla defect #5067
+       * usr/share/time-slider/glade/time-slider-setup.glade: Change mnemonic key for
+         "Custom" radio button from "C" to "u". C is already in use by "Cancel" button.
+         Fixes bugzilla defect #3986
+       * usr/share/time-slider/lib/time_slider/setupgui.py: Change error dialog text to
+         instruct user to consult "svcs -xv" instead of "svcs(1) man page" for more info
+         when time-slider SMF instance is placed into offline state by SMF.
+         Fixes bugzilla defect #5804
+
+2008-12-17 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/cleanupmanager.py: Check
+         ps commmand output before accessing it by catching IndexError
+         exceptions. Prevents root's mailbox being spammed by cron.
+         Fixes bugster #6758575
+
+2008-12-12 Niall Power - <niall.power@sun.com>
+
+       * usr/share/time-slider/lib/time_slider/cleanupmanager.py: Implement
+         destruction of older snapshots since zfs-auto-snapshot only does
+         snapshot destruction recursively and we break the recursion by
+         deleting individual snapshots instead of recursive sets.
+
+2008-12-05 Niall Power - <niall.power@sun.com>
+       * usr/share/time-slider/lib/time_slider/setupgui.py
+         Fixed a patch generation problem when launching time-slider-delete
+
+2008-12-05 Niall Power - <niall.power@sun.com>
+
+       * VERSION: bumped to 0.2.1
+       * Makefile: Minor cleanups
+       * usr/share/time-slider/lib/time_slider/cleanupmanager.py: add
+         perform_purge method to clean up zero sized snapshots under 
+         safe circumstances so that the system doesn't become cluttered
+         with too many permanently zero sized snapshots.
+         Rewrote emercency space makeing cleanup alogorithm in run_cleanup  
+         to be more efficient and spawn far fewer shell commands. No longer
+       usr/share/time-slider/lib/time_slider/setupgui.py: Change error dialog text to
+         instruct user to consult "svcs -xv" instead of "svcs(1) man page" for more info
+         when time-slider SMF instance is placed into offline state by SMF.
+         Fixes bugzilla defect #5804
+  does recursive snapshot deletion since the above changes will break
+         the recursive snapshot chain in most cases and recursive deletion
+         is now overkill since individual snapshots should be larger in size
+         and yield larger space savings per snapshot deleted.
+         Fixed notification bug where notification would happen twice if
+         gnome-session is launched via dbus-launch.
+       * usr/share/time-slider/lib/time_slider/deletegui.py: move
+         __get_cloned_snapshots() method to a public function in zfs.py
+       * usr/share/time-slider/lib/time_slider/notification.py: fix typo
+         bug in send_to_desktop() where initial warning level was set to
+         90000 which broke desktop notification. Should be 0.
+       * usr/share/time-slider/lib/time_slider/zfs.py: Add new function:
+         list_cloned_snapshots() to list snapshots that have cloned filesystem
+         based on them.
+
+2008-12-02 Niall Power - <niall.power@sun.com>
+
+       * Makefile: Fix install target error that didn't install both glade
+         files
+
+2008-12-02 Niall Power - <niall.power@sun.com>
+
+       * VERSION: bumped to 0.2.0
+       * Makefile: added new files to install and uninstall targets
+       * data/Makefile: adjusted for renamed .desktop.in file
+       * usr/share/time-slider/glade/time-slider-setup.glade: Added launch
+         button for snapshot deletion GUI. Rename window title from 
+         "Time Slider Setup" to "Time Slider Manager"
+       * usr/share/time-slider/lib/time_slider/setupgui.py: add launch handler
+         for time-slider-delete
+       * usr/share/time-slider/lib/time_slider/zfs.py: Add utility functions
+         for time-slider-delete for listing and creating snapshot objects
+       * data/time-slider.desktop.in renamed from time-slider-setup.desktop.in
+       * usr/lib/time-slider-delete: Added new snapshot deleter program to
+         allow snapshot browsing/deletion.
+       * usr/share/applications/time-slider.desktop: renamef from 
+         time-slider-setup.desktop
+       * usr/share/time-slider/glade/time-slider-delete.glade: Added glade UI
+         file for snapshot delete GUI
+       * usr/share/time-slider/lib/time_slider/deletegui.py: Added main python
+         code for listing and deleting snapshots
+
+2008-12-02 Niall Power - <niall.power@sun.com>
+
+       * py-compile.py: Added to insure pyc files are in sync with
+         .py sources. Fixes bugster #6754650
+       * VERSION: Added version file. Bump to 0.1.5
+       * SUNWgnome-time-slider.spec: removd because spec file is
+         in spec-files-other repository on opensolaris.org
+       * Makefile: added "dist" target for creating dist bz2 tarballs
+
+2008-10-23 Erwann Chenede - <erwann.chenede@sun.com>
+
+       * usr/share/icons/hicolor/16x16/apps/time-slider-setup.png 
+       * usr/share/icons/hicolor/24x24/apps/time-slider-setup.png 
+       * usr/share/icons/hicolor/32x32/apps/time-slider-setup.png 
+       * usr/share/icons/hicolor/36x36/apps/time-slider-setup.png 
+       * usr/share/icons/hicolor/48x48/apps/time-slider-setup.png 
+       * usr/share/icons/hicolor/72x72/apps/time-slider-setup.png :
+         new icon (4182)
+
+2008-10-20   Takao Fujiwara  <takao.fujiwara@sun.com>
+
+       * Makefile: Updated to load po/Makefile and data/Makefile.
+       * data/Makefile: Added to generate .desktop files.
+       * data/time-slider-setup.desktop.in: Added for intltool.
+       * po: Added for intltool.
+
+2008-09-11 Niall Power - <niall.power@sun.com>
+
+       * Initial import of Time Slider service
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..346ebe8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,152 @@
+include VERSION
+
+mkinstalldirs = /usr/bin/mkdir -p
+INSTALL = /usr/sbin/install
+INSTALL_DATA = ${INSTALL} -u root -g bin -m 644 -f
+INSTALL_PROGRAM = ${INSTALL} -u root -g bin -f
+INSTALL_SCRIPT = ${INSTALL} -f
+RM = /usr/bin/rm -f
+RMRF = /usr/bin/rm -Rf
+RMDIR = /usr/bin/rmdir
+# Use python 2.6 if PYTHON environent is not set
+ifeq ($(strip $(PYTHON)),)
+PYTHON = /usr/bin/python2.6
+endif
+
+SUBDIRS = po data
+
+DISTFILES = Authors \
+                       VERSION \
+                       ChangeLog \
+                       Makefile \
+                       py-compile.py \
+                       $(SUBDIRS) \
+                       lib \
+                       usr \
+                       var \
+                       etc
+
+clean:
+       $(RM) usr/share/time-slider/lib/time_slider/*.pyc
+       $(RM) usr/share/time-slider/lib/plugin/*.pyc
+       $(RM) usr/share/time-slider/lib/plugin/rsync/*.pyc
+       $(RM) usr/share/time-slider/lib/plugin/zfssend/*.pyc
+
+all:
+       for subdir in $(SUBDIRS); do \
+         cd $$subdir; make; cd ..;\
+       done
+       echo $(VERSION)
+
+dist: clean all
+       $(RMRF) time-slider-$(VERSION)
+       mkdir time-slider-$(VERSION)
+       cp -pR $(DISTFILES) time-slider-$(VERSION)
+       /usr/bin/tar cf - time-slider-$(VERSION) | bzip2 > time-slider-$(VERSION).tar.bz2
+       $(RMRF) time-slider-$(VERSION)
+
+install:
+       for subdir in $(SUBDIRS); do \
+         cd $$subdir; \
+         make DESTDIR=$(DESTDIR) GETTEXT_PACKAGE=time-slider install; \
+         cd ..;\
+       done
+       $(mkinstalldirs) $(DESTDIR)/etc/dbus-1/system.d
+       $(INSTALL_DATA) $(DESTDIR)/etc/dbus-1/system.d etc/dbus-1/system.d/time-slider.conf
+       $(mkinstalldirs) $(DESTDIR)/etc/xdg/autostart
+       $(INSTALL_DATA) $(DESTDIR)/etc/xdg/autostart etc/xdg/autostart/*.desktop
+       $(mkinstalldirs) $(DESTDIR)/lib/svc/method
+       $(INSTALL_SCRIPT) $(DESTDIR)/lib/svc/method lib/svc/method/time-slider
+       $(INSTALL_SCRIPT) $(DESTDIR)/lib/svc/method lib/svc/method/time-slider-plugin
+       $(INSTALL_SCRIPT) $(DESTDIR)/lib/svc/method lib/svc/method/time-slider-rsync
+       $(mkinstalldirs) $(DESTDIR)/usr/bin
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/bin usr/bin/time-slider-setup
+       $(mkinstalldirs) $(DESTDIR)/usr/lib/time-slider/plugins/rsync
+       $(mkinstalldirs) $(DESTDIR)/usr/lib/time-slider/plugins/zfssend
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib usr/lib/time-sliderd
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib usr/lib/time-slider-delete
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib usr/lib/time-slider-notify
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib usr/lib/time-slider-snapshot
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib usr/lib/time-slider-version
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib/time-slider/plugins/zfssend usr/lib/time-slider/plugins/zfssend/zfssend
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib/time-slider/plugins/rsync usr/lib/time-slider/plugins/rsync/rsync-trigger
+       $(INSTALL_PROGRAM) $(DESTDIR)/usr/lib/time-slider/plugins/rsync usr/lib/time-slider/plugins/rsync/rsync-backup
+       $(mkinstalldirs) $(DESTDIR)/usr/share/applications
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/applications usr/share/applications/time-slider.desktop
+       $(mkinstalldirs) $(DESTDIR)/usr/share/icons/hicolor/16x16/apps
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/icons/hicolor/16x16/apps usr/share/icons/hicolor/16x16/apps/time-slider-setup.png
+       $(mkinstalldirs) $(DESTDIR)/usr/share/icons/hicolor/24x24/apps
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/icons/hicolor/24x24/apps usr/share/icons/hicolor/24x24/apps/time-slider-setup.png
+       $(mkinstalldirs) $(DESTDIR)/usr/share/icons/hicolor/32x32/apps
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/icons/hicolor/32x32/apps usr/share/icons/hicolor/32x32/apps/time-slider-setup.png
+       $(mkinstalldirs) $(DESTDIR)/usr/share/icons/hicolor/36x36/apps
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/icons/hicolor/36x36/apps usr/share/icons/hicolor/36x36/apps/time-slider-setup.png
+       $(mkinstalldirs) $(DESTDIR)/usr/share/icons/hicolor/48x48/apps
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/icons/hicolor/48x48/apps usr/share/icons/hicolor/48x48/apps/time-slider-setup.png
+       $(mkinstalldirs) $(DESTDIR)/usr/share/icons/hicolor/72x72/apps
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/icons/hicolor/72x72/apps usr/share/icons/hicolor/72x72/apps/time-slider-setup.png
+       $(mkinstalldirs) $(DESTDIR)/usr/share/icons/hicolor/96x96/apps
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/icons/hicolor/96x96/apps usr/share/icons/hicolor/96x96/apps/time-slider-setup.png
+       $(mkinstalldirs) $(DESTDIR)/usr/share/time-slider/glade
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/glade usr/share/time-slider/glade/time-slider-delete.glade
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/glade usr/share/time-slider/glade/time-slider-setup.glade
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/glade usr/share/time-slider/glade/time-slider-snapshot.glade
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/glade usr/share/time-slider/glade/time-slider-version.glade
+       $(mkinstalldirs) $(DESTDIR)/usr/share/time-slider/lib/time_slider
+       for file in usr/share/time-slider/lib/time_slider/*.py; do \
+               if test -f $$file ; then \
+                 $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/lib/time_slider $$file; \
+               fi; \
+       done
+       $(mkinstalldirs) $(DESTDIR)/usr/share/time-slider/lib/plugin
+       for file in usr/share/time-slider/lib/plugin/*.py; do \
+               if test -f $$file ; then \
+                 $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/lib/plugin $$file; \
+               fi; \
+       done
+       $(mkinstalldirs) $(DESTDIR)/usr/share/time-slider/lib/plugin/rsync
+       for file in usr/share/time-slider/lib/plugin/rsync/*.py; do \
+               if test -f $$file ; then \
+                 $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/lib/plugin/rsync $$file; \
+               fi; \
+       done
+       $(mkinstalldirs) $(DESTDIR)/usr/share/time-slider/lib/plugin/zfssend
+       for file in usr/share/time-slider/lib/plugin/zfssend/*.py; do \
+               if test -f $$file ; then \
+                 $(INSTALL_DATA) $(DESTDIR)/usr/share/time-slider/lib/plugin/zfssend $$file; \
+               fi; \
+       done
+       $(mkinstalldirs) $(DESTDIR)/var/svc/manifest/application
+       $(INSTALL_DATA) $(DESTDIR)/var/svc/manifest/application var/svc/manifest/application/time-slider.xml
+       $(INSTALL_DATA) $(DESTDIR)/var/svc/manifest/application var/svc/manifest/application/time-slider-plugin.xml
+       $(mkinstalldirs) $(DESTDIR)/var/svc/manifest/system/filesystem
+       $(INSTALL_DATA) $(DESTDIR)/var/svc/manifest/system/filesystem var/svc/manifest/system/filesystem/auto-snapshot.xml
+       $(PYTHON) py-compile.py
+       
+uninstall:
+       for subdir in $(SUBDIRS); do \
+         cd $$subdir; \
+         make DESTDIR=$(DESTDIR) GETTEXT_PACKAGE=time-slider uninstall; \
+         cd ..;\
+       done
+       $(RM) $(DESTDIR)/etc/dbus-1/system.d/time-slider.conf
+       $(RM) $(DESTDIR)/etc/xdg/autostart/time-slider-notify.desktop
+       $(RM) $(DESTDIR)/lib/svc/method/time-slider
+       $(RM) $(DESTDIR)/lib/svc/method/time-slider-plugin
+       $(RM) $(DESTDIR)/lib/svc/method/time-slider-rsync
+       $(RM) $(DESTDIR)/usr/bin/time-slider-setup
+       $(RM) $(DESTDIR)/usr/lib/time-sliderd
+       $(RM) $(DESTDIR)/usr/lib/time-slider-delete
+       $(RM) $(DESTDIR)/usr/lib/time-slider-notify
+       $(RM) $(DESTDIR)/usr/lib/time-slider-snapshot
+       $(RM) $(DESTDIR)/usr/lib/time-slider-version
+       $(RM) $(DESTDIR)/usr/lib/time-slider-zfssend
+       $(RM) $(DESTDIR)/usr/lib/time-slider-rsync
+       $(RMRF) $(DESTDIR)/usr/lib/time-slider/plugins/rsync
+       $(RMRF) $(DESTDIR)/usr/lib/time-slider/plugins/zfssend
+       $(RM) $(DESTDIR)/usr/share/applications/time-slider.desktop
+       $(RM) $(DESTDIR)/usr/share/icons/hicolor/*/apps/time-slider-setup.png
+       $(RMRF) $(DESTDIR)/usr/share/time-slider
+       $(RM) $(DESTDIR)/var/svc/manifest/application/time-slider.xml
+       $(RM) $(DESTDIR)/var/svc/manifest/application/time-slider-plugin.xml
+       $(RM) $(DESTDIR)/var/svc/manifest/system/filesystem/auto-snapshot.xml
diff --git a/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..8e15db9
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+VERSION = 0.2.98
diff --git a/data/Makefile b/data/Makefile
new file mode 100644 (file)
index 0000000..4855402
--- /dev/null
@@ -0,0 +1,23 @@
+
+top_builddir = ..
+top_srcdir = ..
+mkinstalldirs = /usr/bin/mkdir -p
+INSTALL = /usr/sbin/install
+INSTALL_DATA = ${INSTALL} -u root -g bin -m 644 -f
+RM = /usr/bin/rm -f
+RMDIR = /usr/bin/rmdir
+INTLTOOL_MERGE = /usr/bin/intltool-merge
+desktop_in_files = time-slider.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+all: $(desktop_DATA)
+
+install:
+       $(mkinstalldirs) $(DESTDIR)/usr/share/applications
+       $(INSTALL_DATA) $(DESTDIR)/usr/share/applications time-slider.desktop
+
+uninstall:
+       $(RM) $(DESTDIR)/usr/share/applications/time-slider.desktop
+
+%.desktop:   %.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
diff --git a/data/time-slider.desktop b/data/time-slider.desktop
new file mode 100644 (file)
index 0000000..7ecf0a8
--- /dev/null
@@ -0,0 +1,44 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Time Slider
+Name[ar]=شريط تمرير الوقت 
+Name[ca]=Time Slider
+Name[cs]=Time Slider
+Name[de]=Zeit-Schieberegler
+Name[es]=Deslizador de tiempo
+Name[fr]=Curseur temporel
+Name[hu]=Time Slider
+Name[id]=Time Slider
+Name[it]=Time Slider
+Name[ja]=タイムスライダ
+Name[ko]=시간 슬라이더
+Name[nl]=Tijd glijder
+Name[pl]=Time Slider
+Name[pt_BR]=Barra deslizante de tempo
+Name[zh_CN]=时间滑块
+Name[zh_HK]=時間滑動軸
+Name[zh_TW]=時間滑動軸
+Comment=Configure the system to take automatic snapshots of your data
+Comment[ar]=تاكيد النظام على أخذ صورة عن النظام عن البيانات 
+Comment[ca]=Configurar el sistema per a fer instantànies automàtiques de les vostres dades
+Comment[cs]=Nakonfigurujte si systém tak, aby vytvářel automatické snímky Vašich dat
+Comment[de]=System für automatische Snapshots Ihrer Daten konfigurieren
+Comment[es]=Configurar el sistema para tomar instantáneas de manera automática de los datos
+Comment[fr]=Configurer le système de manière à prendre des instantanés automatiques des données
+Comment[hu]=A rendszer beállítása arra, hogy automatikusan mentse az Ön adatait
+Comment[id]=   
+Comment[it]=Configurare il sistema per fare delle istantanee automatiche dei propri dati
+Comment[ja]=自動的にデータのスナップショットを作成するようにシステムを構成します
+Comment[ko]=사용자 데이터의 자동 스냅샷을 만들도록 시스템 구성
+Comment[nl]=Configureer het systeem om automatische momentopnamen van je gegevens te nemen
+Comment[pl]=Skonfiguruj system do automatycznego wykonywania migawek twoich danych 
+Comment[pt_BR]=Configurar o sistema para realizar instantâneos automáticos dos dados
+Comment[zh_CN]=将系统配置为自动捕获数据的快照
+Comment[zh_HK]=將系統配置為自動對資料執行快照
+Comment[zh_TW]=將系統配置為自動對資料執行快照
+Terminal=false
+Type=Application
+StartupNotify=true
+Exec=time-slider-setup
+Icon=time-slider-setup
+Categories=Application;System;Settings
diff --git a/data/time-slider.desktop.in b/data/time-slider.desktop.in
new file mode 100644 (file)
index 0000000..a4f945a
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Time Slider
+_Comment=Configure the system to take automatic snapshots of your data
+Terminal=false
+Type=Application
+StartupNotify=true
+Exec=time-slider-setup
+Icon=time-slider-setup
+Categories=Application;System;Settings
diff --git a/etc/dbus-1/system.d/time-slider.conf b/etc/dbus-1/system.d/time-slider.conf
new file mode 100644 (file)
index 0000000..10506c5
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE busconfig PUBLIC
+          "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+          "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <!-- Only root or user zfssnap can own the TimeSlider service -->
+  <policy user="zfssnap">
+    <allow own="org.opensolaris.TimeSlider"/>
+  </policy>
+  <policy user="root">
+    <allow own="org.opensolaris.TimeSlider"/>
+  </policy>
+
+  <!-- Only root or user zfssnap can own the rsync service -->
+  <policy user="zfssnap">
+    <allow own="org.opensolaris.TimeSlider.plugin.rsync"/>
+  </policy>
+  <policy user="root">
+    <allow own="org.opensolaris.TimeSlider.plugin.rsync"/>
+  </policy>
+
+  <!-- Only root or user zfssnap can own the config service -->
+  <policy user="zfssnap">
+    <allow own="org.opensolaris.TimeSlider.config"/>
+  </policy>
+  <policy user="root">
+    <allow own="org.opensolaris.TimeSlider.config"/>
+  </policy>
+
+  <!-- Allow anyone to invoke methods on time-sliderd -->
+  <policy context="default">
+    <allow send_destination="org.opensolaris.TimeSlider"/>
+    <allow receive_sender="org.opensolaris.TimeSlider"/>
+  </policy>
+
+  <!-- Allow anyone to invoke methods on the rsync plugin -->
+  <policy context="default">
+    <allow send_destination="org.opensolaris.TimeSlider.plugin.rsync"/>
+    <allow receive_sender="org.opensolaris.TimeSlider.plugin.rsync"/>
+  </policy>
+
+  <!-- Allow anyone to invoke methods on the config service -->
+  <policy context="default">
+    <allow send_destination="org.opensolaris.TimeSlider.config"/>
+    <allow receive_sender="org.opensolaris.TimeSlider.config"/>
+  </policy>
+
+</busconfig>
diff --git a/etc/xdg/autostart/time-slider-notify.desktop b/etc/xdg/autostart/time-slider-notify.desktop
new file mode 100644 (file)
index 0000000..06af0ff
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Time Slider notification applet
+Comment=Show Time Slider status and notifications
+Icon=time-slider-setup
+Exec=/usr/lib/time-slider-notify
+Terminal=false
+Type=Application
+Categories=
+X-GNOME-Autostart-enabled=true
diff --git a/lib/svc/method/time-slider b/lib/svc/method/time-slider
new file mode 100755 (executable)
index 0000000..4ad7614
--- /dev/null
@@ -0,0 +1,97 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident        "%Z%%M% %I%     %E% SMI"
+
+. /lib/svc/share/smf_include.sh
+
+
+# Given the exit status of a command, an integer, 0 if the command completed
+# without errors. If the command exited with errors we degrade the
+# state of this service into maintenance mode. If a 3rd argument is presented
+# we don't degrade the service. We also log an error message as passed into
+# this function.
+#
+function check_failure { # integer exit status, error message, non-fatal flag
+
+       typeset RESULT=$1
+       typeset ERR_MSG=$2
+       typeset NON_FATAL=$3
+
+       if [ $RESULT -ne 0 ] ; then
+           print_log "Error: $ERR_MSG"
+           if [ -z "${NON_FATAL}" ] ; then
+               print_log "Moving service $SMF_FMRI to maintenance mode."
+               svcadm mark maintenance $SMF_FMRI
+           fi
+       fi
+
+}
+
+
+# A function we use to emit output. Right now, this goes to syslog via logger(1)
+# as well as being echoed to stdout which will result in it being picked up by
+# SMF if the $LOG variable is null.
+#
+function print_log { # message to display
+       logger -t time-slider -p daemon.notice $*
+       echo $*
+}
+
+# this function removes any left over cron jobs belonging to
+# legacy zfs-auto-snapshot
+#
+function remove_legacy_cronjobs {
+
+       crontab -l | grep -v "/lib/svc/method/zfs-auto-snapshot" \
+           > /tmp/saved-crontab.$$
+
+       crontab /tmp/saved-crontab.$$
+       check_failure $? "Unable to remove legacy zfs-auto-snaphot cron jobs" "NON_FATAL"
+
+       rm /tmp/saved-crontab.$$
+
+}
+
+case "$1" in
+'start')
+       remove_legacy_cronjobs
+
+       [ ! -x /usr/lib/time-sliderd ] && exit $SMF_EXIT_ERR_CONFIG
+
+       /usr/lib/time-sliderd
+       err=$?
+       if [ $err -ne 0 ]; then
+               echo "Time Slider failed to start: error $err"
+               exit $SMF_EXIT_ERR_FATAL
+       fi
+       ;;
+*)
+        echo "Usage: $0 { start }"
+       exit $SMF_EXIT_ERR_FATAL 
+        ;;
+esac
+
+exit $SMF_EXIT_OK
diff --git a/lib/svc/method/time-slider-plugin b/lib/svc/method/time-slider-plugin
new file mode 100755 (executable)
index 0000000..02744b4
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident        "%Z%%M% %I%     %E% SMI"
+
+. /lib/svc/share/smf_include.sh
+
+case "$1" in
+'start')
+    PLUGIN_CMD="$(svcprop -p plugin/command $SMF_FMRI)"
+    if [ $? -ne 0 ] ; then
+        echo "Unable to obtain plugin invocation command"
+        exit $SMF_EXIT_ERR_CONFIG
+    fi
+
+       if [ ! -x $PLUGIN_CMD ] ; then
+           echo "\"$PLUGIN_CMD\" is not an executable path"
+           exit $SMF_EXIT_ERR_CONFIG
+       fi
+       ;;
+*)
+        echo "Usage: $0 { start }"
+       exit $SMF_EXIT_ERR_FATAL 
+        ;;
+esac
+
+exit $SMF_EXIT_OK
+
diff --git a/lib/svc/method/time-slider-rsync b/lib/svc/method/time-slider-rsync
new file mode 100755 (executable)
index 0000000..a570dad
--- /dev/null
@@ -0,0 +1,136 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+# A rather simple SMF method script for
+# svc:/application/time-slider:default
+# It's sole purpose is to set the correct SMF property value of it's
+# direct "auto-snapshot:<schedule>" dependencies: zfs/fs-name = '//'
+
+. /lib/svc/share/smf_include.sh
+
+RSYNC_PROG="/usr/lib/time-slider/plugins/rsync/rsync-backup"
+
+# This function sets the appropriate svc configuration property for all
+# dependent auto-snapshot:<schedule> instances if necessary
+function update_service_props {
+       DEPENDENCIES=$(svcs -d  -H -o fmri $SMF_FMRI|grep auto-snapshot)
+       for dependency in ${DEPENDENCIES} ; do
+               if [ "$(svcprop -p zfs/fs-name $dependency)" != "//" ] ; then
+                       svccfg -s $dependency setprop zfs/fs-name = astring: "//"
+                       svcadm refresh $dependency
+               fi
+       done
+}
+
+# Given the exit status of a command, an integer, 0 if the command completed
+# without errors. If the command exited with errors we degrade the
+# state of this service into maintenance mode. If a 3rd argument is presented
+# we don't degrade the service. We also log an error message as passed into
+# this function.
+#
+function check_failure { # integer exit status, error message to display, be fatal
+
+       typeset RESULT=$1
+       typeset ERR_MSG=$2
+       typeset NON_FATAL=$3
+
+       if [ $RESULT -ne 0 ] ; then
+           print_log "Error: $ERR_MSG"
+           print_log "Moving service $SMF_FMRI to maintenance mode."
+           if [ -z "${NON_FATAL}" ] ; then
+               print_log "Moving service $SMF_FMRI to maintenance mode."
+               svcadm mark maintenance $SMF_FMRI
+           fi
+       fi
+
+}
+
+# A function we use to emit output. Right now, this goes to syslog via logger(1)
+function print_log { # message to display
+       logger -t time-slider -p daemon.notice $*
+}
+
+
+function add_rsync_cronjob {
+       # Call every 30 minutes, 15 and 45 minutes after the hour.
+       SCHEDULE="15,45 * * * *"
+
+       # adding a cron job is essentially just looking for an existing entry,
+       # removing it, and appending a new one. Neato.
+       crontab -l | grep -v "${RSYNC_PROG} $SMF_FMRI" \
+           > /tmp/saved-crontab.$$
+
+       echo "${SCHEDULE} ${RSYNC_PROG} $SMF_FMRI" \
+           >> /tmp/saved-crontab.$$
+
+       crontab /tmp/saved-crontab.$$
+       check_failure $? "Unable to add cron job!"
+
+       rm /tmp/saved-crontab.$$
+       return 0
+}
+
+function remove_rsync_cronjob {
+
+       crontab -l | grep -v "${RSYNC_PROG} $SMF_FMRI$" \
+           > /tmp/saved-crontab.$$
+       crontab /tmp/saved-crontab.$$
+       check_failure $? "Unable to unschedule cron job for $SMF_FMRI"
+
+       rm /tmp/saved-crontab.$$
+
+       # finally, check our status before we return
+       STATE=$(svcprop -p restarter/state $SMF_FMRI)
+       if [ "${STATE}" == "maintenance" ] ; then
+           STATE=1
+       else
+           STATE=0
+       fi
+}
+
+case $SMF_METHOD in
+"start")
+    #FIXME - This HAS to be == rsync-trigger program
+       PLUGIN_CMD="$(svcprop -p plugin/trigger_command $SMF_FMRI)"
+       if [ $? -ne 0 ] ; then
+               echo "Unable to obtain plugin invocation command"
+               exit $SMF_EXIT_ERR_CONFIG
+       fi
+
+       if [ ! -x $PLUGIN_CMD ] ; then
+           echo "\"$PLUGIN_CMD\" is not an executable path"
+           exit $SMF_EXIT_ERR_CONFIG
+       fi
+       add_rsync_cronjob
+       ;;
+"stop")
+       remove_rsync_cronjob
+       ;;
+*)
+       echo "Command line invocation of ${0} unsupported."
+       echo "This script is intended for smf(5) invocation only"
+       exit $SMF_EXIT_ERR_NOSMF
+       ;;
+esac
+exit $SMF_EXIT_OK
diff --git a/po/.intltool-merge-cache b/po/.intltool-merge-cache
new file mode 100644 (file)
index 0000000..3bb02ae
--- /dev/null
@@ -0,0 +1,543 @@
+ca\1c<b>Summary</b>\ 1<b>Resum</b>\ 1id\1cScanning for older versions\ 1Pemindaian untuk versi lama\ 1cs\1cConfigure the system to take automatic snapshots of your data\ 1Nakonfigurujte si systém tak, aby vytvářel automatické snímky Vašich dat\ 1zh_TW\1c19/01/09\ 119/01/09\ 1zh_HK\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1[立即擷取快照] 需要 2 個引數:
+- 要進行快照擷取的目錄的路徑。
+- 與此目錄對應的 zfs 檔案系統。\ 1zh_CN\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1已创建了一个名为 %(valid_name)s 的 zfs 文件
+系统 %(zfs_fs)s
+的快照。
+\ 1zh_CN\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1该快照管理器服务需要管理权限才能运行。没有为您指定必要的管理权限。
+
+请咨询您的系统管理员 \ 1it\1cTime Slider File Version Explorer\ 1Explorer versione del file Time Slider\ 1ja\1cSome snapshots could not be read\ 1いくつかのスナップショットを読み取れませんでした\ 1it\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Per l'esecuzione dell’eliminazione delle istantanee sono necessari privilegi amministrativi. Non si dispone di privilegi amministrativi necessari.
+
+Rivolgersi all'amministratore di sistema. \ 1id\1cTime Slider Manager\ 1Pengendali Time Slider\ 1zh_CN\1cError\ 1错误\ 1pt_BR\1cConfigure the system to take automatic snapshots of your data\ 1Configurar o sistema para realizar instantâneos automáticos dos dados\ 1zh_TW\1cLegacy\ 1原來的\ 1pl\1cInvalid characters in snapshot name\ 1Niedozwolone znaki w nazwie migawki\ 1id\1cCreation Time\ 1Waktu Pembuatan\ 1ca\1cTime Slider: Low Space Warning\ 1Time Slider: Advertència poc espai\ 1cs\1cEmergency: '%s' is almost full!\ 1Stav nouze: '%s' je skoro plný!\ 1pl\1c_All\ 1_Wszystkie\ 1de\1cSome snapshots could not be read\ 1Einige Schnappschüsse konnten nicht gelesen werden\ 1pl\1c1 snapshot will be deleted.\ 11 migawka będzie usunięta\ 1de\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1Folgende Zeichen sind für den Schnappschussnamen zulässig:
+[a-z][A-Z][0-9][-_.:
+Alle ungültigen Zeichen werden entfernt
+\ 1cs\1cDaily\ 1Denně\ 1de\1cwith the name :\ 1mit dem Namen:\ 1es\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1El servicio de administrador de instantáneas ha detectado un problema y se ha desactivado hasta que se solucione el problema.
+
+Para obtener más información, consulte la página de comando man svcs(1).\ 1ar\1cInvalid arguments count.\ 1فشل بعد الحجج \ 1hu\1cMount Point\ 1Felcsatolási pont\ 1id\1cD_eselect All\ 1D_eselect All\ 1pt_BR\1c19/01/09\ 119/01/09\ 1ko\1cTake a snapshot now\ 1지금 스냅샷 실행\ 1ca\1cFile System Name\ 1Nom Sistema de Fitxers\ 1cs\1cSome snapshots could not be deleted\ 1Některé snímky nemohou být smazány\ 1ko\1cSelect ZFS snapshots to delete from the list below.\ 1다음 목록에서 삭제할 ZFS 스냅샷을 선택하십시오.\ 1ja\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1タイムスライダは、時刻指定の ZFS スナップショットを作成することによって定期的にデータをバックアップします\ 1pt_BR\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Efetuar instantâneo agora requer privilégios administrativos para ser executado. Os privilégios administrativos necessários não lhe foram atribuídos.
+
+Consulte o administrador de sistema \ 1ja\1cSnapshot Name\ 1スナップショット名\ 1zh_CN\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1文件系统 '%s' 的占满程度已超过 %s%%。
+作为一种紧急措施,时间滑块已销毁了它的所有备份。
+要修复此问题,请删除 '%s' 上所有不必要的文件,或增加磁盘空间(请参见 ZFS 文档)。\ 1ja\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1「今すぐスナップショット」を実行するには管理権限が必要です。必要な管理権限が割り当てられていません。
+
+システム管理者に問い合わせてください\ 1ar\1cDaily\ 1يومي \ 1ar\1cSnapshot can not be deleted\ 1صور النظام لا يمكن حذفها \ 1de\1cOpen the current version of the file\ 1Die aktuelle Version der Datei öffnen\ 1ja\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1スナップショット名に許可されている文字は次のとおりです:
+[a-z][A-Z][0-9][-_.:
+無効な文字はすべて削除されます。
+\ 1ca\1cSelect ZFS snapshots to delete from the list below.\ 1Seleccioneu les instantànies ZFS a eliminar del següent llistat.\ 1id\1cWeekly\ 1Mingguan\ 1ko\1cDelete Snapshots\ 1스냅샷 삭제\ 1es\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1El explorador de versiones necesita 2 argumentos:
+- La ruta del directorio raíz de las instantáneas.
+- El nombre del archivo que se va a explorar.\ 1ca\1c<b>Enable Time Slider</b>\ 1<b>Activar Time Slider</b>\ 1fr\1cOpen the current version of the file\ 1Ouvrez la version actuelle du fichier\ 1zh_TW\1cTake a snapshot of \ 1擷取以下項目的快照 \ 1ko\1cInsufficient Priviliges\ 1권한 부족\ 1nl\1cSnapshot created successfully\ 1Momentopname gemaakt\ 1ca\1csize : \ 1mida : \ 1ja\1c_Delete Snapshots...\ 1スナップショットの削除(_D)...\ 1hu\1cWarning: '%s' is getting full\ 1Figyelmeztetés: '%s' megtelik\ 1nl\1cRecommended for most users\ 1Aanbevolen voor de meeste gebruikers\ 1zh_HK\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1快照管理員服務似乎並未安裝於此系統上。
+
+請參閱「svcs(1) 線上手冊」,以取得更多資訊。\ 1pt_BR\1cInvalid characters in snapshot name\ 1Caracteres inválidos no nome do instantâneo\ 1cs\1cScanning for older versions\ 1Skenuji pro starší verze\ 1zh_TW\1c<b>Enable Time Slider</b>\ 1<b>啟用時間調整器</b>\ 1ja\1c_All\ 1すべて(_A)\ 1de\1cEmergency: '%s' is almost full!\ 1Notfall: '%s' ist fast voll!\ 1zh_CN\1cSnapshot Name\ 1快照名称\ 1zh_HK\1cAll\ 1全部\ 1pl\1cPress Delete to continue.\ 1Naciśnij Delete żeby kontynuować. \ 1es\1cSnapshot manager service error\ 1Error del servicio de administrador de instantáneas\ 1pt_BR\1cSnapshot manager service error\ 1Erro do serviço do gerenciador de instantâneos\ 1hu\1c<b>Older Versions</b>\ 1<b>Régebbi Verziók</b>\ 1zh_TW\1c%d snapshots will be deleted.\ 1將刪除 %d 個快照。\ 1pt_BR\1cMount Point\ 1Ponto de montagem\ 1hu\1cDouble click to open the file\ 1Dupla kattintás a fájl megnyitásához\ 1ca\1c10 Mo\ 110 Dl\ 1de\1cReduce backups when storage space usage exceeds:\ 1Sicherungen reduzieren, wenn Speicherplatznutzung Folgendes überschreitet:\ 1zh_HK\1c1/4 Hourly\ 1每 1/4 小時\ 1ja\1cOpen the current version of the file\ 1ファイルの現在のバージョンを開く\ 1de\1cgtk-close\ 1gtk-close\ 1pl\1cSuccess\ 1Powodzenie\ 1fr\1cFile System Name\ 1Nom de système de fichiers\ 1ar\1cLegacy\ 1إرث \ 1zh_CN\1cSnapshot manager service error\ 1快照管理器服务错误\ 1es\1cname :\ 1nombre:\ 1pt_BR\1c<b>Older Versions</b>\ 1<b>Versões mais antigas</b>\ 1hu\1c19/01/09\ 119/01/09\ 1de\1cDeleting snapshots...\ 1Schnappschüsse werden gelöscht...\ 1ko\1c<b>Enable Time Slider</b>\ 1<b>시간 슬라이더 활성화</b>\ 1ko\1cReduce backups when storage space usage exceeds:\ 1저장소 공간 사용량이 초과되는 경우 백업 줄이기:\ 1ja\1cAdvanced Options\ 1詳細オプション\ 1ja\1cTime Slider\ 1タイムスライダ\ 1ar\1cExit when done. \ 1الخروج عن الإنتهاء \ 1zh_CN\1cInsufficient Priviliges\ 1权限不足\ 1cs\1cMount Point\ 1Místo připojení\ 1ca\1cUrgent: '%s' is almost full!\ 1Urgent: '%s' gairebé està ple!\ 1id\1cDelete Snapshots\ 1Menghapus Snapshots\ 1pl\1cError\ 1Błąd\ 1pt_BR\1cSome snapshots could not be read\ 1Alguns instantâneos não podem ser lidos\ 1zh_CN\1cPress Delete to continue.\ 1按“删除”以继续。\ 1de\1c<b>Current Version</b>\ 1<b>Aktuelle Version</b>\ 1ar\1cAdvanced Options\ 1خيارات إضافية \ 1nl\1c%d snapshots will be deleted.\ 1%d momentopnamen zullen worden verwijdert\ 1pl\1cLegacy\ 1Legacy\ 1id\1c%d snapshots will be deleted.\ 1%d snapshots akan dihapus\ 1de\1cfilename\ 1Dateiname\ 1zh_HK\1cC_ustom:\ 1自訂(_U):\ 1ko\1cSuccess\ 1성공\ 1id\1cTime Slider\ 1Time Slider\ 1zh_HK\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1檔案系統:「%s」已超過 %s%%。
+時間調整器所採取的緊急措施是銷毀其所有的備份。
+若要修正此問題,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文件)。\ 1hu\1cwith the name :\ 1névvel :\ 1zh_CN\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1由于相关性问题,快照管理器服务已被置于脱机。已发现以下相关性问题:
+
+%s
+
+有关这些相关性问题的更多信息,请从命令提示符下运行 "svcs -xv"。\ 1fr\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1Un instantané d'un système de fichiers zfs %(zfs_fs)s
+nommé %(valid_name)s
+a été créé.
+\ 1ko\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1지금 스냅샷 기능을 실행하려면 관리 권한이 필요합니다. 필요한 관리 권한이 할당되지 않았습니다.
+
+시스템 관리자에게 문의하십시오. \ 1pl\1cname :\ 1nazwa:\ 1ja\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1このシステムにはスナップショットマネージャーサービスがインストールされていないようです。
+
+詳細は、svcs(1) のマニュアルページを参照してください。\ 1ja\1c%d snapshots will be deleted.\ 1%d 個のスナップショットが削除されます。\ 1pt_BR\1cInvalid arguments count.\ 1Total de argumentos inválidos.\ 1es\1cInvalid arguments count.\ 1Recuento de argumentos no válidos.\ 1zh_HK\1cFor advanced users\ 1適用於進階使用者\ 1nl\1c<b>Older Versions</b>\ 1<b>Oudere versies</b>\ 1cs\1cExit when done. \ 1Ukončit po dokončení. \ 1ko\1cEmergency: '%s' is almost full!\ 1긴급: '%s'이(가) 거의 찼습니다!\ 1it\1cC_ustom:\ 1Personali_zzato:\ 1zh_HK\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1已建立一個名為 %(valid_name)s 的
+ zfs 檔案系統 %(zfs_fs)s
+的快照。
+\ 1id\1cReduce backups when storage space usage exceeds:\ 1Mengurangi ruang penyimpanan backup bila melebihi kapasitas :\ 1es\1cDouble click to open the file\ 1Haga doble clic para abrir este archivo\ 1pt_BR\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1A exclusão de instantâneos requer privilégios administrativos para ser executada. Os privilégios administrativos necessários não lhe foram atribuídos.
+
+Consulte o administrador de sistema \ 1zh_TW\1cSnapshot Name\ 1快照名稱\ 1ja\1cDouble click to open the file\ 1ダブルクリックしてファイルを開く\ 1de\1cAll\ 1Alle\ 1zh_CN\1clast modified : \ 1上次修改时间: \ 1ar\1cDeleting snapshots...\ 1حذف صور النظام...\ 1cs\1cLegacy\ 1Odkaz\ 1de\1cMonthly\ 1Monatlich\ 1ko\1cWarning: '%s' is getting full\ 1경고: '%s'이(가) 꽉 찼습니다.\ 1zh_CN\1cOpen the current version of the file\ 1打开文件的当前版本\ 1ja\1clast modified : \ 1最終更新日付:  \ 1nl\1cwith the name :\ 1met de naam :\ 1pl\1cAll\ 1Wszystkie\ 1pl\1csize : \ 1rozmiar: \ 1fr\1cName:\ 1Nom :\ 1zh_HK\1cAdvanced Options\ 1進階選項\ 1es\1cSuccess\ 1Correcto\ 1fr\1cSnapshot manager service dependency error\ 1Erreur de dépendance du service de gestionnaire d'instantanés\ 1de\1cFile System Name\ 1Dateisystemname\ 1nl\1cConfigure the system to take automatic snapshots of your data\ 1Configureer het systeem om automatische momentopnamen van je gegevens te nemen\ 1zh_CN\1cLegacy\ 1传统\ 1pl\1cSnapshot created successfully\ 1Migawka została utworzona\ 1zh_CN\1cInvalid arguments count.\ 1参数计数无效。\ 1fr\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1Le service de gestionnaire d'instantanés ne semble pas être installé sur ce système.
+
+Pour de plus amples informations, reportez-vous à la page de manuel svcs(1).\ 1pt_BR\1cSelect\ 1Selecione\ 1zh_TW\1cC_ustom:\ 1自訂(_U):\ 1ar\1c<b>Enable Time Slider</b>\ 1<b>تفعيل شريط تمرير الوقت</b>\ 1nl\1c_Delete Snapshots...\ 1_Verwijder momentopnames...\ 1zh_CN\1cTake a snapshot of \ 1捕获以下项的快照 \ 1pl\1cTime Slider File Version Explorer\ 1Time Slider File Version Explorer\ 1de\1c<b>Summary</b>\ 1<b>Zusammenfassung</b>\ 1id\1cTake a snapshot now\ 1Mengambil snapshot sekarang\ 1zh_HK\1cCreation Time\ 1建立時間\ 1pt_BR\1cEmergency: '%s' is almost full!\ 1Emergência: '%s' está quase cheio!\ 1ko\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1파일 시스템 '%s'이(가) 총 용량의 %s%%을(를) 초과했습니다. 해결 조치로시간 슬라이더가 일부 백업을 삭제했으며, 용량이 계속 줄어들 때 좀 더 삭제할 예정이며 결국 모두 삭제합니다.
+이러한 문제가 다시 발생하지 않도록 '%s'에서 불필요한 파일을 삭제하거나 디스크 공간을 추가합니다(ZFS 설명서 참조).\ 1pt_BR\1cSnapshot can not be deleted\ 1O instantâneo não pode ser excluído\ 1pl\1cWeekly\ 1Tygodniowo\ 1cs\1cReduce backups when storage space usage exceeds:\ 1Zmenšit zálohy pokud úložný prostor překročí:\ 1es\1c<b>Enable Time Slider</b>\ 1<b>Habilitar deslizador de tiempo</b>\ 1pt_BR\1cPress Delete to continue.\ 1Pressione Delete para continuar.\ 1ja\1cFor advanced users\ 1上級ユーザー向け\ 1ar\1c1 snapshot will be deleted.\ 11 صورة نظام سوف تحذف \ 1pt_BR\1cExit when done. \ 1Sair ao concluir. \ 1es\1cDeleting Snapshots\ 1Eliminación de instantáneas\ 1ja\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1ファイルシステム: '%s' が総容量の %s%% を超えました。
+緊急の手段として、タイムスライダはすべてのバックアップを破棄しました。
+この問題を解決するために、'%s' 上の不必要なファイルをすべて削除するか、またはディスク容量を追加してください (ZFS のマニュアルを参照)。\ 1es\1cDaily\ 1Cada día\ 1ar\1cHint\ 1ملحوظة \ 1fr\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Pour supprimer des instantanés, vous devez posséder des privilèges administratifs.  Vous ne possédez pas les privilèges administratifs requis.
+
+Consultez votre administrateur système  \ 1fr\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1Le système de fichiers %s est rempli à plus de %s %%.
+Par mesure d'urgence, le curseur temporel a détruit toutes ses sauvegardes.
+Pour résoudre ce problème, supprimez tout fichier non indispensable sur %s ou ajoutez de l'espace disque (voir la documentation ZFS).\ 1ko\1cRecommended for most users\ 1대부분의 사용자에게 권장\ 1it\1cEmergency: '%s' is almost full!\ 1Attenzione: '%s' è quasi pieno.\ 1cs\1cname :\ 1jméno :\ 1ja\1cEmergency: '%s' is almost full!\ 1緊急: '%s' がほぼいっぱいです。\ 1hu\1cDeleting snapshots...\ 1Pillanatképek törlése...\ 1pt_BR\1cSome snapshots could not be deleted\ 1Alguns instantâneos não podem ser excluídos\ 1pl\1cReduce backups when storage space usage exceeds:\ 1Zmniejsz liczbę backupów kiedy przestrzeń przechowywania przekroczy:\ 1zh_HK\1cInsufficient Priviliges\ 1權限不足\ 1ar\1cError\ 1خطأ \ 1cs\1cPress Delete to continue.\ 1Stiskněte Smazat pro pokračování.\ 1hu\1cDetails...\ 1Részletek...\ 1pl\1cDaily\ 1Dziennie\ 1zh_TW\1cFile System:\ 1檔案系統:\ 1es\1cTake a snapshot now\ 1Tomar una instantánea ahora\ 1nl\1cTime Slider\ 1Tijd glijder\ 1it\1cAll\ 1Tutto\ 1fr\1cLegacy\ 1Hérité\ 1de\1cSnapshot created successfully\ 1Schnappschuss wurde erfolgreich erstellt\ 1es\1cSnapshot can not be deleted\ 1La instantánea no se puede eliminar\ 1de\1cName:\ 1Name:\ 1id\1cAll\ 1Semua\ 1es\1cCreation Time\ 1Momento de creación\ 1de\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s hat einen oder mehrere abhängige Klone und wird nicht gelöscht.  Um diesen Schnappschuss zu löschen, löschen Sie zunächst alle Datensätze und Schnappschüsse, die aus diesem Schnappschuss geklont wurden.\ 1zh_CN\1ccompare\ 1比较\ 1fr\1cConfigure the system to take automatic snapshots of your data\ 1Configurer le système de manière à prendre des instantanés automatiques des données\ 1es\1cMonthly\ 1Cada mes\ 1ar\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1The file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1ko\1cDaily\ 1매일\ 1ko\1c1/4 Hourly\ 1매25분\ 1it\1cSnapshot Name\ 1Nome istantanea\ 1ko\1cPress Delete to continue.\ 1계속하려면 삭제를 누르십시오.\ 1id\1cSelect\ 1Pilih\ 1de\1c_All\ 1_Alle\ 1ca\1cReduce backups when storage space usage exceeds:\ 1Reduir les còpies de seguretat quan l'espai d'emmagatzemament excedeixi:\ 1pl\1cSome snapshots could not be read\ 1Nie można odczytać niektórych migawek\ 1zh_HK\1cSuccess\ 1成功\ 1de\1cCreation Time\ 1Erstellungszeit\ 1fr\1cTake a snapshot of \ 1Prenez un instantané de  \ 1hu\1cInvalid characters in snapshot name\ 1Érvénytelen karakterek a pillanatkép nevében\ 1it\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1L’explorer della versione richiede 2 argomenti :
+- La path della directory radice dell’istantanea .
+- Il nome file da ricercare.\ 1zh_TW\1c<b>Older Versions</b>\ 1<b>較舊版本</b>\ 1it\1cUrgent: '%s' is almost full!\ 1Avviso: '%s' è quasi pieno.\ 1zh_HK\1cSnapshot manager service error\ 1快照管理員服務錯誤\ 1ko\1ccompare\ 1비교\ 1pt_BR\1c10 Mo\ 110 Mo\ 1de\1cHourly\ 1Stündlich\ 1nl\1cSuccess\ 1Succes\ 1hu\1cAll\ 1Mind\ 1fr\1c_Delete Snapshots...\ 1Supprimer _des instantanés...\ 1id\1cSnapshot created successfully\ 1Sukses membuat snapshot\ 1ko\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1zfs 파일 시스템 %(zfs_fs)s의 스냅샷
+%(valid_name)s이(가)
+생성되었습니다.
+\ 1zh_TW\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1已建立一個名為 %(valid_name)s 的
+ zfs 檔案系統 %(zfs_fs)s
+的快照。
+\ 1zh_HK\1cTake a snapshot now\ 1立即擷取快照\ 1zh_HK\1csize : \ 1大小: \ 1cs\1cD_eselect All\ 1V_yřadit vše\ 1cs\1c<b>Older Versions</b>\ 1<b>Starší verze</b>\ 1pt_BR\1cUrgent: '%s' is almost full!\ 1Urgente: '%s' está quase cheio!\ 1hu\1cSnapshot manager service dependency error\ 1Pillanatkép kezelő szolgáltatás függőségi hiba\ 1cs\1cDetails...\ 1Podrobnosti...\ 1zh_TW\1cSnapshot can not be deleted\ 1無法刪除快照\ 1pt_BR\1cError occured while creating the snapshot\ 1Erro ocorrido durante a criação do instantâneo\ 1it\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Time Slider consente di eseguire regolarmente backup dei dati mediante l'acquisizione di istantanee ZFS a intervalli regolari\ 1zh_CN\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s 具有一个或多个相关克隆,不会被删除。要删除此快照,请首先删除从此快照克隆的所有数据集和快照。\ 1pl\1cSelect ZFS snapshots to delete from the list below.\ 1Wybierz migawki ZFS do usunięcia z listy poniżej.\ 1pl\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Time Slider regularnie robi kopię zapasową danych poprzez migawkę ZFS\ 1nl\1c<b>File Systems To Back Up</b>\ 1<b>Bestand systemen voor backup</b>\ 1pl\1cCreation Time\ 1Czas utworzenia\ 1ko\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1시간 슬라이더는 시간이 지정된 ZFS 스냅샷을 가져와 데이터를 정기적으로 백업합니다.\ 1ko\1csize : \ 1크기: \ 1hu\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Time Slider rendszeresen végez mentéseket időzített ZFS pillanatképek készítésével.\ 1cs\1cError occured while creating the snapshot\ 1Vyskytla se chyba při vytváření snímku\ 1it\1c_Delete Snapshots...\ 1_Elimina istantanee…\ 1ar\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1شريط تمرير الوقت يقوم بنسخ إحتياطي للبيانات بشكل منتظم \ 1pl\1c<b>Summary</b>\ 1<b>Podsumowanie</b>\ 1zh_CN\1cof file system capacity\ 1关于文件系统容量\ 1zh_TW\1cof file system capacity\ 1檔案系統容量\ 1nl\1cTime Slider: Low Space Warning\ 1Time Slider: Low Space Warning\ 1cs\1c%d snapshots will be deleted.\ 1%d snímky budou smazány.\ 1id\1cFile System:\ 1File Sistem:\ 1it\1cInvalid characters in snapshot name\ 1Caratteri invalidi nel nome dell’istantanea\ 1id\1cMount Point\ 1Mount Point\ 1it\1ccompare\ 1confronta\ 1de\1cof file system capacity\ 1der Dateisystemkapazität\ 1zh_TW\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1檔案系統:「%s」已超過 %s%%。
+時間調整器所採取的緊急措施是銷毀其所有的備份。
+若要修正此問題,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文件)。\ 1hu\1cScanning snapshots...\ 1Pillanatképek keresése...\ 1nl\1c10 Mo\ 110 MO\ 1zh_CN\1cEmergency: '%s' is full!\ 1紧急:'%s' 已满!\ 1pt_BR\1c_All\ 1_Todos\ 1ja\1c10 Mo\ 110 Mo\ 1zh_TW\1cEmergency: '%s' is almost full!\ 1緊急:「%s」幾乎已滿!\ 1pt_BR\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1O serviço do gerenciador de instantâneos requer privilégios administrativos para ser executado. Os privilégios administrativos necessários não lhe foram atribuídos.
+
+Consulte o administrador de sistema \ 1ar\1cD_eselect All\ 1D_eselect All\ 1ca\1cHourly\ 1Cada hora\ 1ja\1cSelect\ 1選択\ 1fr\1cInsufficient Priviliges\ 1Privilèges insuffisants\ 1it\1cD_eselect All\ 1D_eseleziona tutto\ 1zh_CN\1cDeleting Snapshots\ 1正在删除快照\ 1id\1cDetails...\ 1Rincian...\ 1zh_TW\1cDeleting snapshots...\ 1正在刪除快照...\ 1hu\1cFor advanced users\ 1Tapasztalt felhasználóknak\ 1zh_TW\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1快照管理員服務需要有管理權限才能執行。您尚未被指定必要的管理權限。
+
+請洽詢您的系統管理員 \ 1id\1cSuccess\ 1Sukses\ 1de\1c<b>File Systems To Back Up</b>\ 1<b>Dateisystem zur Sicherung</b>\ 1zh_CN\1c<b>Current Version</b>\ 1<b>当前版本</b>\ 1zh_HK\1cError occured while creating the snapshot\ 1建立快照時發生錯誤\ 1pl\1cSome snapshots could not be deleted\ 1Nie można usunąć niektórych migawek\ 1it\1cSnapshot manager service error\ 1Errore del servizio di gestione delle istantanee\ 1de\1cError occured while creating the snapshot\ 1Fehler beim Erstellen des Schnappschusses\ 1ca\1cEmergency: '%s' is full!\ 1Emergència: '%s' està ple!\ 1hu\1cTime Slider: Low Space Warning\ 1Time Slider: Kevés Tárhely Figyelmeztetés\ 1id\1cPress Delete to continue.\ 1Tekan Delete untuk melanjutkan.\ 1pt_BR\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1O serviço do gerenciador de instantâneos encontrou um problema e ficará desativado até que o problema seja corrigido.
+
+Para obter mais informações, consulte a página do manual svcs(1).\ 1id\1cDeleting snapshots...\ 1Menghapus snapshots...\ 1id\1cDouble click to open the file\ 1Klik dua kali untuk membuka file\ 1zh_TW\1cMonthly\ 1每月\ 1zh_CN\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1快照名称中允许使用的字符为:
+[a-z][A-Z][0-9][-_.:
+所有无效字符都会被删除
+\ 1de\1c1/4 Hourly\ 1Viertelstündlich\ 1it\1cScanning for older versions\ 1Ricerca delle versioni precedenti in corso...\ 1hu\1cOpen the current version of the file\ 1Az aktuális fájl verzió megnyitása\ 1ja\1cUrgent: '%s' is almost full!\ 1緊急: '%s' がほぼいっぱいです。\ 1es\1cLegacy\ 1Antiguo\ 1ko\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1파일 시스템 '%s'이(가) %s%% 이상으로 꽉 찼습니다.
+긴급 조치로 시간 슬라이더가 모든 백업을 삭제했습니다
+이 문제를 해결하려면 '%s'에서 불필요한 파일을 삭제하거나 디스크 공간을 추가하십시오(ZFS 설명서 참조).\ 1zh_CN\1cInvalid characters in snapshot name\ 1快照名称中存在无效字符\ 1id\1cExit when done. \ 1Keluar ketika selesai \ 1zh_HK\1cof file system capacity\ 1檔案系統容量\ 1zh_CN\1cSnapshot can not be deleted\ 1无法删除快照\ 1es\1csize : \ 1tamaño: \ 1hu\1clast modified : \ 1Utoljára módosítva : \ 1ja\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1スナップショットマネージャーサービスが問題を検出し、この問題が解決されるまで無効になっています。
+
+詳細は、svcs(1) のマニュアルページを参照してください。\ 1de\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1Das Dateisystem: '%s', ist über %s%% voll.
+Der Zeit-Schieberegler hat im Zuge einer Notfallmaßnahme alle Sicherungsdateien gelöscht.
+Um dieses Problem zu beheben, löschen Sie alle nicht benötigten Dateien auf '%s', oder fügen Sie Speicherplatz hinzu (siehe ZFS-Dokumentation).\ 1pt_BR\1cCreation Time\ 1Hora de criação\ 1ca\1clast modified : \ 1última modificació : \ 1zh_TW\1c10 Mo\ 110 Mo\ 1ja\1cDelete Snapshots\ 1スナップショットの削除\ 1id\1cThe file system: '%s', is over %s%% full.\ 1file sistem: '%s', melebihi %s%% penuh.\ 1fr\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1Le service de gestionnaire d'instantané a été mis hors ligne en raison d'un problème de dépendance.  Les problèmes de dépendance suivants ont été détectés :
+
+%s
+
+Exécutez "svcs  -xv" à partir d'une invite de commande pour plus d'informations sur ces problèmes de dépendance.\ 1ar\1c_Delete Snapshots...\ 1_حذف صور النظام ....\ 1pl\1cSnapshot can not be deleted\ 1Migawka nie może byś usunięta\ 1ca\1c<b>File Systems To Back Up</b>\ 1<b>Sistema de fitxers a fer Còpia de seguretat</b>\ 1fr\1cwith the name :\ 1nommé :\ 1pl\1c10 Mo\ 110 Mo\ 1ko\1cname :\ 1이름:\ 1es\1cDeleting snapshots...\ 1Eliminando instantáneas...\ 1cs\1cTake a snapshot now\ 1Pořídit snímek nyní\ 1ar\1cInsufficient Priviliges\ 1الإمتيازات غير كافية \ 1ko\1cAll\ 1모두\ 1cs\1cSnapshot manager service dependency error\ 1Chyba v závislostech ve službě Správce snímků\ 1pl\1c<b>Older Versions</b>\ 1</b>Starsza Wersja</b>\ 1zh_HK\1cReduce backups when storage space usage exceeds:\ 1當儲存空間使用量超過下列大小時減少備份:\ 1es\1cFile System Name\ 1Nombre del sistema de archivos\ 1it\1cof file system capacity\ 1della capacità del file system\ 1ko\1c_All\ 1모두(_A)\ 1pt_BR\1cDouble click to open the file\ 1Clicar duas vezes para abrir o arquivo\ 1zh_HK\1cConfigure the system to take automatic snapshots of your data\ 1將系統配置為自動對資料執行快照\ 1ca\1cPress Delete to continue.\ 1Premeu a Eliminar per a continuar.\ 1hu\1cFile System:\ 1Fájlrendszer:\ 1id\1cname :\ 1nama :\ 1zh_TW\1cScanning for older versions\ 1掃描較舊版本\ 1ar\1cSelect\ 1إختر \ 1it\1cFor advanced users\ 1Per utenti avanzati\ 1zh_TW\1cWeekly\ 1每週\ 1de\1cTake a snapshot of \ 1Einen Schnappschuss nehmen von  \ 1es\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1La eliminación de la instantánea necesita privilegios administrativos. No se le ha asignado los correspondientes privilegios administrativos.
+
+Consulte al administrador del sistema\ 1cs\1cInsufficient Priviliges\ 1Nedostatečná práva\ 1fr\1cScanning snapshots...\ 1Analyse des instantanés...\ 1ja\1cSome snapshots could not be deleted\ 1いくつかのスナップショットを削除できませんでした\ 1zh_TW\1cName:\ 1名稱:\ 1it\1cFile System Name\ 1Nome file system\ 1cs\1cName:\ 1Jméno:\ 1nl\1cSnapshot manager service dependency error\ 1Momentopname manager service afhankelijkheid fout\ 1it\1cMonthly\ 1Mensile\ 1ja\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1依存関係の問題が発生したために、スナップショットマネージャーサービスがオフラインになりました。次の依存関係の問題が検出されました:
+
+%s
+
+これらの依存関係の問題の詳細を表示するには、コマンドプロンプトから "svcs -xv" を実行してください。\ 1pt_BR\1cReduce backups when storage space usage exceeds:\ 1Reduzir os backups quando o espaço de armazenamento for excedido:\ 1it\1clast modified : \ 1ultima modifica : \ 1ja\1ccompare\ 1比較\ 1es\1cScanning for older versions\ 1Buscando versiones anteriores\ 1de\1cRecommended for most users\ 1Empfohlen für die meisten Benutzer\ 1es\1cSnapshot created successfully\ 1La instantánea se creó correctamente\ 1pl\1cSnapshot Name\ 1Nazwa migawki\ 1it\1cInsufficient Priviliges\ 1Privilegi insufficienti\ 1pt_BR\1cSnapshot manager service dependency error\ 1Erro de dependência do serviço do gerenciador de instantâneos\ 1es\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1El sistema de archivos: '%s', ha sobrepasado un %s%% de su capacidad total. Como solución, el deslizador de tiempo ha destruido algunas copias de seguridad, y destruirá más, posiblemente todas, conforme siga disminuyendo la capacidad.
+Para impedir que se repita este problema, elimine todos los archivos innecesarios de '%s' o agregue espacio al disco (consulte la documentación de ZFS).\ 1cs\1cDouble click to open the file\ 1Dvojitým kliknutím na soubor tento soubor otevřete\ 1ca\1cDeleting snapshots...\ 1Eliminant Instantànies...\ 1es\1cfilename\ 1nombre_archivo\ 1fr\1cSelect\ 1Sélectionner\ 1ja\1cWeekly\ 1毎週\ 1ca\1cLegacy\ 1Llegat\ 1es\1c<b>Summary</b>\ 1<b>Resumen</b>\ 1zh_HK\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1快照管理員服務需要有管理權限才能執行。您尚未被指定必要的管理權限。
+
+請洽詢您的系統管理員 \ 1cs\1cTime Slider Manager\ 1Správce pro Time Slider\ 1cs\1cSnapshot Name\ 1Jméno snímku\ 1ko\1cHourly\ 1매시간\ 1ar\1cConfiguring Time Slider...\ 1إعدادات شريط التوقيت...\ 1zh_HK\1cSnapshot created successfully\ 1已成功建立快照\ 1hu\1cAdvanced Options\ 1Szakértői beállítások\ 1ca\1cC_ustom:\ 1_Personalitzat:\ 1hu\1cWeekly\ 1Heti\ 1ko\1c<b>Summary</b>\ 1<b>요약</b>\ 1ko\1cCreation Time\ 1생성 시간\ 1cs\1c<b>Summary</b>\ 1<b>Shrnutí</b>\ 1zh_TW\1cReduce backups when storage space usage exceeds:\ 1當儲存空間使用量超過下列大小時減少備份:\ 1ja\1c<b>Older Versions</b>\ 1<b>旧バージョン</b>\ 1pl\1cSnapshot manager service dependency error\ 1Błąd usługi menadżera migawek\ 1ko\1cDouble click to open the file\ 1파일을 열려면 두 번 누릅니다.\ 1zh_HK\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s 具有一個或多個附屬複製,不會被刪除。要刪除此快照,請先刪除從此快照複製的所有資料集和快照。\ 1pl\1c%d snapshots will be deleted.\ 1%d migawki zostaną usunięte\ 1hu\1cUrgent: '%s' is almost full!\ 1Sürgős: '%s' majdnem megtelt!\ 1pl\1cDetails...\ 1Details...\ 1hu\1cTime Slider File Version Explorer\ 1Time Slider Fájl Verzió Intéző\ 1hu\1cTime Slider\ 1Time Slider\ 1ar\1cDouble click to open the file\ 1إضغط مرتين لفتح الملف \ 1pl\1cMount Point\ 1Punkt montowania\ 1ca\1cSnapshot Name\ 1Nom de la instantània\ 1ca\1cWeekly\ 1Setmanal\ 1fr\1cPress Delete to continue.\ 1Cliquez sur Supprimer pour continuer.\ 1nl\1cgtk-close\ 1gtk-sluiten\ 1fr\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1L'explorateur de versions nécessite 2 arguments :
+- Chemin d'accès au répertoire d'instantanés racine.
+- Nom de fichier à explorer.\ 1it\1cSome snapshots could not be read\ 1Impossibile leggere alcune istantanee\ 1it\1cLegacy\ 1Legacy\ 1ar\1cSnapshot Name\ 1إسم صورة النظام \ 1pl\1cHourly\ 1Co godzinę\ 1it\1cDeleting Snapshots\ 1Eliminazione delle istantanee\ 1es\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1El deslizador de tiempo hace copias de seguridad de datos con regularidad tomando instantáneas de ZFS programadas\ 1nl\1c<b>Current Version</b>\ 1<b>Huidige versie</b>\ 1zh_HK\1cTime Slider File Version Explorer\ 1時間滑動軸檔案版本檔案總管\ 1ko\1c_Delete Snapshots...\ 1스냅샷 삭제(_D)...\ 1it\1c1/4 Hourly\ 1Ogni quarto d’ora\ 1ca\1c19/01/09\ 119/01/09\ 1de\1cDelete Snapshots\ 1Schnappschüsse löschen\ 1ca\1c<b>Older Versions</b>\ 1<b>Versions Anteriors</b>\ 1ko\1cFor advanced users\ 1고급 사용자용\ 1it\1cTime Slider\ 1Time Slider\ 1ko\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1지금 스냅샷 기능에는 다음과 같은 2개의 인수가 필요합니다.
+- 스냅샷될 디렉토리의 경로
+- 이 디렉토리에 해당하는 zfs 파일 시스템\ 1nl\1cInvalid arguments count.\ 1Ongeldige argumenten aantal.\ 1it\1cInvalid arguments count.\ 1Calcolo degli argomenti non valido.\ 1hu\1cDaily\ 1Napi\ 1ja\1cSnapshot can not be deleted\ 1スナップショットを削除できません\ 1it\1cCreation Time\ 1Tempo di creazione\ 1it\1c<b>Current Version</b>\ 1<b>Versione corrente</b>\ 1zh_CN\1c1/4 Hourly\ 1每 1/4 小时\ 1es\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1El sistema de archivos: '%s', está %s%% por encima.
+Como medida de emergencia, el deslizador de tiempo ha destruido todas sus copias de seguridad.
+Para solventar este problema, elimine todos los archivos innecesarios de '%s' o agregue espacio al disco (consulte la documentación de ZFS).\ 1zh_TW\1cSelect ZFS snapshots to delete from the list below.\ 1請從以下清單中選取要刪除的 ZFS 快照。\ 1ko\1cwith the name :\ 1이름:\ 1ja\1cAll\ 1すべて\ 1cs\1cTime Slider File Version Explorer\ 1Time Slider - Průzkumník verzí \ 1zh_CN\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1该快照管理器服务出现了问题,并已被禁用,直至问题得以修复。
+
+有关更多信息,请参见 svcs(1) 手册页。\ 1zh_CN\1c<b>Summary</b>\ 1<b>摘要</b>\ 1fr\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Pour exécuter le service de gestionnaire d'instantanés, vous devez posséder des privilèges administratifs. Vous ne possédez pas les privilèges administratifs requis.
+
+Consultez votre administrateur système \ 1ko\1cEmergency: '%s' is full!\ 1긴급: '%s'이(가) 꽉 찼습니다!\ 1ko\1cUrgent: '%s' is almost full!\ 1중요: '%s'이(가) 거의 찼습니다!\ 1hu\1cSnapshot created successfully\ 1Pillanatkép sikeresen elkészítve\ 1zh_HK\1c<b>Current Version</b>\ 1<b>目前版本</b>\ 1fr\1c<b>Summary</b>\ 1<b>Résumé</b>\ 1ko\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1스냅샷 관리자 서비스가 종속성 문제로 인해 오프라인 상태로 설정되었습니다. 다음과 같은 종속성 문제가 발견되었습니다.
+
+%s
+
+이러한 종속성 문제에 대한 자세한 내용을 보려면 명령 프롬프트에서 "svcs -xv"를 실행하십시오.\ 1zh_CN\1csize : \ 1大小: \ 1id\1cTime Slider File Version Explorer\ 1Time Slider File Version Explorer\ 1id\1cInvalid characters in snapshot name\ 1Invalid karakter pada nama snapshot\ 1de\1cWeekly\ 1Wöchentlich\ 1pl\1cDeleting Snapshots\ 1Usuwanie migawki\ 1es\1cSome snapshots could not be deleted\ 1No se ha podido eliminar algunas instantáneas\ 1ja\1cTake a snapshot now\ 1今すぐスナップショットを取得する\ 1de\1c_Delete Snapshots...\ 1_Schnappschüsse löschen...\ 1ar\1cDelete Snapshots\ 1حذف صور النظام  \ 1hu\1cFile System Name\ 1Fájlrendszer Neve\ 1ca\1cSnapshot manager service error\ 1S'ha produït un error al servei de gestió de instantànies\ 1fr\1cAll\ 1Tout\ 1id\1ccompare\ 1bandingkan\ 1id\1cInsufficient Priviliges\ 1Hak akses tidak mencukupi\ 1hu\1cSnapshot Name\ 1Pillanatkép neve\ 1it\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1Spazio del file system '%s' occupato oltre il %s%%.
+Come misura di emergenza, Time Slider ha eliminato tutti i backup eseguiti.
+Per risolvere il problema, eliminare i file non necessari in '%s' oppure aggiungere spazio nel disco (vedere la documentazione di ZFS).\ 1hu\1cConfigure the system to take automatic snapshots of your data\ 1A rendszer beállítása arra, hogy automatikusan mentse az Ön adatait\ 1ca\1cMount Point\ 1Punt de Muntatge\ 1hu\1c<b>File Systems To Back Up</b>\ 1<b>Fájl Rendszer Mentése</b>\ 1ja\1cof file system capacity\ 1ファイルシステム容量\ 1ca\1cAll\ 1Tots\ 1pl\1cRecommended for most users\ 1Rekomendowane dla większości użytkowników\ 1id\1cError\ 1Error\ 1id\1cOpen the current version of the file\ 1Buka file dengan versi saat ini\ 1es\1cFor advanced users\ 1Para usuarios avanzados\ 1zh_CN\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1时间滑块通过定时拍摄 ZFS 快照来对数据进行定期备份\ 1zh_HK\1cWeekly\ 1每週\ 1fr\1c19/01/09\ 119/01/09\ 1pl\1cUrgent: '%s' is almost full!\ 1Pilne: '%s' jest prawie zapełniony!\ 1zh_HK\1clast modified : \ 1上次修改時間: \ 1zh_CN\1cDeleting snapshots...\ 1正在删除快照...\ 1pl\1cC_ustom:\ 1C_ustom:\ 1fr\1csize : \ 1taille :  \ 1ja\1cReduce backups when storage space usage exceeds:\ 1ストレージスペースの使用量が超過したらバックアップを削減する:\ 1zh_HK\1cwith the name :\ 1名稱為:\ 1de\1ccompare\ 1vergleichen\ 1pl\1cAdvanced Options\ 1Zaawansowane opcje\ 1cs\1cSelect\ 1Vybrat\ 1nl\1c<b>Summary</b>\ 1<b>Samenvatting</b>\ 1it\1cTake a snapshot of \ 1Crea un’istantanea di \ 1cs\1clast modified : \ 1Naposledy změněn : \ 1nl\1cError occured while creating the snapshot\ 1Fout opgetreden tijdens het maken van de momentopname\ 1pt_BR\1cDelete Snapshots\ 1Excluir instantâneos\ 1hu\1cSome snapshots could not be read\ 1Néhány pillanatkép nem olvasható\ 1id\1c<b>Older Versions</b>\ 1<b>Versi Lama</b>\ 1ko\1cof file system capacity\ 1- 파일 시스템 용량\ 1hu\1cThe file system: '%s', exceeded %s%% of its total capacity\ 1A fájlrendszer: '%s' túllépte teljes kapacitásának %s%%-át\ 1pt_BR\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1A barra deslizante de tempo faz backup de dados regularmente realizando instantâneos programados do ZFS\ 1ar\1cSome snapshots could not be deleted\ 1بعض صور النظام لايمكن أن تحذف \ 1cs\1cWeekly\ 1Týdně\ 1zh_TW\1cTime Slider\ 1時間滑動軸\ 1ja\1cLegacy\ 1旧バージョン\ 1zh_HK\1cWarning: '%s' is getting full\ 1警告:「%s」快要滿了\ 1ar\1cPress Delete to continue.\ 1إضغط على حذف للإستمرار \ 1zh_TW\1c<b>Summary</b>\ 1<b>摘要</b>\ 1es\1cError occured while creating the snapshot\ 1Error al crear la instantánea\ 1de\1cSnapshot Name\ 1Schnappschussname\ 1ar\1cHourly\ 1ساعي \ 1hu\1csize : \ 1méret : \ 1it\1cDeleting snapshots...\ 1Eliminazione delle istantanee in corso…\ 1ja\1c19/01/09\ 119/01/09\ 1ca\1cTime Slider Manager\ 1Gestor de Time Slider\ 1ca\1cConfigure the system to take automatic snapshots of your data\ 1Configurar el sistema per a fer instantànies automàtiques de les vostres dades\ 1zh_TW\1ccompare\ 1對比\ 1ca\1cScanning snapshots...\ 1Escanejant instantànies....\ 1zh_CN\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1需要有管理权限才能立即进行快照。没有为您指定必要的管理权限。
+
+请咨询您的系统管理员 \ 1pt_BR\1cof file system capacity\ 1da capacidade do sistema de arquivos\ 1ca\1cRecommended for most users\ 1Recomanat per a la majoria d'usuaris\ 1hu\1cName:\ 1Név:\ 1es\1cSelect ZFS snapshots to delete from the list below.\ 1Seleccione las instantáneas ZFS que desea eliminar de la siguiente lista.\ 1fr\1cname :\ 1nom :\ 1fr\1c<b>Current Version</b>\ 1<b>Version actuelle</b>\ 1cs\1c<b>Current Version</b>\ 1<b>Současná verze</b>\ 1zh_HK\1c1 snapshot will be deleted.\ 1將刪除 1 個快照。\ 1de\1cUrgent: '%s' is almost full!\ 1Dringend: '%s' ist fast voll!\ 1es\1cAdvanced Options\ 1Opciones avanzadas\ 1ca\1cDelete Snapshots\ 1Eliminar instantànies\ 1cs\1cDelete Snapshots\ 1Smazat snímky\ 1pt_BR\1cWeekly\ 1Semanalmente\ 1zh_HK\1cTime Slider\ 1時間滑動軸\ 1ja\1cDaily\ 1毎日\ 1cs\1cHint\ 1Nápověda\ 1zh_CN\1cSelect\ 1选择\ 1it\1cfilename\ 1nome file\ 1nl\1cThe file system: '%s', is over %s%% full.\ 1The file system: '%s', is over %s%% full.\ 1it\1c<b>Older Versions</b>\ 1<b>Versioni precedenti</b>\ 1ar\1cSnapshot manager service error\ 1خطأ خدمة إدارة صورة النظام \ 1zh_TW\1cFor advanced users\ 1適用於進階使用者\ 1ca\1cfilename\ 1nomfitxer\ 1id\1cAdvanced Options\ 1Pilihan Lanjutan\ 1pl\1cConfigure the system to take automatic snapshots of your data\ 1Skonfiguruj system do automatycznego wykonywania migawek twoich danych \ 1fr\1cScanning for older versions\ 1Recherche d'anciennes versions\ 1cs\1cAll\ 1Vše\ 1ca\1cFile System:\ 1Sistema de Fitxers:\ 1es\1cPress Delete to continue.\ 1Pulse Suprimir para continuar.\ 1zh_HK\1cPress Delete to continue.\ 1請按下 [刪除] 繼續。\ 1de\1cSelect ZFS snapshots to delete from the list below.\ 1Wählen Sie aus der nachstehenden Liste die zu löschenden ZFS-Schnappschüsse aus.\ 1ko\1cName:\ 1이름:\ 1hu\1ccompare\ 1összehasonlítás\ 1fr\1cSome snapshots could not be deleted\ 1Certains instantanés n'ont pas pu être supprimés\ 1ar\1cDeleting Snapshots\ 1حذف صور النظام \ 1ca\1cError\ 1Error\ 1zh_CN\1cEmergency: '%s' is almost full!\ 1紧急:'%s' 几乎已满!\ 1ko\1cDeleting snapshots...\ 1스냅샷 삭제 중...\ 1zh_CN\1cSnapshot manager service dependency error\ 1快照管理器服务相关性错误\ 1ar\1clast modified : \ 1أخر تعديل : \ 1zh_CN\1cC_ustom:\ 1自定义(_U):\ 1pt_BR\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1O serviço do gerenciador de instantâneos parece não estar instalado neste sistema.
+
+Para obter mais informações, consulte a página do manual svcs(1).\ 1pt_BR\1c<b>Current Version</b>\ 1<b>Versão atual</b>\ 1ja\1cDeleting snapshots...\ 1スナップショットを削除しています...\ 1de\1c%d snapshots will be deleted.\ 1%d Schnappschüsse werden gelöscht.\ 1ar\1cwith the name :\ 1بإسم :\ 1zh_TW\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s 具有一個或多個附屬複製,不會被刪除。要刪除此快照,請先刪除從此快照複製的所有資料集和快照。\ 1ca\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Time Slider fa còpies de seguretat regularment prenent Instantànies ZFS programades\ 1zh_HK\1cScanning for older versions\ 1掃描較舊版本\ 1zh_CN\1cSome snapshots could not be read\ 1无法读取某些快照\ 1ar\1cSnapshot created successfully\ 1صورة النظام قد أنشأت بنجاح \ 1fr\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1Le système de fichiers %s dépasse %s %% de sa capacité totale. Pour résoudre cette situation, le curseur temporel a détruit certaines sauvegardes, en détruira d'autres et finira par les détruire toutes, si la capacité continue de diminue.
+Pour éviter que cela se reproduise, supprimez tout fichier non indispensable sur %s ou ajoutez de l'espace disque (voir la documentation ZFS).\ 1ca\1cName:\ 1Nom:\ 1cs\1cSuccess\ 1Úspěch\ 1cs\1c_All\ 1_Vše\ 1hu\1cfilename\ 1fájlnév\ 1ja\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1スナップショットの削除を実行するには管理権限が必要です。必要な管理権限が割り当てられていません。
+
+システム管理者に問い合わせてください\ 1ca\1cof file system capacity\ 1de la capacitat del sistema de fitxers\ 1ca\1cDaily\ 1Diària\ 1ca\1cMonthly\ 1Mensual\ 1ca\1cSnapshot can not be deleted\ 1La instantània no pot ser eliminada\ 1fr\1cDouble click to open the file\ 1Cliquez deux fois sur le fichier pour l'ouvrir.\ 1ca\1cConfiguring Time Slider...\ 1Configurant Time Slider...\ 1nl\1cD_eselect All\ 1D_eselecteer alle\ 1zh_CN\1cDaily\ 1每天\ 1hu\1cInsufficient Priviliges\ 1Nem megfelelő jogosultságok\ 1pt_BR\1csize : \ 1tamanho : \ 1fr\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1Les caractères autorisés dans les noms d'instantané sont les suivants :
+[a-z][A-Z][0-9][-_.:
+Tous les caractères non autorisés seront supprimés
+\ 1fr\1cRecommended for most users\ 1Recommandé pour la plupart des utilisateurs\ 1it\1cReduce backups when storage space usage exceeds:\ 1Ridurre i backup quando lo spazio di memorizzazione utilizzato supera:\ 1ar\1cName:\ 1إسم : \ 1ca\1cWarning: '%s' is getting full\ 1Avís: '%s' s'està emplenant\ 1it\1cAdvanced Options\ 1Opzioni avanzate\ 1hu\1cHint\ 1Javaslat\ 1cs\1cHourly\ 1Každou hodinu\ 1cs\1cTime Slider: Low Space Warning\ 1Time Slider: Varování - málo místa\ 1pl\1cDeleting snapshots...\ 1Usuwanie migawek...\ 1ko\1cMonthly\ 1매달\ 1hu\1cC_ustom:\ 1_Egyedi:\ 1zh_TW\1cOpen the current version of the file\ 1開啟目前版本的檔案\ 1pt_BR\1cC_ustom:\ 1P_ersonalizado:\ 1de\1cAdvanced Options\ 1Erweiterte Optionen\ 1ar\1c%d snapshots will be deleted.\ 1%d الصورة سوف تمحى \ 1id\1cwith the name :\ 1dengan nama :\ 1de\1cExit when done. \ 1Beenden Sie die Anwendung, wenn Sie fertig sind.  \ 1de\1cC_ustom:\ 1B_enutzerdefiniert:\ 1pl\1cOpen the current version of the file\ 1Otwórz bieżącą wersję pliku\ 1pl\1clast modified : \ 1ostatnia modyfikacja : \ 1id\1cConfiguring Time Slider...\ 1Sedang mengkonfigurasi Time Slider...\ 1de\1cSnapshot manager service error\ 1Schnappschussverwaltungsdienst-Fehler\ 1ca\1cSnapshot created successfully\ 1Instantània correctament creada\ 1it\1cOpen the current version of the file\ 1Apri la versione corrente del file\ 1cs\1cSelect ZFS snapshots to delete from the list below.\ 1Vyberte ZFS snímek ze seznamu, který má být smazán.\ 1zh_TW\1cSelect\ 1選取\ 1pl\1cwith the name :\ 1z nazwą:\ 1nl\1cSome snapshots could not be deleted\ 1Sommige momentopnames konden niet verwijdert worden\ 1hu\1cLegacy\ 1Hagyományos\ 1ko\1cTime Slider\ 1시간 슬라이더\ 1de\1cSome snapshots could not be deleted\ 1Einige Schnappschüsse konnten nicht gelöscht werden\ 1zh_HK\1cDouble click to open the file\ 1連按兩下以開啟檔案\ 1pt_BR\1cSnapshot Name\ 1Nome do instantâneo\ 1hu\1cTime Slider Manager\ 1Time Slider Vezérlő\ 1ca\1c_All\ 1_Tots\ 1it\1cError\ 1Errore\ 1cs\1c19/01/09\ 119/01/09\ 1pl\1cInsufficient Priviliges\ 1Niewystarczające uprawnienia\ 1fr\1c10 Mo\ 110 Mo\ 1fr\1cReduce backups when storage space usage exceeds:\ 1Réduire les sauvegardes lorsque l'espace de stockage utilisé dépasse :\ 1es\1cInvalid characters in snapshot name\ 1Caracteres no válidos en el nombre de la instantánea\ 1ar\1cDetails...\ 1تفاصيل...\ 1de\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1„Schnappschuss jetzt“ erfordert 2 Argumente:
+-  Pfad des Verzeichnisses, von dem ein Schnappschuss genommen werden soll.
+-  Entsprechendes ZFS-Dateisystem für dieses Verzeichnis.\ 1nl\1cname :\ 1name :\ 1de\1cLegacy\ 1Veraltet\ 1zh_HK\1cSome snapshots could not be read\ 1無法讀取某些快照\ 1pl\1cDouble click to open the file\ 1Kliknij dwa razy, żeby otworzyć plik\ 1zh_HK\1cTime Slider Manager\ 1時間滑動軸管理員\ 1ko\1cSelect\ 1선택\ 1ar\1cConfigure the system to take automatic snapshots of your data\ 1تاكيد النظام على أخذ صورة عن النظام عن البيانات \ 1ca\1cwith the name :\ 1amb el nom :\ 1fr\1cInvalid characters in snapshot name\ 1Le nom de l'instantané contient des caractères non autorisés\ 1es\1cInsufficient Priviliges\ 1Los privilegios no son suficientes\ 1id\1cDeleting Snapshots\ 1Menghapus Snapshots\ 1pt_BR\1clast modified : \ 1última modificação: \ 1it\1cScanning snapshots...\ 1Scansione delle istantanee in corso…\ 1ca\1cThe file system: '%s', is over %s%% full.\ 1El sistema de fitxers: '%s', sobreexcedeix %s%%.\ 1hu\1cCreation Time\ 1Készítés ideje\ 1fr\1cTime Slider File Version Explorer\ 1Explorateur de versions du fichier de curseur temporel\ 1cs\1cAdvanced Options\ 1Rozšířené možnosti\ 1it\1c<b>Summary</b>\ 1<b>Riepilogo</b>\ 1nl\1cOpen the current version of the file\ 1Open de huidige versie van het bestand\ 1zh_CN\1cName:\ 1名称:\ 1it\1cname :\ 1nome :\ 1pt_BR\1cThe file system: '%s', is over %s%% full.
+As an emergency measure, Time Slider has destroyed all of its backups.
+To fix this problem, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1O sistema de arquivos: '%s' está %s%% acima.
+Como medida de emergência, a barra deslizante de tempo eliminou todos os backups.
+Para corrigir este problema, exclua os arquivos desnecessários de '%s' ou adicione espaço em disco (consulte a documentação do ZFS).\ 1nl\1cDeleting snapshots...\ 1Momentopnamen worden verwijdert...\ 1ar\1cReduce backups when storage space usage exceeds:\ 1تخفيض النسخة الإحتياطية عند تجاوز المساحة النخزينية \ 1ar\1cgtk-close\ 1gtk-إغلاق \ 1pl\1cFile System Name\ 1Nazwa systemu plików\ 1zh_HK\1c<b>Enable Time Slider</b>\ 1<b>啟用時間調整器</b>\ 1it\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1I caratteri ammessi per i nomi delle istantanee sono :
+[a-z][A-Z][0-9][-_.:
+Tutti i caratteri invalidi saranno rimossi
+\ 1pt_BR\1c<b>File Systems To Back Up</b>\ 1<b>Sistemas de arquivos dos quais fazer backup</b>\ 1zh_TW\1cAdvanced Options\ 1進階選項\ 1zh_CN\1cD_eselect All\ 1取消全选(_E)\ 1pl\1cTake a snapshot of \ 1Zrób migawkę \ 1ja\1cSuccess\ 1成功\ 1ko\1cSome snapshots could not be read\ 1일부 스냅샷을 읽을 수 없습니다.\ 1pt_BR\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1Um instantâneo do sistema de arquivos zfs %(zfs_fs)s
+denominado %(valid_name)s
+foi criado.
+\ 1ja\1cgtk-close\ 1gtk-close\ 1it\1cTime Slider Manager\ 1Gestione Time Slider\ 1zh_TW\1cwith the name :\ 1名稱為:\ 1id\1c<b>Current Version</b>\ 1<b>Versi Saat Ini</b>\ 1fr\1cTime Slider Manager\ 1Gestionnaire de curseur temporel\ 1zh_TW\1cDeleting Snapshots\ 1正在刪除快照\ 1cs\1cSnapshot created successfully\ 1Snímek byl vytvořen úspěšně\ 1pl\1cExit when done. \ 1Wyjdź kiedy skończysz. \ 1it\1cSome snapshots could not be deleted\ 1Impossibile eliminare alcune istantanee \ 1nl\1cfilename\ 1bestand naam\ 1zh_CN\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1文件系统 '%s' 已超过其总容量的 %s%%。作为一种补救措施,时间滑块已销毁了一些备份,并随着容量的不断减小,将销毁更多备份,最终销毁所有备份。
+要防止这种情况再次发生,请删除 '%s' 上所有不必要的文件,或增加磁盘空间(请参见 ZFS 文档)。\ 1cs\1cTime Slider\ 1Time Slider\ 1nl\1c_All\ 1_Alle\ 1ar\1cTime Slider File Version Explorer\ 1متصفح ملف إصدار شريط تمرير الوقت \ 1ar\1cof file system capacity\ 1قدرة نظام ملفات النظام \ 1zh_HK\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1需要具有管理權限才能執行 [快照刪除] 操作。沒有為您指定所需的管理權限。
+
+請諮詢系統管理員 \ 1de\1c1 snapshot will be deleted.\ 11 Schnappschuss wird gelöscht.\ 1de\1clast modified : \ 1Letzte Änderung:  \ 1ca\1cAdvanced Options\ 1Opcions avançades\ 1ko\1cSnapshot manager service error\ 1스냅샷 관리자 서비스 오류\ 1it\1cDelete Snapshots\ 1Elimina istantanee\ 1zh_CN\1c1 snapshot will be deleted.\ 11 个快照将被删除。\ 1zh_CN\1cSuccess\ 1成功\ 1ko\1cC_ustom:\ 1사용자 정의(_U):\ 1zh_CN\1cSelect ZFS snapshots to delete from the list below.\ 1从以下列表中选择要删除的 ZFS 快照。\ 1hu\1c%d snapshots will be deleted.\ 1%d pillanatkép törölve lesz.\ 1cs\1cInvalid arguments count.\ 1Neplatný počet argumentů.\ 1de\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1Der Schnappschussverwaltungsdienst ist von einem Problem betroffen und wurde bis zur Behebung des Problems deaktiviert.
+
+Weitere Informationen finden Sie in der Online-Dokumentation, svcs(1).\ 1pt_BR\1cFor advanced users\ 1Para usuários avançados\ 1de\1cWarning: '%s' is getting full\ 1Warnung: '%s' wird voll\ 1zh_CN\1c19/01/09\ 119/01/09\ 1de\1cDeleting Snapshots\ 1Löschen von Schnappschüssen\ 1ar\1cTake a snapshot now\ 1خذ نسخة من صورة النظام الأن \ 1es\1c1/4 Hourly\ 1Cada cuarto de hora\ 1fr\1cSnapshot can not be deleted\ 1Impossible de supprimer l'instantané\ 1pl\1cMonthly\ 1Miesięcznie\ 1ko\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1스냅샷 삭제 기능을 실행하려면 관리 권한이 필요합니다. 필요한 관리 권한이  할당되지 않았습니다.
+
+시스템 관리자에게 문의하십시오. \ 1de\1cFile System:\ 1Dateisystem:\ 1pt_BR\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1Efetuar instantâneo agora requer 2 argumentos :
+- O caminho do diretório do qual será efetuado o instantâneo.
+- O sistema de arquivos zfs correspondente a este diretório.\ 1zh_TW\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1檔案系統:「%s」超過了其總容量的 %s%%。時間調整器所採取的補救措施是銷毀部分備份,並將會銷毀更多備份,而最終會銷毀所有備份,因為容量一直不斷減少。
+若要避免再次發生這種情形,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文件)。\ 1zh_CN\1cScanning snapshots...\ 1正在扫描快照...\ 1pt_BR\1c1 snapshot will be deleted.\ 11 instantâneo será excluído.\ 1cs\1csize : \ 1velikost : \ 1ar\1cSelect ZFS snapshots to delete from the list below.\ 1إختر ZFS صور النظام لحذف من اسفل القائمة \ 1ca\1c1/4 Hourly\ 1Cada 1/4 d'hora\ 1it\1cDaily\ 1Ogni giorno\ 1cs\1cInvalid characters in snapshot name\ 1Neplatný znak v názvu snímku\ 1ja\1cSnapshot manager service dependency error\ 1スナップショットマネージャーサービスの依存関係エラー\ 1pt_BR\1cAdvanced Options\ 1Opções avançadas\ 1ar\1c1/4 Hourly\ 11/4 ساعي \ 1ca\1c<b>Current Version</b>\ 1<b>Versió Actual</b>\ 1ja\1cInvalid arguments count.\ 1引数の数が無効です。\ 1es\1cUrgent: '%s' is almost full!\ 1Urgente: '%s' se ha llenado casi del todo\ 1ko\1clast modified : \ 1마지막 수정: \ 1nl\1c19/01/09\ 119/01/09\ 1de\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1"Schnappschuss jetzt" erfordert Administratorrechte.  Ihnen wurden nicht die nötigen Administratorrechte zugewiesen.
+
+Wenden Sie sich an Ihren Systemadministrator.  \ 1zh_HK\1cD_eselect All\ 1全部取消選取(_E)\ 1de\1cPress Delete to continue.\ 1Klicken Sie auf „Löschen“, um fortzufahren.\ 1ja\1cDeleting Snapshots\ 1スナップショットを削除しています\ 1zh_HK\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1允許用於快照名稱的字元如下:
+[a-z]、[A-Z]、[0-9]、[、-、_、.、:
+將移除所有無效字元
+\ 1es\1cSnapshot Name\ 1Nombre de instantánea\ 1zh_TW\1cSnapshot created successfully\ 1已成功建立快照\ 1nl\1cHourly\ 1Ieder uur\ 1zh_HK\1c<b>File Systems To Back Up</b>\ 1<b>要備份的檔案系統</b>\ 1it\1cTake a snapshot now\ 1Crea un’istantanea\ 1ar\1c_All\ 1_الكل \ 1nl\1cDetails...\ 1Details...\ 1nl\1clast modified : \ 1laatst bewerkt : \ 1ar\1csize : \ 1الحجم : \ 1ko\1cgtk-close\ 1gtk-close\ 1zh_HK\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1由於相依性問題,已將快照管理員服務置為離線。發現以下相依性問題:
+
+%s
+
+請從指令提示符號下執行「svcs –xv」,以取得有關這些相依性問題的更多資訊。\ 1it\1cExit when done. \ 1Chiudi al termine dell'operazione. \ 1it\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1Il servizio di gestione delle istantanee è stato disconnesso a causa di un problema di dipendenza. Sono stati riscontrati i seguenti problemi di dipendenza:
+
+%s
+
+Eseguire "svcs -xv" da un prompt di comando per ottenere maggiori informazioni su questi problemi di dipendenza.\ 1pt_BR\1cInsufficient Priviliges\ 1Privilégios insuficientes\ 1ca\1cInvalid arguments count.\ 1Nombre d'arguments incorrectes.\ 1zh_CN\1cSnapshot created successfully\ 1已成功创建快照\ 1ar\1cTake a snapshot of \ 1خذ نسخة من صورة النظام \ 1fr\1cof file system capacity\ 1de la capacité du système de fichiers\ 1it\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s possiede uno o più cloni dipendenti e non verrà eliminata. Per eliminare questa istantanea, eliminare prima tutti i set di dati e le istantanee clonate da questa istantanea.\ 1nl\1cInvalid characters in snapshot name\ 1Ongeldige tekens in momentopname naam\ 1id\1cSnapshot manager service error\ 1Layanan pengendali Snapshot error\ 1cs\1cRecommended for most users\ 1Doporučeno pro většinu uživatelů\ 1ca\1cSelect\ 1Seleccionar\ 1ar\1c<b>Summary</b>\ 1<b> ملخص </b>\ 1hu\1cTake a snapshot of \ 1Pillanatkép készítése a \ 1pl\1c_Delete Snapshots...\ 1_Usuwanie Migawki...\ 1zh_TW\1cInsufficient Priviliges\ 1權限不足\ 1pt_BR\1cfilename\ 1nome de arquivo\ 1de\1cDaily\ 1Täglich\ 1de\1cDouble click to open the file\ 1Auf die Datei doppelklicken, um sie zu öffnen\ 1ko\1cfilename\ 1파일 이름\ 1zh_TW\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1[立即擷取快照] 需要 2 個引數:
+- 要進行快照擷取的目錄的路徑。
+- 與此目錄對應的 zfs 檔案系統。\ 1es\1cTake a snapshot of \ 1Tomar una instantánea de \ 1fr\1clast modified : \ 1dernière modification :  \ 1ar\1c<b>Current Version</b>\ 1<b>الإصدار الحالي</b>\ 1de\1c19/01/09\ 119/01/09\ 1de\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1Ein Schnappschuss des ZFS-Dateisystems %(zfs_fs)s
+mit dem Namen %(valid_name)s
+wurde erstellt.
+\ 1nl\1cTake a snapshot now\ 1Neem nu een momentopname\ 1zh_CN\1cwith the name :\ 1名称为:\ 1fr\1cEmergency: '%s' is almost full!\ 1Urgence : %s est presque plein !\ 1zh_TW\1cInvalid arguments count.\ 1引數計數無效。\ 1ar\1cUrgent: '%s' is almost full!\ 1عاجل : '%s' على الإغلب ممتلئ \ 1es\1cSome snapshots could not be read\ 1No se ha podido leer algunas instantáneas\ 1pl\1c<b>Current Version</b>\ 1<b> Wersja bieżąca</b>\ 1de\1cTime Slider\ 1Zeit-Schieberegler\ 1nl\1cSnapshot can not be deleted\ 1Momentopname kan niet gewist worden\ 1hu\1c10 Mo\ 110 megabájt\ 1de\1cSelect\ 1Auswählen\ 1id\1cDaily\ 1Harian\ 1nl\1cEmergency: '%s' is almost full!\ 1Noodgeval: '% s' is bijna vol!\ 1ca\1cInsufficient Priviliges\ 1Privilegis insuficients\ 1de\1cScanning snapshots...\ 1Suche nach Schnappschüssen wird ausgeführt...\ 1fr\1cHourly\ 1Toutes les heures\ 1es\1cSelect\ 1Seleccionar\ 1ca\1cEmergency: '%s' is almost full!\ 1Emergència: '%s' gairebé està ple!\ 1pt_BR\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1O caracteres permitidos em nomes de instantâneos são :
+[a-z][A-Z][0-9][-_.:
+Todos os caracteres inválidos serão removidos
+\ 1pl\1cInvalid arguments count.\ 1Niepoprawna liczba argumentów.\ 1zh_TW\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1需要具有管理權限才能執行 [立即擷取快照] 操作。沒有為您指定所需的管理權限。
+
+請諮詢系統管理員 \ 1zh_HK\1c19/01/09\ 119/01/09\ 1zh_CN\1cgtk-close\ 1gtk-close\ 1ar\1cError occured while creating the snapshot\ 1الخطأ حدث عند إنشاء صورة النظام \ 1de\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Für die Ausführung des Schnappschussverwaltungsdienstes sind Administratorrechte erforderlich. Ihnen wurden nicht die nötigen Administratorrechte zugewiesen.
+
+Wenden Sie sich an den Systemadministrator \ 1zh_HK\1cMonthly\ 1每月\ 1zh_TW\1cUrgent: '%s' is almost full!\ 1緊要:「%s」幾乎已滿!\ 1zh_HK\1c_Delete Snapshots...\ 1刪除快照(_D)...\ 1hu\1cSuccess\ 1Eredmény\ 1ko\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1버전 탐색기에 다음과 같은 2개의 인수가 필요합니다.
+- 루트 스냅샷 디렉토리의 경로
+- 탐색할 파일 이름\ 1ko\1cExit when done. \ 1완료 후 종료합니다. \ 1pl\1cTake a snapshot now\ 1Zrób migawkę teraz\ 1ja\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1「今すぐスナップショット」には次の 2 つの引数が必要です:
+- スナップショットを取得するディレクトリのパス。
+- このディレクトリに対応する zfs ファイルシステム。\ 1ca\1cError occured while creating the snapshot\ 1S'ha produït un error mentre s'estava creant la instantània\ 1zh_HK\1c<b>Older Versions</b>\ 1<b>較舊版本</b>\ 1fr\1cgtk-close\ 1gtk-close\ 1de\1csize : \ 1Größe:  \ 1zh_TW\1cError\ 1錯誤\ 1de\1cTime Slider File Version Explorer\ 1Time  Slider  File  Version  Explorer\ 1zh_TW\1cTime Slider File Version Explorer\ 1時間滑動軸檔案版本檔案總管\ 1ca\1c_Delete Snapshots...\ 1_Eliminar Instantànies...\ 1de\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1Das Dateisystem: '%s', %s%% der Gesamtkapazität überschritten. Der Zeit-Schieberegler hat im Zuge einer Abhilfemaßnahme einige Sicherungsdateien gelöscht und wird weitere und letztlich alle Sicherungsdateien löschen, wenn die Kapazität weiter abnimmt.
+Um zu verhindern, dass dieses Problem erneut auftritt, löschen Sie alle nicht benötigten Dateien auf '%s', oder fügen Sie Speicherplatz hinzu (siehe ZFS-Dokumentation).\ 1cs\1cFor advanced users\ 1Pro pokročilé uživatele\ 1zh_HK\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1需要具有管理權限才能執行 [立即擷取快照] 操作。沒有為您指定所需的管理權限。
+
+請諮詢系統管理員 \ 1nl\1cSome snapshots could not be read\ 1Sommige momentopnames konden niet gelezen worden\ 1fr\1cWarning: '%s' is getting full\ 1Avertissement : %s est presque plein\ 1zh_CN\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1版本资源管理器需要 2 个参数:
+- 根快照目录的路径。
+- 要浏览的文件名。\ 1ko\1cDeleting Snapshots\ 1스냅샷 삭제 중\ 1ko\1c19/01/09\ 119/01/09\ 1cs\1cThe file system: '%s', is over %s%% full.\ 1Souborový systém: %s', je z %s%% plný.\ 1es\1cError\ 1Error\ 1zh_HK\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1檔案系統:「%s」超過了其總容量的 %s%%。時間調整器所採取的補救措施是銷毀部分備份,並將會銷毀更多備份,而最終會銷毀所有備份,因為容量一直不斷減少。
+若要避免再次發生這種情形,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文件)。\ 1nl\1cDouble click to open the file\ 1Dubbelklik om het bestand te openen\ 1zh_TW\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1快照管理員服務遇到了問題,而且在問題修正之前都處於停用狀態。
+
+請參閱「svcs(1) 線上手冊」,以取得更多資訊。\ 1hu\1c1/4 Hourly\ 1Negyed óránkénti\ 1ja\1cTime Slider File Version Explorer\ 1タイムスライダファイルバージョンエクスプローラ\ 1nl\1cTake a snapshot of \ 1Neem een momentopname van \ 1pt_BR\1cOpen the current version of the file\ 1Abrir a versão atual do arquivo\ 1ja\1cD_eselect All\ 1すべてを選択解除(_E)\ 1pl\1cfilename\ 1nazwa pliku\ 1pt_BR\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1O serviço do gerenciador de instantâneos foi colocado off-line devido a um problema de dependência. Foram encontrados os seguintes problemas de dependência:
+
+%s
+
+Execute "svcs -xv" de um prompt de comando para obter mais informações sobre estes problemas de dependência.\ 1cs\1cSnapshot manager service error\ 1Chyba ve službě Správce snímků\ 1es\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1Una instantánea del sistema de archivos zfs %(zfs_fs)s
+llamada %(valid_name)s
+se ha creado.
+\ 1hu\1c<b>Current Version</b>\ 1<b>Jelenlegi Verzió</b>\ 1id\1c_Delete Snapshots...\ 1_Menghapus Snapshots...\ 1fr\1c1/4 Hourly\ 1Tous les quarts d'heure\ 1it\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1Il servizio di gestione delle istantanee non sembra essere installato nel sistema corrente.
+
+Per ulteriori informazioni consultare la pagina man svcs(1).\ 1ko\1cAdvanced Options\ 1고급 옵션\ 1ja\1cInvalid characters in snapshot name\ 1スナップショット名の文字が無効です\ 1de\1cScanning for older versions\ 1Nach älteren Versionen suchen\ 1nl\1cError\ 1Fout\ 1es\1c_Delete Snapshots...\ 1_Eliminar instantáneas...\ 1it\1cError occured while creating the snapshot\ 1Errore durante la creazione dell’istantanea\ 1nl\1cName:\ 1Naam:\ 1hu\1cD_eselect All\ 1Kijelölések megszüntetése\ 1zh_CN\1cError occured while creating the snapshot\ 1创建快照时发生错误\ 1ca\1cname :\ 1nom :\ 1de\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1Der Schnappschussverwaltungsdienst ist offenbar nicht auf diesem System installiert.
+
+Weitere Informationen finden Sie in der Online-Dokumentation, svcs(1).\ 1pl\1cSnapshot manager service error\ 1Błąd menadżera migawek\ 1es\1cConfigure the system to take automatic snapshots of your data\ 1Configurar el sistema para tomar instantáneas de manera automática de los datos\ 1nl\1cTime Slider File Version Explorer\ 1Tijd slijder bestand versie onverzoeker\ 1fr\1c1 snapshot will be deleted.\ 11 instantané sera supprimé.\ 1pt_BR\1cFile System Name\ 1Nome do sistema de arquivos\ 1zh_TW\1cfilename\ 1檔案名稱\ 1zh_HK\1cSelect ZFS snapshots to delete from the list below.\ 1請從以下清單中選取要刪除的 ZFS 快照。\ 1ja\1cScanning snapshots...\ 1スナップショットをスキャンしています...\ 1ar\1cname :\ 1إسم : \ 1id\1cgtk-close\ 1gtk-close\ 1ja\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1スナップショットマネージャーサービスを実行するには管理権限が必要です。必要な管理権限が割り当てられていません。
+
+システム管理者に問い合わせてください\ 1id\1cSome snapshots could not be read\ 1Beberapa snapshot tidak dapat dibaca\ 1zh_TW\1cWarning: '%s' is getting full\ 1警告:「%s」快要滿了\ 1zh_HK\1cRecommended for most users\ 1建議大多數使用者採用\ 1it\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1Crea istantanea richiede 2 argomenti :
+- La path della directory di cui deve essere creata l’istantanea.
+- Il file system zfs corrispondente a questa directory.\ 1cs\1cScanning snapshots...\ 1Skenuji snímky...\ 1zh_TW\1clast modified : \ 1上次修改時間: \ 1id\1c<b>Summary</b>\ 1<b>Hasil</b>\ 1id\1clast modified : \ 1modifikasi terakhir : \ 1de\1cname :\ 1Name:\ 1es\1c19/01/09\ 119/01/09\ 1pl\1cgtk-close\ 1gtk-zamknij\ 1es\1cHourly\ 1Cada hora\ 1pt_BR\1cDaily\ 1Diariamente\ 1hu\1cDeleting Snapshots\ 1Pillanatképek törlése\ 1id\1c_All\ 1_Semua\ 1ja\1cfilename\ 1ファイル名\ 1id\1cTime Slider: Low Space Warning\ 1Time Slider: Peringatan Tempat Penyimpanan Hampir Penuh\ 1nl\1cDelete Snapshots\ 1Verwijder momentopnamen\ 1zh_TW\1cSome snapshots could not be read\ 1無法讀取某些快照\ 1ko\1cTime Slider Manager\ 1시간 슬라이더 관리자\ 1pt_BR\1cTime Slider File Version Explorer\ 1Explorador de versões de arquivos da barra deslizante de tempo\ 1zh_HK\1cDelete Snapshots\ 1刪除快照\ 1zh_TW\1cSnapshot manager service dependency error\ 1快照管理員服務相依性錯誤\ 1zh_TW\1c1/4 Hourly\ 1每 1/4 小時\ 1fr\1cDaily\ 1Journalière\ 1ar\1cSome snapshots could not be read\ 1بعض صور النظام لايمكن أن تقرأ \ 1zh_HK\1cTake a snapshot of \ 1擷取以下項目的快照 \ 1id\1cInvalid arguments count.\ 1Kesalahan argumen bertambah\ 1ja\1c<b>Current Version</b>\ 1<b>現在のバージョン</b>\ 1fr\1c<b>File Systems To Back Up</b>\ 1<b>Systèmes de fichiers à sauvegarder</b>\ 1ar\1cFor advanced users\ 1من أجل المستخدمين المتقدمين \ 1it\1cDouble click to open the file\ 1Fare doppio clic per aprire il file\ 1zh_CN\1cUrgent: '%s' is almost full!\ 1紧急:'%s' 几乎已满!\ 1cs\1cError\ 1Chyba\ 1de\1cSnapshot can not be deleted\ 1Schnappschuss kann nicht gelöscht werden\ 1es\1cRecommended for most users\ 1Recomendado para la mayoría de los usuarios\ 1zh_TW\1cSome snapshots could not be deleted\ 1無法刪除某些快照\ 1pl\1cSelect\ 1Wybierz\ 1ja\1cSnapshot manager service error\ 1スナップショットマネージャーサービスのエラー\ 1zh_TW\1cDaily\ 1每天\ 1es\1cScanning snapshots...\ 1Buscando instantáneas...\ 1cs\1cWarning: '%s' is getting full\ 1Upozornění: '% s' se zaplňuje\ 1nl\1cHint\ 1Hint\ 1zh_TW\1c<b>Current Version</b>\ 1<b>目前版本</b>\ 1es\1c<b>Older Versions</b>\ 1<b>Versiones anteriores</b>\ 1ko\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1스냅샷 관리자 서비스를 실행하려면 관리 권한이 필요합니다. 필요한관리 권한이 지정되지 않았습니다.
+
+시스템 관리자에게 문의하십시오. \ 1zh_HK\1cOpen the current version of the file\ 1開啟目前版本的檔案\ 1ar\1cSnapshot manager service dependency error\ 1خدمة إدارة صورة النظام  تعتمد خطأ \ 1pt_BR\1c1/4 Hourly\ 1Cada 15 minutos\ 1ar\1cFile System Name\ 1إسم ملف النظام \ 1es\1cEmergency: '%s' is almost full!\ 1Emergencia: '%s' se ha llenado casi del todo\ 1id\1cMonthly\ 1Bulanan\ 1nl\1cTime Slider Manager\ 1Tijd glijder beheerder\ 1cs\1c10 Mo\ 1Pondělí 10\ 1zh_TW\1cDouble click to open the file\ 1連按兩下以開啟檔案\ 1hu\1cgtk-close\ 1gtk-close\ 1ko\1cTime Slider File Version Explorer\ 1시간 슬라이더 파일 버전 탐색기\ 1ko\1c<b>File Systems To Back Up</b>\ 1<b>백업할 파일 시스템</b>\ 1id\1cfilename\ 1nama file\ 1pt_BR\1cgtk-close\ 1gtk-close\ 1zh_HK\1cEmergency: '%s' is almost full!\ 1緊急:「%s」幾乎已滿!\ 1ja\1cInsufficient Priviliges\ 1権限が不足しています\ 1ar\1cRecommended for most users\ 1المطلوب من كل المستخدمين \ 1zh_HK\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1版本檔案總管需要 2 個引數:
+- 快照根目錄的路徑。
+- 要瀏覽的檔案名稱。\ 1nl\1cUrgent: '%s' is almost full!\ 1Urgent: '% s' is bijna vol!\ 1fr\1cInvalid arguments count.\ 1Nombre d'arguments incorrect.\ 1ja\1cSnapshot created successfully\ 1スナップショットが正常に作成されました\ 1ar\1cThe file system: '%s', exceeded %s%% of its total capacity\ 1نظام الملفات: '%s', تجاوز %s%% فوق كل السعة الكلية \ 1cs\1cDeleting Snapshots\ 1Mažu snímky\ 1zh_TW\1cEmergency: '%s' is full!\ 1緊急:「%s」已滿!\ 1fr\1c%d snapshots will be deleted.\ 1%d instantanés seront supprimés.\ 1ar\1c<b>File Systems To Back Up</b>\ 1<b> ملف النظام للنسخة الإحتياطية </b>\ 1id\1cSnapshot Name\ 1Nama Snapshot\ 1it\1cConfigure the system to take automatic snapshots of your data\ 1Configurare il sistema per fare delle istantanee automatiche dei propri dati\ 1hu\1cExit when done. \ 1Kilépés, ha elkészült. \ 1zh_CN\1cTime Slider File Version Explorer\ 1时间滑块文件版本资源管理器\ 1zh_TW\1c1 snapshot will be deleted.\ 1將刪除 1 個快照。\ 1id\1c<b>File Systems To Back Up</b>\ 1<b>File Systems To Back Up</b>\ 1de\1c10 Mo\ 110  Mo\ 1de\1cInsufficient Priviliges\ 1Nicht ausreichend Zugriffsrechte\ 1ko\1c%d snapshots will be deleted.\ 1%d개의 스냅샷이 삭제됩니다.\ 1zh_CN\1cMount Point\ 1挂载点\ 1ja\1cFile System:\ 1ファイルシステム: \ 1id\1cC_ustom:\ 1C_ustom:\ 1es\1cC_ustom:\ 1_Personalizar:\ 1id\1cUrgent: '%s' is almost full!\ 1Mendesak: '%s' hampir penuh!\ 1es\1c_All\ 1_Todo\ 1es\1cwith the name :\ 1con el nombre:\ 1zh_TW\1c_Delete Snapshots...\ 1刪除快照(_D)...\ 1hu\1cError\ 1Hiba\ 1id\1cEmergency: '%s' is almost full!\ 1Darurat: '%s' hampir penuh!\ 1nl\1cPress Delete to continue.\ 1Druk delete om door te gaan.\ 1pt_BR\1c<b>Enable Time Slider</b>\ 1<b>Ativar a barra deslizante de tempo</b>\ 1fr\1c<b>Older Versions</b>\ 1<b>Anciennes versions</b>\ 1pl\1cThe file system: '%s', is over %s%% full.\ 1The file system: '%s', is over %s%% full.\ 1zh_TW\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1需要具有管理權限才能執行 [快照刪除] 操作。沒有為您指定所需的管理權限。
+
+請諮詢系統管理員 \ 1cs\1cDeleting snapshots...\ 1Mažu snímky...\ 1zh_HK\1ccompare\ 1對比\ 1it\1cSnapshot can not be deleted\ 1Impossibile eliminare l’istantanea\ 1ar\1cC_ustom:\ 1C_ustom:\ 1hu\1cSelect ZFS snapshots to delete from the list below.\ 1Jelöljön ki ZFS pillanatképeket törlésre a listából.\ 1hu\1cname :\ 1név :\ 1ar\1cScanning for older versions\ 1الفحص للإصدارات الأقدم \ 1ko\1cInvalid characters in snapshot name\ 1스냅샷 이름에 잘못된 문자가 있습니다.\ 1zh_TW\1c<b>File Systems To Back Up</b>\ 1<b>要備份的檔案系統</b>\ 1zh_HK\1c<b>Summary</b>\ 1<b>摘要</b>\ 1pt_BR\1cAll\ 1Todos\ 1nl\1cDeleting Snapshots\ 1Momentopnames worden verwijdert\ 1cs\1c<b>Enable Time Slider</b>\ 1<b>Povolit Time Slider</b>\ 1es\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1El servicio de administrador de instantáneas se ha quedado sin conexión por un problema de dependencia. Se han detectado los siguientes problemas de dependencia:
+
+%s
+
+Ejecute "svcs -xv" desde un indicador de comandos para obtener más información sobre estos problemas de dependencia.\ 1pt_BR\1cWarning: '%s' is getting full\ 1Aviso: '%s' está ficando cheio\ 1zh_TW\1cHourly\ 1每小時\ 1zh_CN\1c_All\ 1全部(_A)\ 1it\1cFile System:\ 1File system:\ 1zh_HK\1c%d snapshots will be deleted.\ 1將刪除 %d 個快照。\ 1hu\1cError occured while creating the snapshot\ 1Hiba lépett fel pillanatkép készítésekor\ 1ja\1cMount Point\ 1マウントポイント\ 1ar\1c<b>Older Versions</b>\ 1<b>الإصدارات السابقة</b>\ 1it\1cWeekly\ 1Settimanale\ 1zh_HK\1cUrgent: '%s' is almost full!\ 1緊要:「%s」幾乎已滿!\ 1zh_HK\1cExit when done. \ 1完成後結束。 \ 1pt_BR\1cRecommended for most users\ 1Recomendado para a maioria dos usuários\ 1id\1c10 Mo\ 110 Mo\ 1hu\1cof file system capacity\ 1fájlrendszer kapacitásának\ 1ca\1cTake a snapshot of \ 1Fer una instantània de \ 1es\1cD_eselect All\ 1D_eseleccionar todo\ 1it\1cHourly\ 1Ogni ora\ 1nl\1cMonthly\ 1Maandelijks\ 1hu\1cSome snapshots could not be deleted\ 1Néhány pillanatkép nem törölhető\ 1fr\1cSelect ZFS snapshots to delete from the list below.\ 1Sélectionnez les instantanés ZFS à supprimer dans la liste suivante.\ 1cs\1cfilename\ 1jméno souboru\ 1es\1c10 Mo\ 110 Mo\ 1pl\1c<b>File Systems To Back Up</b>\ 1<b>System plików do Back Up</b>\ 1ar\1cScanning snapshots...\ 1فحص صور النظام \ 1pt_BR\1cName:\ 1Nome:\ 1zh_CN\1cExit when done. \ 1完成后退出。 \ 1hu\1cRecommended for most users\ 1Ajánlott az átlagfelhasználóknak\ 1nl\1cConfiguring Time Slider...\ 1Configuring Time Slider...\ 1nl\1cFor advanced users\ 1Voor geavanceerde gebruikers\ 1it\1c_All\ 1_Tutto\ 1zh_HK\1cDeleting Snapshots\ 1正在刪除快照\ 1pt_BR\1cMonthly\ 1Mensalmente\ 1id\1cFor advanced users\ 1Untuk pengguna lanjutan\ 1de\1cError\ 1Fehler\ 1zh_CN\1cCreation Time\ 1创建时间\ 1fr\1c_All\ 1_Tous\ 1zh_TW\1cTime Slider Manager\ 1時間滑動軸管理員\ 1id\1cSnapshot can not be deleted\ 1Snapshot tidak dapat dihapus\ 1ja\1cEmergency: '%s' is full!\ 1緊急: '%s' がいっぱいです。\ 1it\1cPress Delete to continue.\ 1Premere Elimina per continuare.\ 1zh_CN\1cAdvanced Options\ 1高级选项\ 1zh_TW\1c_All\ 1全部(_A)\ 1zh_CN\1cfilename\ 1文件名\ 1cs\1ccompare\ 1porovnat\ 1hu\1cSelect\ 1Kiválasztás\ 1pl\1cThe file system: '%s', exceeded %s%% of its total capacity\ 1The file system: '%s', exceeded %s%% of its total capacity\ 1zh_TW\1cTake a snapshot now\ 1立即擷取快照\ 1ko\1cFile System Name\ 1파일 시스템 이름\ 1hu\1cEmergency: '%s' is full!\ 1Vészhelyzet: '%s' megtelt!\ 1nl\1cReduce backups when storage space usage exceeds:\ 1Verminder back-ups als opslagruimte gebruik meer bedraagt dan:\ 1ja\1cC_ustom:\ 1カスタム(_U): \ 1pt_BR\1c<b>Summary</b>\ 1<b>Resumo</b>\ 1it\1cSelect ZFS snapshots to delete from the list below.\ 1Selezionare le istantanee ZFS da eliminare dall’elenco di seguito riportato.\ 1zh_CN\1cTake a snapshot now\ 1立即捕获快照\ 1zh_CN\1c10 Mo\ 110 Mo\ 1es\1cTime Slider Manager\ 1Administrador del deslizador de tiempo\ 1zh_CN\1cname :\ 1名称:\ 1pt_BR\1cTime Slider\ 1Barra deslizante de tempo\ 1zh_HK\1cFile System Name\ 1檔案系統名稱\ 1it\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1La capacità totale del file system '%s' è stata superata del %s%%. Come rimedio, Time Slider ha eliminato alcuni backup e ne eliminerà altri o tutti man mano che la capacità diminuisce.
+Per evitare il ripetersi del problema, eliminare eventuali file non necessari in '%s' oppure aggiungere spazio sul disco (vedere la documentazione di ZFS).\ 1zh_HK\1cError\ 1錯誤\ 1ar\1cOpen the current version of the file\ 1إفتح نفس إصدار الملف \ 1cs\1c1/4 Hourly\ 1Každou 1/4 hodinu\ 1fr\1cAdvanced Options\ 1Options avancées\ 1it\1csize : \ 1dimensioni : \ 1zh_HK\1cDeleting snapshots...\ 1正在刪除快照...\ 1pt_BR\1cScanning for older versions\ 1Explorando versões mais antigas\ 1fr\1cTake a snapshot now\ 1Prenez un instantané\ 1pl\1cFile System:\ 1System plików:\ 1id\1cWarning: '%s' is getting full\ 1Peringatan: '%s' mulai penuh\ 1fr\1cfilename\ 1nom de fichier\ 1fr\1cMonthly\ 1Mensuelle\ 1pl\1cWarning: '%s' is getting full\ 1Ostrzeżenie: '%s' staje się pełny\ 1es\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Tomar instantánea ahora necesita privilegios administrativos. No se le han asignado los correspondientes privilegios administrativos.
+
+Consulte al administrador del sistema\ 1fr\1c<b>Enable Time Slider</b>\ 1<b>Activer le curseur temporel</b>\ 1ja\1cTime Slider Manager\ 1タイムスライダマネージャー\ 1cs\1c<b>File Systems To Back Up</b>\ 1<b>Záloha souborového systému</b>\ 1fr\1cFile System:\ 1Système de fichiers :\ 1ca\1cFor advanced users\ 1Per a usuaris avançats\ 1ca\1c1 snapshot will be deleted.\ 11 instantània serà eliminada.\ 1nl\1cInsufficient Priviliges\ 1Onvoldoende Privileges\ 1ar\1cTime Slider\ 1شريط تمرير الوقت \ 1de\1cSuccess\ 1Erfolg\ 1fr\1cTime Slider\ 1Curseur temporel\ 1zh_CN\1cWeekly\ 1每周\ 1fr\1cC_ustom:\ 1Pers_onnalisé :\ 1fr\1cSnapshot Name\ 1Nom de l'instantané\ 1ca\1cDouble click to open the file\ 1Doble clic per a obrir un fitxer\ 1zh_CN\1cDouble click to open the file\ 1双击以打开文件\ 1ar\1cEmergency: '%s' is almost full!\ 1الخظر : '%s'  على الأغلب كامل \ 1ja\1cTake a snapshot of \ 1スナップショットを取得する対象 \ 1ca\1cTake a snapshot now\ 1Fer una instantània ara\ 1de\1cMount Point\ 1Einhängepunkt\ 1cs\1cEmergency: '%s' is full!\ 1Stav nouze: '%s' je plný!\ 1pt_BR\1cTake a snapshot of \ 1Efetuar um instantâneo de \ 1hu\1cDelete Snapshots\ 1Pillanatképek törlése\ 1fr\1cUrgent: '%s' is almost full!\ 1Urgent : %s est presque plein !\ 1it\1c10 Mo\ 110 Mo\ 1es\1cWarning: '%s' is getting full\ 1Advertencia: '%s' se está llenando\ 1ca\1cTime Slider File Version Explorer\ 1Explorador de Versions de Fitxer de Time Slider\ 1ko\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1스냅샷 관리자 서비스에 문제가 발생하여 문제가 수정될 때까지 비활성화되었습니다.
+
+자세한 내용은 svcs(1) 매뉴얼 페이지를 참조하십시오.\ 1pl\1cTime Slider: Low Space Warning\ 1Time Slider: Low Space Warning\ 1ko\1cScanning for older versions\ 1이전 버전 검색 중\ 1it\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Per l'esecuzione del servizio di gestione delle istantanee sono necessari privilegi amministrativi. Non si dispone di privilegi amministrativi sufficienti.
+
+Rivolgersi all'amministratore di sistema. \ 1pl\1c1/4 Hourly\ 1Co 15 minut\ 1cs\1c_Delete Snapshots...\ 1_Smazat snímek...\ 1ja\1c<b>Summary</b>\ 1<b>要約</b>\ 1ar\1cSuccess\ 1نجاح \ 1zh_CN\1cFor advanced users\ 1适用于高级用户\ 1ja\1cSelect ZFS snapshots to delete from the list below.\ 1下の一覧から削除する ZFS スナップショットを選択します。\ 1ko\1cConfigure the system to take automatic snapshots of your data\ 1사용자 데이터의 자동 스냅샷을 만들도록 시스템 구성\ 1es\1cThe snapshot manager service requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1El servicio de administrador de instantáneas necesita privilegios administrativos. No se le ha asignado los correspondientes privilegios administrativos.
+
+Consulte al administrador del sistema \ 1fr\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s a un ou plusieurs clones dépendants et ne sera pas supprimé.  Supprimez au préalable tous les jeux de données et instantanés clonés à partir de cet instantané pour pouvoir supprimer ce dernier.\ 1nl\1c<b>Enable Time Slider</b>\ 1<b>Schakel tijd slijder in</b>\ 1zh_TW\1cDelete Snapshots\ 1刪除快照\ 1ko\1c<b>Current Version</b>\ 1<b>현재 버전</b>\ 1zh_TW\1cFile System Name\ 1檔案系統名稱\ 1id\1cof file system capacity\ 1dari kapasitas file sistem\ 1ja\1cPress Delete to continue.\ 1続行するには「削除」を押します。\ 1it\1c<b>File Systems To Back Up</b>\ 1<b>File system di cui eseguire il backup</b>\ 1fr\1cDeleting Snapshots\ 1Suppression des instantanés\ 1de\1cTake a snapshot now\ 1Jetzt einen Schnappschuss nehmen\ 1ar\1cAll\ 1الكل \ 1zh_TW\1cRecommended for most users\ 1建議大多數使用者採用\ 1pt_BR\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1O sistema de arquivos: '%s' excedeu %s%% da capacidade total. Como medida de reforço, a barra deslizante de tempo eliminou alguns backups e eliminará mais, eventualmente todos, caso a capacidade continue diminuindo.
+Para evitar que isso acorra novamente, exclua os arquivos desnecessários de '%s' ou adicione espaço em disco (consulte a documentação do ZFS).\ 1zh_HK\1c_All\ 1全部(_A)\ 1nl\1cSnapshot manager service error\ 1Momentopname manager service fout\ 1de\1cFor advanced users\ 1Für erfahrene Benutzer\ 1id\1c1 snapshot will be deleted.\ 11 snapshot akan di hapus\ 1pl\1cEmergency: '%s' is full!\ 1Uwaga: '%s' jest zapełniony\ 1zh_TW\1cAll\ 1全部\ 1es\1c1 snapshot will be deleted.\ 1Se eliminará 1 instantánea.\ 1ca\1cDeleting Snapshots\ 1Eliminant Instantànies\ 1zh_HK\1cLegacy\ 1原來的\ 1zh_CN\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1需要有管理权限才能删除快照。没有为您指定必要的管理权限。
+
+请咨询您的系统管理员 \ 1pt_BR\1cDeleting snapshots...\ 1Excluindo instantâneos...\ 1ja\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1バージョンエクスプローラには次の 2 つの引数が必要です:
+- ルートスナップショットディレクトリのパス。
+- 調査するファイル名。\ 1nl\1c1 snapshot will be deleted.\ 11 momentopname zal niet verwijdert worden\ 1hu\1cMonthly\ 1Havi\ 1pl\1cScanning for older versions\ 1Wyszukuje starsze wersje\ 1ja\1cFile System Name\ 1ファイルシステム名\ 1it\1cRecommended for most users\ 1Per tutti gli utenti\ 1nl\1cScanning snapshots...\ 1Momentopnamen aan het scanderen...\ 1id\1cLegacy\ 1Legacy\ 1nl\1cSelect\ 1Selecteer\ 1it\1cSnapshot manager service dependency error\ 1Errore di dipendenza del servizio di gestione delle istantanee\ 1ko\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1스냅샷 관리자 서비스가 이 시스템에 설치된 것으로 나타나지 않습니다.
+
+자세한 내용은 svcs(1) 매뉴얼 페이지를 참조하십시오.\ 1zh_CN\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1立即进行快照需要 2 个参数:
+- 要进行快照的目录的路径。
+- 与此目录相对应的 zfs 文件系统。\ 1pt_BR\1cLegacy\ 1Legado\ 1es\1cWeekly\ 1Cada semana\ 1pl\1cHint\ 1Hint\ 1fr\1ccompare\ 1comparaison\ 1id\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Time Slider membackup data secara teratur berdasarkan waktu Snapshot ZFS\ 1it\1c%d snapshots will be deleted.\ 1Verranno eliminate %d istantanee.\ 1es\1cgtk-close\ 1gtk-cerrar\ 1es\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1El servicio de administrador de instantáneas parece no estar instalado en este sistema.
+
+Para obtener más información, consulte la página de comando man svcs(1).\ 1ca\1cHint\ 1Pista\ 1pt_BR\1cFile System:\ 1Sistema de arquivos:\ 1hu\1cScanning for older versions\ 1Keresés régebbi verziók után\ 1ja\1cConfigure the system to take automatic snapshots of your data\ 1自動的にデータのスナップショットを作成するようにシステムを構成します\ 1hu\1cEmergency: '%s' is almost full!\ 1Vészhelyzet: '%s' majdnem teli!\ 1cs\1cSnapshot can not be deleted\ 1Snímek nemůže být smazán\ 1hu\1c1 snapshot will be deleted.\ 11 pillanatkép kerül törlésre.\ 1pt_BR\1cTake a snapshot now\ 1Efetuar um instantâneo agora\ 1pt_BR\1c_Delete Snapshots...\ 1_Excluir instantâneos...\ 1nl\1cCreation Time\ 1Aanmaaktijd\ 1de\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1Der Schnappschussverwaltungsdienst wurde wegen eines Abhängigkeitsproblems offline geschaltet.  Folgende Abhängigkeitsprobleme wurden festgestellt:
+
+%s
+
+Führen Sie über eine Eingabeaufforderung den Befehl "svcs  -xv" aus, um weitere Informationen zu diesen Abhängigkeitsproblemen zu erhalten.\ 1nl\1cScanning for older versions\ 1Zoeken naar oudere versies\ 1cs\1cgtk-close\ 1gtk-close\ 1ja\1cRecommended for most users\ 1ほとんどのユーザーに推奨\ 1pl\1c19/01/09\ 119/01/09\ 1zh_TW\1cThe snapshot manager service has been placed offline due to a dependency problem. The following dependency problems were found:
+
+%s
+
+Run "svcs -xv" from a command prompt for more information about these dependency problems.\ 1由於相依性問題,已將快照管理員服務置為離線。發現以下相依性問題:
+
+%s
+
+請從指令提示符號下執行「svcs –xv」,以取得有關這些相依性問題的更多資訊。\ 1it\1cSnapshot created successfully\ 1Istantanea creata con successo\ 1zh_CN\1cFile System Name\ 1文件系统名称\ 1pt_BR\1cname :\ 1nome :\ 1cs\1cTake a snapshot of \ 1Pořídit snímek \ 1id\1cSnapshot manager service dependency error\ 1Kesalahan dependensi layanan pengendali Snapshot\ 1ar\1cInvalid characters in snapshot name\ 1خطأ برموز إسم صورة النظام \ 1fr\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Pour utiliser l'option Prendre un instantané, vous devez posséder des privilèges administratifs.  Vous ne possédez pas les privilèges administratifs requis.
+
+Consultez votre administrateur système  \ 1hu\1c<b>Enable Time Slider</b>\ 1<b>Time Slider engedélyezése</b>\ 1zh_TW\1cgtk-close\ 1gtk-close\ 1de\1cSnapshot deletion requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Die Löschung von Schnappschüssen erfordert Administratorrechte.  Ihnen wurden nicht die nötigen Administratorrechte zugewiesen.
+
+Wenden Sie sich an Ihren Systemadministrator.  \ 1ja\1cThe file system: '%s', exceeded %s%% of its total capacity. As a remedial measure, Time Slider has destroyed some backups, and will destroy more, eventually all, as capacity continues to diminish.
+To prevent this from happening again, delete any unnecessary files on '%s', or add disk space (see ZFS documentation).\ 1ファイルシステム: '%s' が総容量の %s%% を超えました。是正手段として、タイムスライダはすでに一部のバックアップを破棄しており、容量が減り続ければさらに多くのバックアップ、最終的にはすべてのバックアップを破棄します。
+この問題がふたたび発生しないようにするために、'%s' 上の不必要なファイルをすべて削除するか、またはディスク容量を追加してください (ZFS のマニュアルを参照)。\ 1pl\1cof file system capacity\ 1możliwości systemu plików\ 1ko\1cSnapshot manager service dependency error\ 1스냅샷 관리자 서비스 종속성 오류\ 1fr\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1Le service de gestionnaire d'instantanés a rencontré un problème et a été désactivé jusqu'à la résolution du problème.
+
+Pour de plus amples informations, reportez-vous à la page de manuel svcs(1).\ 1zh_HK\1cgtk-close\ 1gtk-close\ 1ko\1cSnapshot can not be deleted\ 1스냅샷을 삭제할 수 없습니다.\ 1cs\1cC_ustom:\ 1V_lastní\ 1ja\1c1/4 Hourly\ 115 分ごと\ 1ko\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1스냅샷 이름에 사용할 수 있는 문자는 다음과 같습니다.
+[a-z][A-Z][0-9][-_.:
+잘못된 문자는 모두 제거됩니다.
+\ 1pt_BR\1cEmergency: '%s' is full!\ 1Emergência: '%s' está cheio!\ 1fr\1cDelete Snapshots\ 1Supprimer des instantanés\ 1ko\1c<b>Older Versions</b>\ 1<b>이전 버전</b>\ 1zh_TW\1cPress Delete to continue.\ 1請按下 [刪除] 繼續。\ 1ko\1cScanning snapshots...\ 1스냅샷 검색 중...\ 1hu\1cSnapshot manager service error\ 1Pillanatkép kezelő szolgáltatás hiba\ 1ca\1cD_eselect All\ 1De-_seleccionar-ho Tot\ 1ar\1cMonthly\ 1شهريا \ 1nl\1cLegacy\ 1Legaat\ 1ko\1cFile System:\ 1파일 시스템:\ 1ko\1cError\ 1오류\ 1ca\1c%d snapshots will be deleted.\ 1%d instantànies a ser eliminades.\ 1hu\1cConfiguring Time Slider...\ 1Time Slider konfigurációja...\ 1ar\1cCreation Time\ 1إنشاء الوقت \ 1hu\1cInvalid arguments count.\ 1Érvénytelen argumentum szám.\ 1zh_TW\1csize : \ 1大小: \ 1it\1cSuccess\ 1Operazione riuscita\ 1fr\1cSome snapshots could not be read\ 1Certains instantanés n'ont pas pu être lus\ 1cs\1cFile System Name\ 1Jméno souborového systému\ 1it\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1Il servizio di gestione delle istantanee ha riscontrato un problema ed è stato disabilitato fino alla risoluzione del problema.
+
+Per ulteriori informazioni consultare la pagina man svcs(1).\ 1de\1cTime Slider Manager\ 1Zeit-Schieberegler-Manager\ 1pt_BR\1cSnapshot created successfully\ 1Instantâneo criado com êxito\ 1zh_CN\1c_Delete Snapshots...\ 1删除快照(_D)...\ 1ko\1cTake a snapshot of \ 1다음 항목의 스냅샷 실행 \ 1ko\1c1 snapshot will be deleted.\ 11개의 스냅샷이 삭제됩니다.\ 1it\1cMount Point\ 1Punto di attivazione\ 1pt_BR\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1O explorador de versão requer 2 argumentos :
+- O caminho do diretório raiz do instantâneo.
+- O nome de arquivo para exploração.\ 1fr\1cSuccess\ 1Terminé sans erreur\ 1id\1cFile System Name\ 1Nama File Sistem\ 1it\1cWarning: '%s' is getting full\ 1Avvertenza: lo spazio su '%s' sta per esaurirsi\ 1ar\1cfilename\ 1إسم الملف \ 1fr\1cFor advanced users\ 1Pour les utilisateurs expérimentés\ 1zh_HK\1cHourly\ 1每小時\ 1nl\1cof file system capacity\ 1van bestand systeem capaciteit\ 1pt_BR\1cError\ 1Erro\ 1nl\1cC_ustom:\ 1C_ustom:\ 1zh_HK\1cMount Point\ 1掛載點\ 1de\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Der Zeit-Schieberegler sichert regelmäßig Daten durch Erfassung von zeitlich festgelegten ZFS-Schnappschüssen\ 1cs\1cSome snapshots could not be read\ 1Některé snímky nelze přečíst\ 1zh_TW\1cD_eselect All\ 1全部取消選取(_E)\ 1it\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1Un’istantanea del file system zfs %(zfs_fs)s
+denominata %(valid_name)s
+è stata creata.
+\ 1zh_CN\1cConfigure the system to take automatic snapshots of your data\ 1将系统配置为自动捕获数据的快照\ 1zh_TW\1cSnapshot manager service error\ 1快照管理員服務錯誤\ 1zh_TW\1cInvalid characters in snapshot name\ 1快照名稱中有無效字元\ 1pl\1cScanning snapshots...\ 1Wyszukuje migawki...\ 1nl\1cSelect ZFS snapshots to delete from the list below.\ 1Kies de te verwijderen ZFS momentopnamen van de lijst beneden. \ 1ar\1cTime Slider: Low Space Warning\ 1شريط التوقيت : تحذير بإنخفاض المساحة\ 1es\1cTime Slider File Version Explorer\ 1Explorador de versiones de archivos del deslizador de tiempo\ 1es\1cOpen the current version of the file\ 1Abrir la versión actual del archivo\ 1ja\1cError\ 1エラー\ 1zh_HK\1c10 Mo\ 110 Mo\ 1fr\1cDeleting snapshots...\ 1Suppression des instantanés...\ 1nl\1cMount Point\ 1Monteer punt\ 1ja\1cScanning for older versions\ 1旧バージョンをスキャンしています\ 1pt_BR\1c%d snapshots will be deleted.\ 1%d instantâneos serão excluídos.\ 1zh_TW\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1快照管理員服務似乎並未安裝於此系統上。
+
+請參閱「svcs(1) 線上手冊」,以取得更多資訊。\ 1id\1cName:\ 1Nama:\ 1ja\1c<b>Enable Time Slider</b>\ 1<b>タイムスライダを有効にする</b>\ 1id\1cSome snapshots could not be deleted\ 1Beberapa snapshot tidak dapat dihapus\ 1zh_HK\1cScanning snapshots...\ 1正在掃描快照...\ 1pl\1cTime Slider Manager\ 1Menadżer Time Slider\ 1ar\1c10 Mo\ 110 Mo\ 1it\1cName:\ 1Nome:\ 1zh_HK\1cInvalid arguments count.\ 1引數計數無效。\ 1ko\1cLegacy\ 1레거시\ 1nl\1cEmergency: '%s' is full!\ 1Alarm: '% s' is vol!\ 1cs\1cMonthly\ 1Měsíčně\ 1ja\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s には 1 つ以上の複製が依存しているため、削除されません。このスナップショットを削除するには、まず、このスナップショットから複製されたすべてのデータセットとスナップショットを削除してください。\ 1zh_CN\1cHourly\ 1每小时\ 1fr\1cD_eselect All\ 1Tout désél_ectionner\ 1ca\1cThe file system: '%s', exceeded %s%% of its total capacity\ 1El sistema de fitxers: '%s', excedeix %s%% de la seva capacitat total\ 1ja\1cName:\ 1名前: \ 1ca\1cSuccess\ 1Realitzat\ 1id\1c1/4 Hourly\ 1Tiap 1/4 jam\ 1ja\1cCreation Time\ 1作成時間\ 1pl\1cDelete Snapshots\ 1Usuwam migawki\ 1ar\1cWeekly\ 1إسبوعيا \ 1zh_HK\1cThe snapshot manager service has encountered a problem and has been disabled until the problem is fixed.
+
+See the svcs(1) man page for more information.\ 1快照管理員服務遇到了問題,而且在問題修正之前都處於停用狀態。
+
+請參閱「svcs(1) 線上手冊」,以取得更多資訊。\ 1es\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1Los caracteres permitidos en los nombres de las instantáneas son:
+[a-z][A-Z][0-9][-_.:
+Se suprimirán todos los caracteres no válidos
+\ 1pt_BR\1cHourly\ 1De hora em hora\ 1ko\1cSnapshot created successfully\ 1스냅샷이 성공적으로 생성되었습니다.\ 1zh_TW\1cAllowed characters for snapshot names are :
+[a-z][A-Z][0-9][-_.:
+All invalid characters will be removed
+\ 1允許用於快照名稱的字元如下:
+[a-z]、[A-Z]、[0-9]、[、-、_、.、:
+將移除所有無效字元
+\ 1pl\1cD_eselect All\ 1O_dznacz wszystkie\ 1ca\1cScanning for older versions\ 1Escanejant per a versions antigues\ 1zh_CN\1cRecommended for most users\ 1建议大多数用户采用\ 1pl\1cName:\ 1Nazwa:\ 1pt_BR\1cD_eselect All\ 1Cancelar s_eleção de todos\ 1hu\1c_All\ 1_Mind\ 1ar\1ccompare\ 1مقارنة \ 1id\1cConfigure the system to take automatic snapshots of your data\ 1  \ 1zh_HK\1cname :\ 1名稱:\ 1hu\1cTake a snapshot now\ 1Pillanatkép készítése most\ 1es\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s tiene uno o más duplicados y no se puede eliminar. Para eliminar esta instantánea, primero debe borrar todos sus conjuntos de datos e instantáneas duplicados.\ 1it\1cwith the name :\ 1con il nome :\ 1zh_CN\1cFile System:\ 1文件系统:\ 1id\1cSelect ZFS snapshots to delete from the list below.\ 1Pilih ZFS snapshots untuk menghapus dari daftar dibawah ini.\ 1fr\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1L'option Prendre un instantané nécessite 2 arguments :
+- Chemin d'accès au répertoire dont un instantané doit être pris.
+- Système de fichiers ZFS correspondant à ce répertoire.\ 1id\1c<b>Enable Time Slider</b>\ 1<b>Enable Time Slider</b>\ 1zh_CN\1cScanning for older versions\ 1正在扫描早期版本\ 1es\1cEmergency: '%s' is full!\ 1Emergencia: '%s' se ha llenado\ 1ko\1cSome snapshots could not be deleted\ 1일부 스냅샷을 삭제할 수 없습니다.\ 1it\1cEmergency: '%s' is full!\ 1Attenzione: '%s' è pieno.\ 1zh_HK\1cFile System:\ 1檔案系統:\ 1ja\1cA snapshot of zfs filesystem %(zfs_fs)s
+named %(valid_name)s
+has been created.
+\ 1zfs ファイルシステム %(zfs_fs)s のスナップショット
+(名前は %(valid_name)s)
+が作成されました。
+\ 1ja\1cwith the name :\ 1名前: \ 1nl\1cDaily\ 1Dagelijks\ 1ko\1c10 Mo\ 110Mo\ 1es\1c<b>Current Version</b>\ 1<b>Versión actual</b>\ 1it\1cSelect\ 1Seleziona\ 1nl\1ccompare\ 1vergelijk\ 1cs\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Time Slider zálohuje pravidelně data pomocí časových ZFS smínků\ 1es\1c<b>File Systems To Back Up</b>\ 1<b>Sistemas de archivos de los que hacer copia de seguridad</b>\ 1zh_HK\1cSome snapshots could not be deleted\ 1無法刪除某些快照\ 1id\1cError occured while creating the snapshot\ 1Terjadi error ketika membuat snapshot\ 1zh_HK\1cEmergency: '%s' is full!\ 1緊急:「%s」已滿!\ 1ca\1cOpen the current version of the file\ 1Obrir la versió actual del fitxer\ 1pl\1ccompare\ 1porównaj\ 1zh_TW\1cCreation Time\ 1建立時間\ 1id\1cTake a snapshot of \ 1Mengambil snapshot dari \ 1zh_TW\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1版本檔案總管需要 2 個引數:
+- 快照根目錄的路徑。
+- 要瀏覽的檔案名稱。\ 1ja\1csize : \ 1サイズ:  \ 1ko\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s에 하나 이상의 종속 복제가 있어 삭제되지 않습니다. 이 스냅샷을 삭제하려면 먼저 이 스냅샷에서 복제된 모든 데이터 집합과 스냅샷을 삭제하십시오.\ 1pt_BR\1ccompare\ 1comparar\ 1cs\1cof file system capacity\ 1kapacity souborového systému\ 1ca\1cCreation Time\ 1Temps de creació\ 1pl\1cError occured while creating the snapshot\ 1Wystąpił błąd podczas tworzenia migawki\ 1zh_CN\1cSome snapshots could not be deleted\ 1无法删除某些快照\ 1hu\1cReduce backups when storage space usage exceeds:\ 1Csökkentse a mentések számát ha a tároló helyhasználata \ 1ca\1cInvalid characters in snapshot name\ 1Caràcters no vàlids al nom de la instantània\ 1fr\1cExit when done. \ 1Quitter une fois l'opération terminée.  \ 1nl\1cAdvanced Options\ 1Geavanceerde opties\ 1ar\1cTime Slider Manager\ 1إدارة شريط تمرير الوقت \ 1fr\1cMount Point\ 1Point de montage\ 1fr\1cError occured while creating the snapshot\ 1Une erreur s'est produite lors de la création de l'instantané\ 1fr\1cSnapshot manager service error\ 1Erreur du service de gestionnaire d'instantanés\ 1cs\1cConfiguring Time Slider...\ 1Konfiguruji Time Slider...\ 1ko\1cD_eselect All\ 1모두 선택 해제(_E)\ 1cs\1cUrgent: '%s' is almost full!\ 1Naléhavé: '%s' je skoro plný!\ 1de\1cEmergency: '%s' is full!\ 1Notfall: '%s' ist voll!\ 1ja\1cExit when done. \ 1完了したら終了します。 \ 1es\1c%d snapshots will be deleted.\ 1Se eliminarán %d instantáneas.\ 1ja\1cError occured while creating the snapshot\ 1スナップショットの作成中にエラーが発生しました\ 1pt_BR\1c%s has one or more dependent clones and will not be deleted. To delete this snapshot, first delete all datasets and snapshots cloned from this snapshot.\ 1%s tem um ou mais clones dependentes e não será excluído. Para excluir este instantâneo, exclua primeiro todos os conjuntos de dados e instantâneos clonados deste instantâneo.\ 1zh_CN\1cMonthly\ 1每月\ 1id\1cEmergency: '%s' is full!\ 1Darurat: '%s' penuh!\ 1nl\1c1/4 Hourly\ 1Ieder kwartier\ 1id\1cScanning snapshots...\ 1Memindai snapshots...\ 1de\1cVersion explorer requires 2 arguments :
+- The path of the root snapshot directory.
+- The filename to explore.\ 1Versions-Explorer erfordert 2 Argumente:
+-  Pfad des Schnappschuss-Stammverzeichnisses.
+-  Dateiname, nach dem gesucht werden soll.\ 1zh_CN\1cAll\ 1全部\ 1zh_HK\1cSelect\ 1選取\ 1hu\1c<b>Summary</b>\ 1<b>Összesítés</b>\ 1ca\1cgtk-close\ 1tancar-gtk\ 1es\1cAll\ 1Todos\ 1cs\1cOpen the current version of the file\ 1Otevřete soubor současné verze\ 1ca\1ccompare\ 1comparar\ 1zh_TW\1cConfigure the system to take automatic snapshots of your data\ 1將系統配置為自動對資料執行快照\ 1fr\1cCreation Time\ 1Période de création\ 1zh_HK\1cSnapshot can not be deleted\ 1無法刪除快照\ 1ko\1cOpen the current version of the file\ 1파일의 현재 버전을 엽니다.\ 1es\1cTime Slider\ 1Deslizador de tiempo\ 1zh_HK\1cSnapshot manager service dependency error\ 1快照管理員服務相依性錯誤\ 1zh_CN\1cThe snapshot manager service does not appear to be installed on this system.
+
+See the svcs(1) man page for more information.\ 1该快照管理器服务似乎没有安装在此系统上。
+
+有关更多信息,请参见 svcs(1) 手册页。\ 1nl\1cAll\ 1Alle\ 1ca\1cTime Slider\ 1Time Slider\ 1id\1csize : \ 1ukuran : \ 1es\1cMount Point\ 1Punto de montaje\ 1pt_BR\1cScanning snapshots...\ 1Explorando instantâneos...\ 1hu\1cSnapshot can not be deleted\ 1Nem törölhető pillanatkép\ 1ja\1cHourly\ 1毎時\ 1ca\1cSnapshot manager service dependency error\ 1Error de dependència del servei gestor de instantànies\ 1zh_HK\1cName:\ 1名稱:\ 1fr\1cSnapshot created successfully\ 1L'instantané a été créé\ 1ca\1cSome snapshots could not be deleted\ 1No s'han pogut eliminar algunes instantànies\ 1pl\1c<b>Enable Time Slider</b>\ 1<b>Włącz Time Slider</b>\ 1es\1cof file system capacity\ 1de capacidad de sistema de archivos\ 1ja\1cMonthly\ 1毎月\ 1cs\1c1 snapshot will be deleted.\ 11 snímek bude smazán\ 1zh_CN\1c%d snapshots will be deleted.\ 1%d 个快照将被删除。\ 1pl\1cFor advanced users\ 1Dla zaawansowanych użytkowników\ 1zh_TW\1cError occured while creating the snapshot\ 1建立快照時發生錯誤\ 1zh_CN\1cReduce backups when storage space usage exceeds:\ 1当存储空间使用率超过以下值时减少备份:\ 1ar\1c19/01/09\ 119/01/09\ 1de\1cInvalid arguments count.\ 1Ungültige Argumente.\ 1cs\1cFile System:\ 1Souborový systém:\ 1it\1cSnapshot Now requires administrative privileges to run. You have not been assigned the necessaryadministrative priviliges.
+
+Consult your system administrator \ 1Per l’esecuzione del comando Crea istantanea sono necessari privilegi amministrativi. Non si dispone dei privilegi amministrativi necessari.
+
+Rivolgersi all'amministratore di sistema. \ 1nl\1cThe file system: '%s', exceeded %s%% of its total capacity\ 1The file system: '%s', exceeded %s%% of its total capacity\ 1hu\1c_Delete Snapshots...\ 1_Pillanatkép törlése...\ 1pt_BR\1cDeleting Snapshots\ 1Excluindo instantâneos\ 1ko\1cInvalid arguments count.\ 1잘못된 인수 카운트입니다.\ 1zh_TW\1cSuccess\ 1成功\ 1nl\1cExit when done. \ 1Sluit af als je klaar bent. \ 1cs\1cCreation Time\ 1Čas vytvoření\ 1zh_HK\1cfilename\ 1檔案名稱\ 1zh_HK\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1時間調整器會透過擷取定時的 ZFS 快照,定期備份資料\ 1nl\1cWarning: '%s' is getting full\ 1Waarschuwing: '%s' wordt voller en voller\ 1zh_TW\1cExit when done. \ 1完成後結束。 \ 1es\1cExit when done. \ 1Salir al terminar. \ 1zh_CN\1cWarning: '%s' is getting full\ 1警告:'%s' 即将被占满\ 1nl\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Tijd glijder maakt reservekopie&#235;n van gegevens door het nemen van een regelmatige ZFS momentopnamen\ 1ja\1cWarning: '%s' is getting full\ 1警告: '%s' がいっぱいになりつつあります\ 1ko\1cError occured while creating the snapshot\ 1스냅샷 생성 중 오류가 발생했습니다.\ 1zh_TW\1cname :\ 1名稱:\ 1zh_HK\1cDaily\ 1每天\ 1hu\1cHourly\ 1Óránkénti\ 1id\1c19/01/09\ 119/01/09\ 1zh_HK\1cSnapshot Name\ 1快照名稱\ 1id\1cHourly\ 1Tiap Jam\ 1ar\1cFile System:\ 1نظام الملفات : \ 1pt_BR\1cSelect ZFS snapshots to delete from the list below.\ 1Selecione  na lista abaixo os instantâneos do ZFS que serão excluídos.\ 1ar\1cWarning: '%s' is getting full\ 1تحذير : '%s' الحصول على الكامل \ 1ja\1c<b>File Systems To Back Up</b>\ 1<b>バックアップするファイルシステム</b>\ 1ca\1cDetails...\ 1Detalls...\ 1it\1c1 snapshot will be deleted.\ 11 istantanea verrà eliminata.\ 1it\1cgtk-close\ 1gtk-close\ 1it\1c19/01/09\ 119/01/09\ 1zh_CN\1cTime Slider\ 1时间滑块\ 1fr\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1Le curseur temporel sauvegarde les données régulièrement en prenant des instantanés ZFS différés\ 1es\1ccompare\ 1comparar\ 1fr\1cError\ 1Erreur\ 1nl\1csize : \ 1grootte : \ 1zh_CN\1c<b>Enable Time Slider</b>\ 1<b>启用时间滑块</b>\ 1es\1cSnapshot manager service dependency error\ 1Error de dependencia del servicio de administrador de instantáneas\ 1pt_BR\1cTime Slider Manager\ 1Gerenciador da barra deslizante de tempo\ 1nl\1cFile System Name\ 1Bestand systeem naam\ 1de\1cInvalid characters in snapshot name\ 1Schnappschussname enthält ungültige Zeichen\ 1zh_CN\1c<b>File Systems To Back Up</b>\ 1<b>要备份的文件系统</b>\ 1ca\1cSome snapshots could not be read\ 1No s'han pogut llegir algunes instantànies\ 1pl\1cConfiguring Time Slider...\ 1Configuring Time Slider...\ 1ar\1cMount Point\ 1نقطة التحميل \ 1de\1cSnapshot manager service dependency error\ 1Abhängigkeitsfehler im Zusammenhang mit dem Schnappschussverwaltungsdienst\ 1ca\1cExit when done. \ 1Sortir quant estigui fet. \ 1id\1cHint\ 1Petunjuk\ 1de\1cConfigure the system to take automatic snapshots of your data\ 1System für automatische Snapshots Ihrer Daten konfigurieren\ 1zh_HK\1cInvalid characters in snapshot name\ 1快照名稱中有無效字元\ 1ko\1cWeekly\ 1매주\ 1es\1cReduce backups when storage space usage exceeds:\ 1Destruir las copias de seguridad cuando se sobrepase el uso del espacio de almacenamiento:\ 1ko\1cSnapshot Name\ 1스냅샷 이름\ 1es\1cFile System:\ 1Sistema de archivos:\ 1ar\1cEmergency: '%s' is full!\ 1الخطر : '%s' ممتلئ!\ 1ja\1c1 snapshot will be deleted.\ 11 つのスナップショットが削除されます。\ 1nl\1cSnapshot Name\ 1Momentopname naam\ 1es\1cDelete Snapshots\ 1Eliminar instantáneas\ 1nl\1cWeekly\ 1Wekelijks\ 1zh_CN\1cTime Slider Manager\ 1时间滑块管理器\ 1zh_TW\1cMount Point\ 1掛載點\ 1es\1clast modified : \ 1última modificación: \ 1zh_CN\1c<b>Older Versions</b>\ 1<b>早期版本</b>\ 1pt_BR\1cSuccess\ 1Êxito\ 1hu\1cThe file system: '%s', is over %s%% full.\ 1A fájlrendszer: '%s' több mint %s%%-kal megtelve.\ 1cs\1cThe file system: '%s', exceeded %s%% of its total capacity\ 1Souborový systém:  '%s', překročil %s%% své celkové kapacity\ 1de\1cD_eselect All\ 1A_uswahl aufheben\ 1it\1c<b>Enable Time Slider</b>\ 1<b>Abilita Time Slider </b>\ 1cs\1cwith the name :\ 1s názvem:\ 1fr\1cWeekly\ 1Hebdomadaire\ 1pl\1cTime Slider\ 1Time Slider\ 1ko\1cMount Point\ 1마운트 지점\ 1de\1c<b>Older Versions</b>\ 1<b>Ältere Versionen</b>\ 1pt_BR\1cwith the name :\ 1com o nome:\ 1zh_TW\1cTime Slider backs up data regularly by taking timed ZFS Snapshots\ 1時間調整器會透過擷取定時的 ZFS 快照,定期備份資料\ 1pl\1cEmergency: '%s' is almost full!\ 1Uwaga: '%s' jest prawie zapełniony\ 1nl\1cFile System:\ 1Bestand systeem:\ 1es\1cSnapshot Now requires 2 arguments :
+- The path of the directory to be snapshotted.
+- The zfs filesystem corresponding to this directory.\ 1Tomar instantánea ahora necesita 2 argumentos:
+- La ruta del directorio del que se va a tomar la instantánea.
+- El sistema de archivos zfs correspondiente a este directorio.\ 1fr\1cEmergency: '%s' is full!\ 1Urgence : %s est plein !\ 1es\1cName:\ 1Nombre:\ 1zh_TW\1cScanning snapshots...\ 1正在掃描快照...\ 1id\1cRecommended for most users\ 1Direkomendasikan untuk sebagian besar pengguna\ 1ar\1cThe file system: '%s', is over %s%% full.\ 1نظام الملفات: '%s', كامل  %s%% ممتلئ.\ 1zh_CN\1cDelete Snapshots\ 1删除快照\ 1de\1c<b>Enable Time Slider</b>\ 1<b>Zeit-Schieberegler aktivieren</b>\ 1id\1cThe file system: '%s', exceeded %s%% of its total capacity\ 1File Sistem: '%s', melebihi %s%% dari kapasitas total.\ 1ja\1cname :\ 1名前: \ 1hu\1cPress Delete to continue.\ 1Nyomjon Delete-t a folytatáshoz.
\ No newline at end of file
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644 (file)
index 0000000..d61d752
--- /dev/null
@@ -0,0 +1,27 @@
+2010-01-21  Harry Fu  <harry.fu@sun.com
+
+       * LINGUAS: new languages are added - ca
+       * *.po: Updated with the latest translations.
+       
+2009-05-12  Harry Fu  <harry.fu@sun.com>
+
+       * LINGUAS: new languages are added - ar,id,nl
+       * *.po: Updated cs/hu/pl with the latest translations.
+
+2009-02-19  Takao Fujiwara  <takao.fujiwara@sun.com>
+
+       * POTFILES.in: Added time-slider-version.glade and fileversion.py
+       * *.po: Updated with the latest strings.
+
+2008-11-04  Takao Fujiwara  <takao.fujiwara@sun.com>
+
+       * *.po: Updated with the latest strings.
+
+2008-10-20  Takao Fujiwara  <takao.fujiwara@sun.com>
+
+       * LINGUAS: Added to compile .mo files.
+       * Makefile: Added.
+       * POTFILES.in: Added for intltool.
+       * cs.po de.po es.po fr.po hu.po it.po ja.po ko.po pl.po pt_BR.po ru.po
+         sv.po zh_CN.po zh_HK.po zh_TW.po: Added .po files.
+
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644 (file)
index 0000000..fd836de
--- /dev/null
@@ -0,0 +1,21 @@
+# please keep this list sorted alphabetically
+#
+ar
+ca
+cs
+de
+es
+fr
+hu
+id
+it
+ja
+ko
+nl
+pl
+pt_BR
+ru
+sv
+zh_CN
+zh_HK
+zh_TW
diff --git a/po/Makefile b/po/Makefile
new file mode 100644 (file)
index 0000000..5e315d0
--- /dev/null
@@ -0,0 +1,93 @@
+srcdir = .
+top_srcdir = ..
+top_builddir = ..
+
+subdir = po
+prefix = /usr
+DATADIRNAME = share
+itlocaledir = $(prefix)/$(DATADIRNAME)/locale
+LOCALE_OWNER = root
+LOCALE_GROUP = root
+#mkdir_p = install -d -m 755 -o $(LOCALE_OWNER) -g $(LOCALE_GROUP)
+mkdir_p = install -d -m 755
+
+PACKAGE = $(firstword $(patsubst PACKAGE=%, %, $(shell grep "^PACKAGE=" $(top_srcdir)/Makefile)))
+VERSION = $(firstword $(patsubst VERSION=%, %, $(shell grep "^VERSION=" $(top_srcdir)/Makefile)))
+GETTEXT_PACKAGE = $(PACKAGE)
+
+INSTALL = install -c
+INSTALL_DATA = ${INSTALL} -m 644
+
+GMSGFMT = msgfmt
+MSGFMT = msgfmt
+
+ALL_LINGUAS = 
+
+PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; fi)
+
+USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep ^$$lang$$ $(srcdir)/LINGUAS`" -o -n "`echo $$ALINGUAS|grep ' ?$$lang ?'`"; then printf "$$lang "; fi; done; fi)
+
+USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done)
+
+POFILES=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done)
+
+DISTFILES = Makefile POTFILES.in $(POFILES)
+EXTRA_DISTFILES = LINGUAS
+
+CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done)
+
+.SUFFIXES:
+.SUFFIXES: .po .gmo
+
+.po.gmo:
+       file=`echo $* | sed 's,.*/,,'`.gmo \
+         && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+all: all-yes
+
+all-yes: $(CATALOGS)
+all-no:
+
+install: install-data
+install-data: install-data-yes
+install-data-no: all
+install-data-yes: all
+       $(mkdir_p) $(DESTDIR)$(itlocaledir)
+       linguas="$(USE_LINGUAS)"; \
+       for lang in $$linguas; do \
+         dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \
+         $(mkdir_p) $$dir; \
+         if test -r $$lang.gmo; then \
+           $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+           echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \
+         else \
+           $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+           echo "installing $(srcdir)/$$lang.gmo as" \
+                "$$dir/$(GETTEXT_PACKAGE).mo"; \
+         fi; \
+       done
+
+uninstall:
+       linguas="$(USE_LINGUAS)"; \
+       for lang in $$linguas; do \
+         rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \
+       done
+
+clean:
+       rm -f *.gmo
+       rm -f .intltool-merge-cache
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: $(DISTFILES)
+       dists="$(DISTFILES)"; \
+       extra_dists="$(EXTRA_DISTFILES)"; \
+       for file in $$extra_dists; do \
+         test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \
+       done; \
+       for file in $$dists; do \
+         test -f $$file || file="$(srcdir)/$$file"; \
+         ln $$file $(distdir) 2> /dev/null \
+           || cp -p $$file $(distdir); \
+       done
+
+.NOEXPORT:
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644 (file)
index 0000000..8252e1e
--- /dev/null
@@ -0,0 +1,12 @@
+# List of source files containing translatable strings.
+# Please keep this file sorted alphabetically.
+data/time-slider.desktop.in
+usr/share/time-slider/glade/time-slider-delete.glade
+usr/share/time-slider/glade/time-slider-setup.glade
+usr/share/time-slider/glade/time-slider-snapshot.glade
+usr/share/time-slider/glade/time-slider-version.glade
+usr/share/time-slider/lib/time_slider/applet.py
+usr/share/time-slider/lib/time_slider/deletegui.py
+usr/share/time-slider/lib/time_slider/fileversion.py
+usr/share/time-slider/lib/time_slider/setupgui.py
+usr/share/time-slider/lib/time_slider/snapnowui.py
diff --git a/po/ar.gmo b/po/ar.gmo
new file mode 100644 (file)
index 0000000..819fdc3
Binary files /dev/null and b/po/ar.gmo differ
diff --git a/po/ar.po b/po/ar.po
new file mode 100644 (file)
index 0000000..f3b6635
--- /dev/null
+++ b/po/ar.po
@@ -0,0 +1,533 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+       "Project-Id-Version: time-slider HEAD\n"
+       "Report-Msgid-Bugs-To: \n"
+       "POT-Creation-Date: 2009-12-07 22:37+0900\n"
+       "PO-Revision-Date: 2010-01-20 20:31+0100\n"
+       "Last-Translator: Hosam Al Ali\n"
+       "Language-Team: Arabic language team <i18n-discuss@opensolaris.org>\n"
+       "MIME-Version: 1.0\n"
+       "Content-Type: text/plain; charset=UTF-8\n"
+       "Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "تاكيد النظام على أخذ صورة عن النظام عن البيانات "
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "شريط تمرير الوقت "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d الصورة سوف تمحى "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b> ملخص </b>"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "D_eselect All"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "حذف صور النظام  "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "حذف صور النظام "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "حذف صور النظام..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "الخروج عن الإنتهاء "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "نظام الملفات : "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "إسم : "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "إضغط على حذف للإستمرار "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "فحص صور النظام "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "إختر ZFS صور النظام لحذف من اسفل القائمة "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>تفعيل شريط تمرير الوقت</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b> ملف النظام للنسخة الإحتياطية </b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "خيارات إضافية "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "C_ustom:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr "إعدادات شريط التوقيت..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "من أجل المستخدمين المتقدمين "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "المطلوب من كل المستخدمين "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "تخفيض النسخة الإحتياطية عند تجاوز المساحة النخزينية "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "إدارة شريط تمرير الوقت "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "شريط تمرير الوقت يقوم بنسخ إحتياطي للبيانات بشكل منتظم "
+       "بأخذ صورة للنظام "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_الكل "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_حذف صور النظام ...."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "قدرة نظام ملفات النظام "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "خذ نسخة من صورة النظام الأن "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "خذ نسخة من صورة النظام "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "بإسم :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>الإصدار الحالي</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>الإصدارات السابقة</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "إضغط مرتين لفتح الملف "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "إفتح نفس إصدار الملف "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "الفحص للإصدارات الأقدم "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "متصفح ملف إصدار شريط تمرير الوقت "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "مقارنة "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "إسم الملف "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-إغلاق "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "أخر تعديل : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "إسم : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "الحجم : "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr "شريط التوقيت : تحذير بإنخفاض المساحة"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "الخطر : '%s' ممتلئ!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr "نظام الملفات: '%s', كامل  %s%% ممتلئ."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+       "نظام الملفات : `%s`  وكامل %s%%. ممتلى \n"
+       "والتدبير الإحترازي, شريط تمرير الوقت سوف يحذف كامل النسخ الإحتياطي . \n"
+       "ولإصلاح هذه المشكلة , إحذف أي ملفات غير ضرورية '%s', أو أضف قرص أخر "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "الخظر : '%s'  على الأغلب كامل "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr "نظام الملفات: '%s', تجاوز %s%% فوق كل السعة الكلية "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+       "نظام الملفات: '%s', تجاوز %s%% من اجمالي قدرتها. باعتبارها emerency"
+       "قياس ، شريط الوقت سوف يلغي معظم ا كل ملفات النسخة الإحتياطي لمنع ملئ القرص . لمنع حدوث ذلك مرة أخرى, يجب عليك , delete any, حذف كل الملفات الغير مفيدة ضمنه '%s', أو أضف قرص جديد(إنظر ZFS دليل)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "عاجل : '%s' على الإغلب ممتلئ "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "تحذير : '%s' الحصول على الكامل "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+       "'%s' تجاوزت %s%% كامل المساحة المتاحة. لحل المشكلة, شريط الوقت يحذف كل ويزيل أخر ملفات النسخ الإحتياطي, وسوف يستمر بعملية الحذف الإزالة من أجل التقليص .\n"
+       "لمنع حدوث ذلك مرة أخرى , يجب عليك حذف الملفات الغير مفيدة ضمنه'%s', "
+       "أو اضف قرص جديد (إنظر ZFS دليل).\n"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr "تفاصيل..."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "إرث "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "نقطة التحميل "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "إسم ملف النظام "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "إسم صورة النظام "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "إنشاء الوقت "
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "الكل "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "شهريا "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "إسبوعيا "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "يومي "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "ساعي "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "1/4 ساعي "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "صور النظام لا يمكن حذفها "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+       "%s هناك وأحد او أكثر من نسخ معتمدة على بعضها لا يمكن خذفها . "
+       "لحذف صورة النظام , أولا أحذف كل datasetes ونسخ صور النظام من صور النظام "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 صورة نظام سوف تحذف "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "بعض صور النظام لايمكن أن تقرأ "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "بعض صور النظام لايمكن أن تحذف "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "الإمتيازات غير كافية "
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "حذف صورة النظام تطلب إمتيازات المدراء لتتم ."
+       "أنت لم تنقل أو تعرف على إمتيازات المدراء الضرورية . \n \n "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr "ملحوظة "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+       "تنصيب إضافات meld الحزم سوف تحسن من عملية المقارنة المرئية "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "فشل بعد الحجج "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+       "إصدار المستكشف يتطلب طلبين :\n"
+       "- مسار مجلد صورة نظام حساب root"
+       "- إسم الملف للإستعراض  "
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "إختر "
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "خدمة إدارة صورة النظام  تعتمد خطأ "
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+       "خدمة إدارة صورة النظام تكون بحالة غير فعالة ويستحق الإعتمادية. اخطاء الإرتباطات التالية ممكن إيجادها:\n"
+       "\n"
+       "%s\n"
+       "\n"
+       "شغل الأمر التالي \"svcs -xv\" من خلال موجه الأوامر لمزيد من المعلومات حول أخطاء الإعتمادية."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "خطأ خدمة إدارة صورة النظام "
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "خدمة إدارة صورة النظام تواجه المشاكل ولذلك هي غير فعالة حتى تحل المشكلة .\n "
+       "\n "
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "خدمة إدارة صورة التظام لا تظهر على أنها منصبة ضمن النظام . \n "
+       "إنظر الى svcs(1) man page for more information."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "خدمة إدارة صورة النظام تحتاج الى صلاحيات المدير لكي تعمل , وأنت لم تعرف على أساس الإمتيازات الضرورية كمدير . \n "
+       "\n "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "خطأ برموز إسم صورة النظام "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "خطأ "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+       "الرموز المتاحة بإسم صورة النظام  :\n"
+       "[a-z][A-Z][0-9][-_.:\n"
+       "وكل الرموز الغير متاحة قد أزيلت \n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "الخطأ حدث عند إنشاء صورة النظام "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "صورة النظام قد أنشأت بنجاح "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "نجاح "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+       "الصورة ضمن نظام ملفات ZFS %(zfs_fs)s\n"
+       "مسماه %(valid_name)s\n"
+       "قد أنشأ .\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+       "صورة النظام تحتاج طلبين : \n"
+       "-      مسار المجلد الخاص بصور النظام .\n"
+       "-      نظام ملفات zfs متطابق مع مع المجلد "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "صورة النظام الأن تحتاج الى صلاحيات مدير للعمل , وأنت لم تعرف على أساس الإمتيازات الضرورية كمدير . \n \n"
+       "راجع مدير النظام "
diff --git a/po/ca.gmo b/po/ca.gmo
new file mode 100644 (file)
index 0000000..b6cef3e
Binary files /dev/null and b/po/ca.gmo differ
diff --git a/po/ca.po b/po/ca.po
new file mode 100644 (file)
index 0000000..e59fe8e
--- /dev/null
+++ b/po/ca.po
@@ -0,0 +1,535 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+       "Project-Id-Version: time-slider HEAD\n"
+       "Report-Msgid-Bugs-To: \n"
+       "POT-Creation-Date: 2009-12-07 22:37+0900\n"
+       "PO-Revision-Date: 2010-01-20 20:31+0100\n"
+       "Last-Translator: Robert Antoni Buj\n"
+       "Language-Team: Catalan language team <i18n-discuss@opensolaris.org>\n"
+       "MIME-Version: 1.0\n"
+       "Content-Type: text/plain; charset=UTF-8\n"
+       "Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "Configurar el sistema per a fer instantànies automàtiques de les vostres dades"
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d instantànies a ser eliminades."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Resum</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "De-_seleccionar-ho Tot"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Eliminar instantànies"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Eliminant Instantànies"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Eliminant Instantànies..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Sortir quant estigui fet. "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Sistema de Fitxers:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Nom:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Premeu a Eliminar per a continuar."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Escanejant instantànies...."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Seleccioneu les instantànies ZFS a eliminar del següent llistat."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Activar Time Slider</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Sistema de fitxers a fer Còpia de seguretat</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Opcions avançades"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "_Personalitzat:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr "Configurant Time Slider..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Per a usuaris avançats"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Recomanat per a la majoria d'usuaris"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Reduir les còpies de seguretat quan l'espai d'emmagatzemament excedeixi:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Gestor de Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "Time Slider fa còpies de seguretat regularment prenent Instantànies ZFS programades"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Tots"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Eliminar Instantànies..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "de la capacitat del sistema de fitxers"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Fer una instantània ara"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Fer una instantània de "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "amb el nom :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Dl"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Versió Actual</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Versions Anteriors</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Doble clic per a obrir un fitxer"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Obrir la versió actual del fitxer"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Escanejant per a versions antigues"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Explorador de Versions de Fitxer de Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "comparar"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "nomfitxer"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "tancar-gtk"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "última modificació : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "nom :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "mida : "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr "Time Slider: Advertència poc espai"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Emergència: '%s' està ple!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr "El sistema de fitxers: '%s', sobreexcedeix %s%%."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+       "El sistema de fitxers: '%s', està gairebé %s%% ple.\n"
+       "Com a mesura d'emergència, Time Slider ha destruït totes les vostres còpies de seguretat.\n"
+       "Per solucionar aquest problema, elimineu qualsevol fitxer innecessari de '%s', o afegiu espai al disc (vegeu la documentació de ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Emergència: '%s' gairebé està ple!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr "El sistema de fitxers: '%s', excedeix %s%% de la seva capacitat total"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+       "El sistema de fitxers: '%s', excedeix %s%% de la seva capacitat total. Com a mesura d'emergència, Time Slider ha moltes o totes les seves còpies de seguretat per a prevenir que el disc estigués ple. Per a prevenir que això no torni a passar, elimineu qualsevol fitxer innecessari '%s', o afegiu espai de disc (vegeu la documentació de ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Urgent: '%s' gairebé està ple!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+       "El sistema de fitxers: '%s', excedeix %s%% de la seva capacitat total. com a mesura correctora, Time Slider ha destruït algunes còpies de seguretat, i en destruirà més, eventualment totes, si la capacitat continua disminuint.\n"
+       "Per preveure que això no torni a passar, elimineu qualsevol fitxer innecessari de '%s', o afegiu espai al disc (vegeu la documentació de ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Avís: '%s' s'està emplenant"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+       "'%s' excedeix %s%% de la seva capacitat total. Per a corregir-ho, Time Slider ha algunes còpies de seguretat recents, i en continuarà destruint-ne més si la capacitat continua reduint-se.\n"
+       "Per a prevenir que això no torni a passar més, elimineu qualsevol fitxer innecessari en '%s', o afegiu espai de disc addicional (vegeu la documentació de ZFS).\n"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr "Detalls..."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Llegat"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Punt de Muntatge"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Nom Sistema de Fitxers"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Nom de la instantània"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Temps de creació"
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Tots"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Mensual"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Setmanal"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Diària"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Cada hora"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Cada 1/4 d'hora"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "La instantània no pot ser eliminada"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+       "%s té un o més clons que en depenen i no serà eliminat. Per eliminar aquesta"
+       "instantània, primer elimineu tots els datasets i instantànies clonades d'aquesta instantània."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 instantània serà eliminada."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "No s'han pogut llegir algunes instantànies"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "No s'han pogut eliminar algunes instantànies"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Privilegis insuficients"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "L'eliminació de instantànies requereix privilegis administratius per a funcionar. No teniu assignats els privilegis necessaris administratius.\n"
+       "\n"
+       "Consulteu al vostre administrador de sistema "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr "Pista"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+       "Instal·lant el paquet addicional meld enriquirà la comparació de fitxers de virtualització"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Nombre d'arguments incorrectes."
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+       "L'explorador de versions requereix 2 arguments :\n"
+       "- La ruta del directori arrel de la instantània.\n"
+       "- El nom del fitxer a explorar."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Seleccionar"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Error de dependència del servei gestor de instantànies"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+       "El servei gestor de instantànies s'ha posat fora de línia a causa del "
+       "problema de dependència. S'han trobat els següents problemes de dependència:\n"
+       "\n"
+       "%s\n"
+       "\n"
+       "Executeu \"svcs -xv\" des de la línia de comandes per a més informació quant a aquests problemes de dependència."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "S'ha produït un error al servei de gestió de instantànies"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "El servei gestor de instantànies ha trobat un problema i ha estat "
+       "deshabilitat mentre no es solucioni el problema.\n"
+       "\n"
+       "Vegeu la pàgina del manual svcs(1) per a més informació."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "El servei gestor de instantànies no sembla que estigui instal·lat en aquest"
+       "sistema.\n"
+       "\n"
+       "Vegeu la pàgina del manual svcs(1) per a més informació."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "El servei gestor de instantànies requereix privilegis d'administrador per a funcionar. No teniu assignats els privilegis necessaris administratius.\n"
+       "\n"
+       "Consulteu al vostre administrador de sistema "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Caràcters no vàlids al nom de la instantània"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Error"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+       "Els caràcters permesos pel nom de la instantània són :\n"
+       "[a-z][A-Z][0-9][-_.:\n"
+       "S'eliminaran tots els caràcters incorrectes\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "S'ha produït un error mentre s'estava creant la instantània"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Instantània correctament creada"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Realitzat"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+       "Una instantània del sistema de fitxers zfs %(zfs_fs)s\n"
+       "anomenada %(valid_name)s\n"
+       "ha estat creada.\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+       "Instantània Ara requereix 2 arguments :\n"
+       "- La ruta del directori per fer la instantània.\n"
+       "- El sistema de fitxers zfs corresponent al directori."
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "La instantània Ara requereix privilegis administratius per a funcionar. Sembla no teniu assignats els privilegis necessaris administratius.\n"
+       "\n"
+       "Consulteu al vostre administrador de sistema "
diff --git a/po/cs.gmo b/po/cs.gmo
new file mode 100644 (file)
index 0000000..3508940
Binary files /dev/null and b/po/cs.gmo differ
diff --git a/po/cs.po b/po/cs.po
new file mode 100644 (file)
index 0000000..2439cb3
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,541 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+       "Project-Id-Version: time-slider HEAD\n"
+       "Report-Msgid-Bugs-To: \n"
+       "POT-Creation-Date: 2009-12-07 22:37+0900\n"
+       "PO-Revision-Date: 2010-01-20 20:31+0100\n"
+       "Last-Translator: Kristyna Kitzbergerova\n"
+       "Language-Team: Czech language team <i18n-discuss@opensolaris.org>\n"
+       "MIME-Version: 1.0\n"
+       "Content-Type: text/plain; charset=UTF-8\n"
+       "Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "Nakonfigurujte si systém tak, aby vytvářel automatické snímky Vašich dat"
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d snímky budou smazány."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Shrnutí</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "V_yřadit vše"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Smazat snímky"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Mažu snímky"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Mažu snímky..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Ukončit po dokončení. "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Souborový systém:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Jméno:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Stiskněte Smazat pro pokračování."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Skenuji snímky..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Vyberte ZFS snímek ze seznamu, který má být smazán."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Povolit Time Slider</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Záloha souborového systému</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Rozšířené možnosti"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "V_lastní"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr "Konfiguruji Time Slider..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Pro pokročilé uživatele"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Doporučeno pro většinu uživatelů"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Zmenšit zálohy pokud úložný prostor překročí:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Správce pro Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "Time Slider zálohuje pravidelně data pomocí časových ZFS smínků"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Vše"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Smazat snímek..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "kapacity souborového systému"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Pořídit snímek nyní"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Pořídit snímek "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "s názvem:"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "Pondělí 10"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Současná verze</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Starší verze</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Dvojitým kliknutím na soubor tento soubor otevřete"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Otevřete soubor současné verze"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Skenuji pro starší verze"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Time Slider - Průzkumník verzí "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "porovnat"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "jméno souboru"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "Naposledy změněn : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "jméno :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "velikost : "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr "Time Slider: Varování - málo místa"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Stav nouze: '%s' je plný!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr "Souborový systém: %s', je z %s%% plný."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+       "Souborový systém: '%s', z %s%% je přeplněn.\n"
+       "Time Slider smazal všechny své zálohy jako nouzové opatření.\n"
+       "Chcete-li vyřešit tento problém, smažte nepotřebné soubory na '%s' nebo "
+       "přidejte více místa (viz ZFS dokumentace)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Stav nouze: '%s' je skoro plný!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr "Souborový systém:  '%s', překročil %s%% své celkové kapacity"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+       "Souborový systém '%s', překročil %s%% ze své celkové kapacity. Jako "
+       "nouzové opatření Time Slider odstranil většinu svých záloh, aby předešel"
+       " zaplnění disku. Smažte nepotřebné soubory na '%s' nebo přidejte místo, "
+       "abyste se tomuto problému příště vyhnuli (viz ZFS dokumentace)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Naléhavé: '%s' je skoro plný!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+       "Souborový systém '%s', překročil %s%% ze své celkové kapacity. "
+       "Jako nouzové opatření, Time Slider odstranil některé ze svých záloh a odstraní více, eventuálně vše, pokud se kapacita bude nadále snižovat.\n"
+       "Abyste tomuto zabránili do budoucna, smažte nepotřebné soubory na '%s', "
+       "nebo přidejte další diskový prostor (více v dokumentaci o ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Upozornění: '% s' se zaplňuje"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+       "'%s', překročil %s%% ze své celkové kapacity. Time Slider odstranil některé své zálohy a odstraní více, pokud se kapacita bude nadále snižovat.\n"
+       "Abyste tomuto zabránili do budoucna, smažte nepotřebné soubory na '%s', nebo přidejte další diskový prostor (více v dokumentaci o ZFS).\n"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr "Podrobnosti..."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Odkaz"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Místo připojení"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Jméno souborového systému"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Jméno snímku"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Čas vytvoření"
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Vše"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Měsíčně"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Týdně"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Denně"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Každou hodinu"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Každou 1/4 hodinu"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Snímek nemůže být smazán"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+       "%s má jednu nebo více závislých klonů a nemůže být smazán."
+       " Abyste mohli odstranit tento snímek, musíte nejdříve smazat všechny "
+       "jeho datové sady a klony."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 snímek bude smazán"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Některé snímky nelze přečíst"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Některé snímky nemohou být smazány"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Nedostatečná práva"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Smazání snímku požaduje administrátorská práva. Vy tato práva nemáte.\n"
+       "Kontaktujte Vašeho správce systému "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr "Nápověda"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+       "Instalování volitelných balíčků zvýrazní vizualizaci srovnání souborů"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Neplatný počet argumentů."
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+       "Průzkumník verzí požaduje 2 argumenty: \n"
+       "- Cestu k adresáři se snímky kořenového adresáře"
+       "- Jméno souboru, které se má prozkoumat"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Vybrat"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Chyba v závislostech ve službě Správce snímků"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+       "Služba Správce snímků byla umístěna offline kvůli problémům v závislostech. "
+       "Následující chyby v závislostech byly nalezeny: \n"
+       "\n"
+       "%s\n"
+       "\n"
+       "Z příkazové řádky spusťte \"svcs -xv\" pro více informací o těchto potížích."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Chyba ve službě Správce snímků"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "Služba Správce snímku zaznamenala problém a byla proto vypnuta, "
+       "dokud problém nebude vyřešen. \n"
+       "\n"
+       "Viz manuálové stránky svcs(1) pro více informací."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "Služba Správce snímků se nezdá, že by byla nainstalována na tomto "
+       "systému. \n"
+       "\n"
+       "Viz manuálové stránky svcs(1) pro více informací."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Služba Správce snímků požaduje administrátorská práva. "
+       "Vy tato práva nemáte.\n"
+       "\n"
+       "Kontaktujte Vašeho správce systému "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Neplatný znak v názvu snímku"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Chyba"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+       "Povolené znaky pro název snímku jsou následující: \n"
+       "[a-z][A-Z][0-9][-_.:\n"
+       "Všechny neplatné znaky budou odstraněny\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Vyskytla se chyba při vytváření snímku"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Snímek byl vytvořen úspěšně"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Úspěch"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+       "Byl vytvořen snímek ZFS souborového systému%(zfs_fs)s\n"
+       "s názvem %(valid_name)s\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+       "Snímek nyní požaduje 2 argumenty: \n"
+       "- Cestu k adresáři, kde má být snímek vytvořen"
+       "- zfs souborový systém odpovídající tomuto adresáři"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Snímek nyní vyžaduje administrátorská práva. Vy tato práva nemáte. \n"
+       "\n"
+       "Kontaktujte Vašeho správce systému "
diff --git a/po/de.gmo b/po/de.gmo
new file mode 100644 (file)
index 0000000..4b22606
Binary files /dev/null and b/po/de.gmo differ
diff --git a/po/de.po b/po/de.po
new file mode 100644 (file)
index 0000000..7f8da66
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,868 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2009-02-16 18:55+0100\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "System für automatische Snapshots Ihrer Daten konfigurieren"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Zeit-Schieberegler"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d Schnappschüsse werden gelöscht."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Zusammenfassung</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "A_uswahl aufheben"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Schnappschüsse löschen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Löschen von Schnappschüssen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Schnappschüsse werden gelöscht..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Beenden Sie die Anwendung, wenn Sie fertig sind.  "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Dateisystem:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Name:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Klicken Sie auf „Löschen“, um fortzufahren."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Suche nach Schnappschüssen wird ausgeführt..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr ""
+"Wählen Sie aus der nachstehenden Liste die zu löschenden ZFS-Schnappschüsse "
+"aus."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Zeit-Schieberegler aktivieren</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Dateisystem zur Sicherung</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Erweiterte Optionen"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "B_enutzerdefiniert:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Für erfahrene Benutzer"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Empfohlen für die meisten Benutzer"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr ""
+"Sicherungen reduzieren, wenn Speicherplatznutzung Folgendes überschreitet:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Zeit-Schieberegler-Manager"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+"Der Zeit-Schieberegler sichert regelmäßig Daten durch Erfassung von zeitlich "
+"festgelegten ZFS-Schnappschüssen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Alle"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Schnappschüsse löschen..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "der Dateisystemkapazität"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Jetzt einen Schnappschuss nehmen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Einen Schnappschuss nehmen von  "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "mit dem Namen:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10  Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Aktuelle Version</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Ältere Versionen</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Auf die Datei doppelklicken, um sie zu öffnen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Die aktuelle Version der Datei öffnen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Nach älteren Versionen suchen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Time  Slider  File  Version  Explorer"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "vergleichen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "Dateiname"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "Letzte Änderung:  "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "Name:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "Größe:  "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "Zeit-Schieberegler-Manager"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Notfall: '%s' ist voll!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"Das Dateisystem: '%s', ist über %s%% voll.\n"
+"Der Zeit-Schieberegler hat im Zuge einer Notfallmaßnahme alle "
+"Sicherungsdateien gelöscht.\n"
+"Um dieses Problem zu beheben, löschen Sie alle nicht benötigten Dateien auf "
+"'%s', oder fügen Sie Speicherplatz hinzu (siehe ZFS-Dokumentation)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Notfall: '%s' ist fast voll!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"Das Dateisystem: '%s', %s%% der Gesamtkapazität überschritten. Der Zeit-"
+"Schieberegler hat im Zuge einer Notfallmaßnahme die meisten oder alle "
+"Sicherungsdateien gelöscht, um zu verhindern, dass der Datenträger voll "
+"wird. Um zu verhindern, dass dieses Problem erneut auftritt, löschen Sie "
+"alle nicht benötigten Dateien auf '%s', oder fügen Sie Speicherplatz hinzu "
+"(siehe ZFS-Dokumentation).\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Dringend: '%s' ist fast voll!"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"Das Dateisystem: '%s', %s%% der Gesamtkapazität überschritten. Der Zeit-"
+"Schieberegler hat im Zuge einer Abhilfemaßnahme einige Sicherungsdateien "
+"gelöscht und wird weitere und letztlich alle Sicherungsdateien löschen, wenn "
+"die Kapazität weiter abnimmt.\n"
+"Um zu verhindern, dass dieses Problem erneut auftritt, löschen Sie alle "
+"nicht benötigten Dateien auf '%s', oder fügen Sie Speicherplatz hinzu (siehe "
+"ZFS-Dokumentation)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Warnung: '%s' wird voll"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"'%s' %s%% der Gesamtkapazität überschritten. Um dieses Problem zu beheben, "
+"hat der Zeit-Schieberegler einige der zuletzt erstellten Sicherungsdateien "
+"gelöscht und wird weitere Sicherungsdateien löschen, wenn die Kapazität "
+"weiter abnimmt.\n"
+"Um zu verhindern, dass dieses Problem erneut auftritt, löschen Sie alle "
+"nicht benötigten Dateien auf '%s', oder fügen Sie Speicherplatz hinzu (siehe "
+"ZFS-Dokumentation)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Veraltet"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Einhängepunkt"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Dateisystemname"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Schnappschussname"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Erstellungszeit"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Alle"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Monatlich"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Wöchentlich"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Täglich"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Stündlich"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Viertelstündlich"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Schnappschuss kann nicht gelöscht werden"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s hat einen oder mehrere abhängige Klone und wird nicht gelöscht.  Um "
+"diesen Schnappschuss zu löschen, löschen Sie zunächst alle Datensätze und "
+"Schnappschüsse, die aus diesem Schnappschuss geklont wurden."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 Schnappschuss wird gelöscht."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Einige Schnappschüsse konnten nicht gelesen werden"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Einige Schnappschüsse konnten nicht gelöscht werden"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Nicht ausreichend Zugriffsrechte"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Die Löschung von Schnappschüssen erfordert Administratorrechte.  Ihnen "
+"wurden nicht die nötigen Administratorrechte zugewiesen.\n"
+"\n"
+"Wenden Sie sich an Ihren Systemadministrator.  "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Ungültige Argumente."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"Versions-Explorer erfordert 2 Argumente:\n"
+"-  Pfad des Schnappschuss-Stammverzeichnisses.\n"
+"-  Dateiname, nach dem gesucht werden soll."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Auswählen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr ""
+"Abhängigkeitsfehler im Zusammenhang mit dem Schnappschussverwaltungsdienst"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"Der Schnappschussverwaltungsdienst wurde wegen eines Abhängigkeitsproblems "
+"offline geschaltet.  Folgende Abhängigkeitsprobleme wurden festgestellt:\n"
+"\n"
+"%s\n"
+"\n"
+"Führen Sie über eine Eingabeaufforderung den Befehl \"svcs  -xv\" aus, um "
+"weitere Informationen zu diesen Abhängigkeitsproblemen zu erhalten."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Schnappschussverwaltungsdienst-Fehler"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"Der Schnappschussverwaltungsdienst ist von einem Problem betroffen und wurde "
+"bis zur Behebung des Problems deaktiviert.\n"
+"\n"
+"Weitere Informationen finden Sie in der Online-Dokumentation, svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"Der Schnappschussverwaltungsdienst ist offenbar nicht auf diesem System "
+"installiert.\n"
+"\n"
+"Weitere Informationen finden Sie in der Online-Dokumentation, svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Für die Ausführung des Schnappschussverwaltungsdienstes sind "
+"Administratorrechte erforderlich. Ihnen wurden nicht die nötigen "
+"Administratorrechte zugewiesen.\n"
+"\n"
+"Wenden Sie sich an den Systemadministrator "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Schnappschussname enthält ungültige Zeichen"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Fehler"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"Folgende Zeichen sind für den Schnappschussnamen zulässig:\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"Alle ungültigen Zeichen werden entfernt\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Fehler beim Erstellen des Schnappschusses"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Schnappschuss wurde erfolgreich erstellt"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Erfolg"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"Ein Schnappschuss des ZFS-Dateisystems %(zfs_fs)s\n"
+"mit dem Namen %(valid_name)s\n"
+"wurde erstellt.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"„Schnappschuss jetzt“ erfordert 2 Argumente:\n"
+"-  Pfad des Verzeichnisses, von dem ein Schnappschuss genommen werden soll.\n"
+"-  Entsprechendes ZFS-Dateisystem für dieses Verzeichnis."
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"\"Schnappschuss jetzt\" erfordert Administratorrechte.  Ihnen wurden nicht "
+"die nötigen Administratorrechte zugewiesen.\n"
+"\n"
+"Wenden Sie sich an Ihren Systemadministrator.  "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid ""
+#~ "A snapshot of zfs filesystem %s\n"
+#~ "named %s\n"
+#~ "has been created.\n"
+#~ msgstr ""
+#~ "Ein Schnappschuss des ZFS-Dateisystems %s\n"
+#~ "mit dem Namen %s\n"
+#~ "wurde erstellt.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr ""
+#~ "Älteste Sicherungsdateien löschen, wenn der zur Nutzung vorgesehene "
+#~ "Speicherplatz überschritten wird:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "der Pool-Kapazität"
diff --git a/po/es.gmo b/po/es.gmo
new file mode 100644 (file)
index 0000000..df2a172
Binary files /dev/null and b/po/es.gmo differ
diff --git a/po/es.po b/po/es.po
new file mode 100644 (file)
index 0000000..4e8bb4b
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,870 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2009-02-16 18:31+0100\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr ""
+"Configurar el sistema para tomar instantáneas de manera automática de los "
+"datos"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Deslizador de tiempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "Se eliminarán %d instantáneas."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Resumen</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "D_eseleccionar todo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Eliminar instantáneas"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Eliminación de instantáneas"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Eliminando instantáneas..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Salir al terminar. "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Sistema de archivos:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Nombre:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Pulse Suprimir para continuar."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Buscando instantáneas..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr ""
+"Seleccione las instantáneas ZFS que desea eliminar de la siguiente lista."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Habilitar deslizador de tiempo</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Sistemas de archivos de los que hacer copia de seguridad</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Opciones avanzadas"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "_Personalizar:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Para usuarios avanzados"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Recomendado para la mayoría de los usuarios"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr ""
+"Destruir las copias de seguridad cuando se sobrepase el uso del espacio de "
+"almacenamiento:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Administrador del deslizador de tiempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+"El deslizador de tiempo hace copias de seguridad de datos con regularidad "
+"tomando instantáneas de ZFS programadas"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Todo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Eliminar instantáneas..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "de capacidad de sistema de archivos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Tomar una instantánea ahora"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Tomar una instantánea de "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "con el nombre:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Versión actual</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Versiones anteriores</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Haga doble clic para abrir este archivo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Abrir la versión actual del archivo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Buscando versiones anteriores"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Explorador de versiones de archivos del deslizador de tiempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "comparar"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "nombre_archivo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-cerrar"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "última modificación: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "nombre:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "tamaño: "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "Administrador del deslizador de tiempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Emergencia: '%s' se ha llenado"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"El sistema de archivos: '%s', está %s%% por encima.\n"
+"Como medida de emergencia, el deslizador de tiempo ha destruido todas sus "
+"copias de seguridad.\n"
+"Para solventar este problema, elimine todos los archivos innecesarios de '%"
+"s' o agregue espacio al disco (consulte la documentación de ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Emergencia: '%s' se ha llenado casi del todo"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"El sistema de archivos: '%s', ha sobrepasado un %s%% de su capacidad total. "
+"Como medida de emergencia, el deslizador de tiempo ha destruido casi todas "
+"sus copias de seguridad para impedir que el disco se llenara por completo. "
+"Para impedir que se repita este problema, elimine todos los archivos "
+"innecesarios de '%s' o agregue espacio al disco (consulte la documentación "
+"de ZFS).\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Urgente: '%s' se ha llenado casi del todo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"El sistema de archivos: '%s', ha sobrepasado un %s%% de su capacidad total. "
+"Como solución, el deslizador de tiempo ha destruido algunas copias de "
+"seguridad, y destruirá más, posiblemente todas, conforme siga disminuyendo "
+"la capacidad.\n"
+"Para impedir que se repita este problema, elimine todos los archivos "
+"innecesarios de '%s' o agregue espacio al disco (consulte la documentación "
+"de ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Advertencia: '%s' se está llenando"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"'%s' ha sobrepasado un %s%% de su capacidad total. Para solucionarlo, el "
+"deslizador de tiempo ha destruido algunas copias de seguridad recientes, y "
+"destruirá más conforme siga disminuyendo la capacidad.\n"
+"Para impedir que se repita este problema, elimine todos los archivos "
+"innecesarios de '%s' o agregue espacio al disco (consulte la documentación "
+"de ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Antiguo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Punto de montaje"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Nombre del sistema de archivos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Nombre de instantánea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Momento de creación"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Todos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Cada mes"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Cada semana"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Cada día"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Cada hora"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Cada cuarto de hora"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "La instantánea no se puede eliminar"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s tiene uno o más duplicados y no se puede eliminar. Para eliminar esta "
+"instantánea, primero debe borrar todos sus conjuntos de datos e instantáneas "
+"duplicados."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "Se eliminará 1 instantánea."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "No se ha podido leer algunas instantáneas"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "No se ha podido eliminar algunas instantáneas"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Los privilegios no son suficientes"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"La eliminación de la instantánea necesita privilegios administrativos. No se "
+"le ha asignado los correspondientes privilegios administrativos.\n"
+"\n"
+"Consulte al administrador del sistema"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Recuento de argumentos no válidos."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"El explorador de versiones necesita 2 argumentos:\n"
+"- La ruta del directorio raíz de las instantáneas.\n"
+"- El nombre del archivo que se va a explorar."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Seleccionar"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Error de dependencia del servicio de administrador de instantáneas"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"El servicio de administrador de instantáneas se ha quedado sin conexión por "
+"un problema de dependencia. Se han detectado los siguientes problemas de "
+"dependencia:\n"
+"\n"
+"%s\n"
+"\n"
+"Ejecute \"svcs -xv\" desde un indicador de comandos para obtener más "
+"información sobre estos problemas de dependencia."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Error del servicio de administrador de instantáneas"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"El servicio de administrador de instantáneas ha detectado un problema y se "
+"ha desactivado hasta que se solucione el problema.\n"
+"\n"
+"Para obtener más información, consulte la página de comando man svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"El servicio de administrador de instantáneas parece no estar instalado en "
+"este sistema.\n"
+"\n"
+"Para obtener más información, consulte la página de comando man svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"El servicio de administrador de instantáneas necesita privilegios "
+"administrativos. No se le ha asignado los correspondientes privilegios "
+"administrativos.\n"
+"\n"
+"Consulte al administrador del sistema "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Caracteres no válidos en el nombre de la instantánea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Error"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"Los caracteres permitidos en los nombres de las instantáneas son:\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"Se suprimirán todos los caracteres no válidos\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Error al crear la instantánea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "La instantánea se creó correctamente"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Correcto"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"Una instantánea del sistema de archivos zfs %(zfs_fs)s\n"
+"llamada %(valid_name)s\n"
+"se ha creado.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"Tomar instantánea ahora necesita 2 argumentos:\n"
+"- La ruta del directorio del que se va a tomar la instantánea.\n"
+"- El sistema de archivos zfs correspondiente a este directorio."
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Tomar instantánea ahora necesita privilegios administrativos. No se le han "
+"asignado los correspondientes privilegios administrativos.\n"
+"\n"
+"Consulte al administrador del sistema"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid ""
+#~ "A snapshot of zfs filesystem %s\n"
+#~ "named %s\n"
+#~ "has been created.\n"
+#~ msgstr ""
+#~ "Una instantánea del sistema de archivos zfs %s\n"
+#~ "llamada %s\n"
+#~ "se ha creado.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr ""
+#~ "Destruir la copias de seguridad más antiguas cuando el uso del espacio de "
+#~ "almacenamiento supere:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "de capacidad de la agrupación"
diff --git a/po/fr.gmo b/po/fr.gmo
new file mode 100644 (file)
index 0000000..13e64f7
Binary files /dev/null and b/po/fr.gmo differ
diff --git a/po/fr.po b/po/fr.po
new file mode 100644 (file)
index 0000000..6e01fed
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,864 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2009-02-16 18:36+0100\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr ""
+"Configurer le système de manière à prendre des instantanés automatiques des "
+"données"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Curseur temporel"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d instantanés seront supprimés."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Résumé</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "Tout désél_ectionner"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Supprimer des instantanés"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Suppression des instantanés"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Suppression des instantanés..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Quitter une fois l'opération terminée.  "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Système de fichiers :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Nom :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Cliquez sur Supprimer pour continuer."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Analyse des instantanés..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Sélectionnez les instantanés ZFS à supprimer dans la liste suivante."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Activer le curseur temporel</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Systèmes de fichiers à sauvegarder</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Options avancées"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "Pers_onnalisé :"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Pour les utilisateurs expérimentés"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Recommandé pour la plupart des utilisateurs"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Réduire les sauvegardes lorsque l'espace de stockage utilisé dépasse :"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Gestionnaire de curseur temporel"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+"Le curseur temporel sauvegarde les données régulièrement en prenant des "
+"instantanés ZFS différés"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Tous"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "Supprimer _des instantanés..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "de la capacité du système de fichiers"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Prenez un instantané"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Prenez un instantané de  "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "nommé :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Version actuelle</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Anciennes versions</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Cliquez deux fois sur le fichier pour l'ouvrir."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Ouvrez la version actuelle du fichier"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Recherche d'anciennes versions"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Explorateur de versions du fichier de curseur temporel"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "comparaison"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "nom de fichier"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "dernière modification :  "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "nom :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "taille :  "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "Gestionnaire de curseur temporel"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Urgence : %s est plein !"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"Le système de fichiers %s est rempli à plus de %s %%.\n"
+"Par mesure d'urgence, le curseur temporel a détruit toutes ses sauvegardes.\n"
+"Pour résoudre ce problème, supprimez tout fichier non indispensable sur %s "
+"ou ajoutez de l'espace disque (voir la documentation ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Urgence : %s est presque plein !"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"Le système de fichiers %s dépasse %s %% de sa capacité totale. Par mesure "
+"d'urgence, le curseur temporel a détruit toutes ses sauvegardes ou la "
+"plupart d'entre elles afin d'éviter que le disque soit plein. Pour éviter "
+"que cela se reproduise, supprimez tout fichier non indispensable sur %s ou "
+"ajoutez de l'espace disque (voir la documentation ZFS).\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Urgent : %s est presque plein !"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"Le système de fichiers %s dépasse %s %% de sa capacité totale. Pour résoudre "
+"cette situation, le curseur temporel a détruit certaines sauvegardes, en "
+"détruira d'autres et finira par les détruire toutes, si la capacité continue "
+"de diminue.\n"
+"Pour éviter que cela se reproduise, supprimez tout fichier non indispensable "
+"sur %s ou ajoutez de l'espace disque (voir la documentation ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Avertissement : %s est presque plein"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"%s dépasse %s %% de sa capacité totale. Pour résoudre cette situation, le "
+"curseur temporel a détruit des sauvegardes récentes et en détruira d'autres "
+"si la capacité continue de diminue.\n"
+"Pour éviter que cela se reproduise, supprimez tout fichier non indispensable "
+"sur %s ou ajoutez de l'espace disque (voir la documentation ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Hérité"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Point de montage"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Nom de système de fichiers"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Nom de l'instantané"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Période de création"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Tout"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Mensuelle"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Hebdomadaire"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Journalière"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Toutes les heures"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Tous les quarts d'heure"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Impossible de supprimer l'instantané"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s a un ou plusieurs clones dépendants et ne sera pas supprimé.  Supprimez "
+"au préalable tous les jeux de données et instantanés clonés à partir de cet "
+"instantané pour pouvoir supprimer ce dernier."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 instantané sera supprimé."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Certains instantanés n'ont pas pu être lus"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Certains instantanés n'ont pas pu être supprimés"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Privilèges insuffisants"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Pour supprimer des instantanés, vous devez posséder des privilèges "
+"administratifs.  Vous ne possédez pas les privilèges administratifs requis.\n"
+"\n"
+"Consultez votre administrateur système  "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Nombre d'arguments incorrect."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"L'explorateur de versions nécessite 2 arguments :\n"
+"- Chemin d'accès au répertoire d'instantanés racine.\n"
+"- Nom de fichier à explorer."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Sélectionner"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Erreur de dépendance du service de gestionnaire d'instantanés"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"Le service de gestionnaire d'instantané a été mis hors ligne en raison d'un "
+"problème de dépendance.  Les problèmes de dépendance suivants ont été "
+"détectés :\n"
+"\n"
+"%s\n"
+"\n"
+"Exécutez \"svcs  -xv\" à partir d'une invite de commande pour plus "
+"d'informations sur ces problèmes de dépendance."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Erreur du service de gestionnaire d'instantanés"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"Le service de gestionnaire d'instantanés a rencontré un problème et a été "
+"désactivé jusqu'à la résolution du problème.\n"
+"\n"
+"Pour de plus amples informations, reportez-vous à la page de manuel svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"Le service de gestionnaire d'instantanés ne semble pas être installé sur ce "
+"système.\n"
+"\n"
+"Pour de plus amples informations, reportez-vous à la page de manuel svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Pour exécuter le service de gestionnaire d'instantanés, vous devez posséder "
+"des privilèges administratifs. Vous ne possédez pas les privilèges "
+"administratifs requis.\n"
+"\n"
+"Consultez votre administrateur système "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Le nom de l'instantané contient des caractères non autorisés"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Erreur"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"Les caractères autorisés dans les noms d'instantané sont les suivants :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"Tous les caractères non autorisés seront supprimés\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Une erreur s'est produite lors de la création de l'instantané"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "L'instantané a été créé"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Terminé sans erreur"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"Un instantané d'un système de fichiers zfs %(zfs_fs)s\n"
+"nommé %(valid_name)s\n"
+"a été créé.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"L'option Prendre un instantané nécessite 2 arguments :\n"
+"- Chemin d'accès au répertoire dont un instantané doit être pris.\n"
+"- Système de fichiers ZFS correspondant à ce répertoire."
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Pour utiliser l'option Prendre un instantané, vous devez posséder des "
+"privilèges administratifs.  Vous ne possédez pas les privilèges "
+"administratifs requis.\n"
+"\n"
+"Consultez votre administrateur système  "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid ""
+#~ "A snapshot of zfs filesystem %s\n"
+#~ "named %s\n"
+#~ "has been created.\n"
+#~ msgstr ""
+#~ "Un instantané d'un système de fichiers zfs %s\n"
+#~ "nommé %s\n"
+#~ "a été créé.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr ""
+#~ "Détruire les plus anciennes sauvegardes lorsque l'espace de stockage "
+#~ "utilisé dépasse :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "de la capacité du pool"
diff --git a/po/hu.gmo b/po/hu.gmo
new file mode 100644 (file)
index 0000000..96ffccd
Binary files /dev/null and b/po/hu.gmo differ
diff --git a/po/hu.po b/po/hu.po
new file mode 100644 (file)
index 0000000..41fb1ed
--- /dev/null
+++ b/po/hu.po
@@ -0,0 +1,531 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+       "Project-Id-Version: time-slider HEAD\n"
+       "Report-Msgid-Bugs-To: \n"
+       "POT-Creation-Date: 2009-12-07 22:37+0900\n"
+       "PO-Revision-Date: 2010-01-20 20:31+0100\n"
+       "Last-Translator: Zsolt Suri <surizs@opensolaris.org>\n"
+       "Language-Team: Hungarian language team <i18n-discuss@opensolaris.org>\n"
+       "MIME-Version: 1.0\n"
+       "Content-Type: text/plain; charset=UTF-8\n"
+       "Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "A rendszer beállítása arra, hogy automatikusan mentse az Ön adatait"
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d pillanatkép törölve lesz."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Összesítés</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "Kijelölések megszüntetése"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Pillanatképek törlése"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Pillanatképek törlése"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Pillanatképek törlése..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Kilépés, ha elkészült. "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Fájlrendszer:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Név:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Nyomjon Delete-t a folytatáshoz."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Pillanatképek keresése..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Jelöljön ki ZFS pillanatképeket törlésre a listából."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Time Slider engedélyezése</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Fájl Rendszer Mentése</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Szakértői beállítások"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "_Egyedi:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr "Time Slider konfigurációja..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Tapasztalt felhasználóknak"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Ajánlott az átlagfelhasználóknak"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Csökkentse a mentések számát ha a tároló helyhasználata "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Time Slider Vezérlő"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "Time Slider rendszeresen végez mentéseket időzített ZFS pillanatképek készítésével."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Mind"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Pillanatkép törlése..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "fájlrendszer kapacitásának"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Pillanatkép készítése most"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Pillanatkép készítése a "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "névvel :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 megabájt"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Jelenlegi Verzió</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Régebbi Verziók</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Dupla kattintás a fájl megnyitásához"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Az aktuális fájl verzió megnyitása"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Keresés régebbi verziók után"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Time Slider Fájl Verzió Intéző"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "összehasonlítás"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "fájlnév"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "Utoljára módosítva : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "név :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "méret : "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr "Time Slider: Kevés Tárhely Figyelmeztetés"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Vészhelyzet: '%s' megtelt!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr "A fájlrendszer: '%s' több mint %s%%-kal megtelve."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+       "A fájlrendszer: '%s' több mint %s%%-a megtelt.\n"
+       "A katasztrófa elkerülés érdekében a Time Slider törölte az összes mentést.\n"
+       "A probléma megoldása érdekében töröljön minden felesleges fájlt a '%s'-ről, vagy adjon hozzá több lemezterületet (Lásd ZFS dokumentációt)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Vészhelyzet: '%s' majdnem teli!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr "A fájlrendszer: '%s' túllépte teljes kapacitásának %s%%-át"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+       "A fájlrendszer: '%s', túllépte teljes kapacitása %s%%-át. Mint egy vészhelyzetet elkerülendő, a Time Slider megsemmisítette a legtöbb vagy minden mentést mielőtt a lemez megtelne. A jövőben az ilyen helyzeteket megelőzvén törölje a felesleges fájlokat a '%s'-en vagy adjon hozzá lemezterületet (lást ZFS dokumentációt). "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Sürgős: '%s' majdnem megtelt!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+       "A fájlrendszer: '%s', túllépte teljes kapacitása %s%%-át. Mint egy javító intézkedés, a Time Slider megsemmisített számos mentést, és még többet fog, végül mindet, ahogy a kapacitás továbbra is csökken.\n"
+       "A jövőben az ilyen helyzeteket megelőzvén törölje a felesleges fájlokat a '%s'-en vagy adjon hozzá lemezterületet (lást ZFS dokumentációt). "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Figyelmeztetés: '%s' megtelik"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+       "A '%s' meghaladta teljes kapacitása %s%%-át. Javításként, a Time Slider megsemmisített néhány közeli mentést, és még többet fog, ahogy a kapacitás továbbra is csökken.\n"
+       "A jövőben az ilyen helyzeteket megelőzvén törölje a felesleges fájlokat a '%s'-en vagy adjon hozzá lemezterületet (lást ZFS dokumentációt).\n"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr "Részletek..."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Hagyományos"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Felcsatolási pont"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Fájlrendszer Neve"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Pillanatkép neve"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Készítés ideje"
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Mind"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Havi"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Heti"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Napi"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Óránkénti"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Negyed óránkénti"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Nem törölhető pillanatkép"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+       "Egy vagy több klónnal rendelkezik %s, így nem törölhető. Ezen pillanatkép törléséhez, először törölni kell a pillanatképből az összes adathalmazt és a klónozott pillanatképeket."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 pillanatkép kerül törlésre."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Néhány pillanatkép nem olvasható"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Néhány pillanatkép nem törölhető"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Nem megfelelő jogosultságok"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Pillanatkép törléséhez adminisztratív jogosultságok szükségesek. Ön nem rendelkezik a szükséges adminisztratív jogosultságokkal.\n"
+       "\n"
+       "Lépjen kapcsolatba a rendszer adminisztrátorával. "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr "Javaslat"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+       "Opcionális csomag telepítésével növelheti a fájlok összehasonlításának megjelenítését."
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Érvénytelen argumentum szám."
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+       "A verzió kezelő kettő paramétert igényel :\n"
+       "- Az elérési útvonala a gyökér pillanatképnek.\n"
+       "- Az érintett fájl neve."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Kiválasztás"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Pillanatkép kezelő szolgáltatás függőségi hiba"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+       "A pillanatkép kezelő szolgáltatás üzemen kívül lett helyezve függőségi probléma miatt. A következő függőségi problémák merültek fel:\n"
+       "\n"
+       "%s\n"
+       "\n"
+       "Futtassa a \"svcs -xv\" parancsot további információkért a függőségi problémákról."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Pillanatkép kezelő szolgáltatás hiba"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "A pillanatkép kezelő szolgáltatás problémába ütközött és ezért üzemen kívül lett helyezve a probléma megoldásáig.\n"
+       "\n"
+       "Lásd a svcs(1) man oldalt további információkért."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "A pillanatkép kezelő szolgáltatás nem úgy tűnik mint ha telepítve lenne ezen a rendszeren.\n"
+       "\n"
+       "Lásd a svcs(1) man oldalt további információkért."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "A pillanatkép kezelő szolgáltatás futtatásához adminisztratív jogosultságok szükségesek.Ön nem rendelkezik a szükséges adminisztratív jogosultságokkal.\n"
+       "\n"
+       "Lépjen kapcsolatba a rendszer adminisztrátorával. "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Érvénytelen karakterek a pillanatkép nevében"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Hiba"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+       "Pillanatkép nevében a következő karakterek engedélyezettek :\n"
+       "[a-z][A-Z][0-9][-_.:\n"
+       "Minden érvénytelen karakter eltávolításra kerül\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Hiba lépett fel pillanatkép készítésekor"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Pillanatkép sikeresen elkészítve"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Eredmény"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+       "A %(zfs_fs)s ZFS fájlrendszeren\n"
+       "%(valid_name)s névvel\n"
+       "pillanatkép készült.\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+       "A Pillanatkép Most kettő paramétert igényel :\n"
+       "- A könyvtár elérési útvonala, amelyről a pillanatkép készül.\n"
+       "- A könyvtárnak megfelelő ZFS fájlrendszer."
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Pillanatkép Most futtatásához adminisztratív  jogosultságok szükségesek. Ön nem rendelkezik a szükséges adminisztratív jogosultságokkal.\n"
+       "\n"
+       "Lépjen kapcsolatba a rendszer adminisztrátorával. "
diff --git a/po/id.gmo b/po/id.gmo
new file mode 100644 (file)
index 0000000..0205d65
Binary files /dev/null and b/po/id.gmo differ
diff --git a/po/id.po b/po/id.po
new file mode 100644 (file)
index 0000000..10e9db9
--- /dev/null
+++ b/po/id.po
@@ -0,0 +1,541 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+       "Project-Id-Version: time-slider HEAD\n"
+       "Report-Msgid-Bugs-To: \n"
+       "POT-Creation-Date: 2009-12-07 22:37+0900\n"
+       "PO-Revision-Date: 2010-01-20 20:31+0100\n"
+       "Last-Translator: Kurniawan Wahyu Illahi, martin\n"
+       "Language-Team: Indonesian language team <i18n-discuss@opensolaris.org>\n"
+       "MIME-Version: 1.0\n"
+       "Content-Type: text/plain; charset=UTF-8\n"
+       "Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "       "
+       "Mengkonfigurasi sistem otomatis untuk mengambil snapshot dari data anda"
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d snapshots akan dihapus"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Hasil</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "D_eselect All"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Menghapus Snapshots"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Menghapus Snapshots"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Menghapus snapshots..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Keluar ketika selesai "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "File Sistem:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Nama:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Tekan Delete untuk melanjutkan."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Memindai snapshots..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Pilih ZFS snapshots untuk menghapus dari daftar dibawah ini."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Enable Time Slider</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>File Systems To Back Up</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Pilihan Lanjutan"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "C_ustom:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr "Sedang mengkonfigurasi Time Slider..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Untuk pengguna lanjutan"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Direkomendasikan untuk sebagian besar pengguna"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Mengurangi ruang penyimpanan backup bila melebihi kapasitas :"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Pengendali Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "Time Slider membackup data secara teratur berdasarkan waktu Snapshot ZFS"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Semua"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Menghapus Snapshots..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "dari kapasitas file sistem"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Mengambil snapshot sekarang"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Mengambil snapshot dari "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "dengan nama :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Versi Saat Ini</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Versi Lama</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Klik dua kali untuk membuka file"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Buka file dengan versi saat ini"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Pemindaian untuk versi lama"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Time Slider File Version Explorer"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "bandingkan"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "nama file"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "modifikasi terakhir : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "nama :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "ukuran : "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr "Time Slider: Peringatan Tempat Penyimpanan Hampir Penuh"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Darurat: '%s' penuh!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr "file sistem: '%s', melebihi %s%% penuh."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+       "File sistem: '%s', is over %s%% full.\n"
+       "Ukuran darurat, Time Slider akan menghancurkan semua backup.\n"
+       "Untuk memperbaiki masalah ini, hapus semua file yang tidak diperlukan di '%s', atau tambah ukuran disk."
+       ""
+       "(lihat dokumentasi ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Darurat: '%s' hampir penuh!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr "File Sistem: '%s', melebihi %s%% dari kapasitas total."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+       "File Sistem: '%s', melebihi %s%% dari kapasitas total. Sebagai penanganan darurat, Time Slider telah menghapus sebagian besar atau semua backup untuk mencegah tempat penyimpanan menjadi penuh. Untuk menghindari hal ini terjadi lagi, hapus file-file yang tidak perlu pada '%s', "
+       "atau tambahkan tempat penyimpanan(lihat dokumentasi ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Mendesak: '%s' hampir penuh!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+       "File sistem: '%s', melebihi %s%% kapasitas total. Penanganannya, Time Slider akan menghancurkan beberapa backup, dan akan menghancurkan lainnya, "
+       "bahkan semuanya, selama kapasitas semakin menurun.\n"
+       "Untuk menghindari keadaan ini terjadi lagi, hapus file-file yang tidak perlu pada '%s', "
+       "atau tambahkan tempat penyimpanan(lihat dokumentasi ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Peringatan: '%s' mulai penuh"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+       "'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+       "destroyed some recent backups, and will destroy more as capacity continues "
+       "to diminish.\n"
+       "To prevent this from happening again, delete any unnecessary files on '%s', "
+       "or add disk space (see ZFS documentation).\n"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr "Rincian..."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Legacy"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Mount Point"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Nama File Sistem"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Nama Snapshot"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Waktu Pembuatan"
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Semua"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Bulanan"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Mingguan"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Harian"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Tiap Jam"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Tiap 1/4 jam"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Snapshot tidak dapat dihapus"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+       "%s mempunyai satu atau beberapa clone yang tergantung dan tidak akan dihapus. Untuk menghapus snapshot ini, langkah pertama hapus seluruh datasets dan clones snapshots dari snapshot ini."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 snapshot akan di hapus"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Beberapa snapshot tidak dapat dibaca"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Beberapa snapshot tidak dapat dihapus"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Hak akses tidak mencukupi"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Menghapus snapshot membutuhkan hak akses administrasi agar dapat berjalan. Anda belum terdaftar sebagai user yang mempunyai hak akses administrasi.\n"
+       "\n"
+       "Konsultasi dengan sistem administrator anda. "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr "Petunjuk"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+       "Installing the optional meld package will enhance the file comparison "
+       "visualization"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Kesalahan argumen bertambah"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+       "Versi explorer membutuhkan 2 argumen :\n"
+       "- Path dari direktori root snapshot.\n"
+       "- Nama file untuk pencarian"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Pilih"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Kesalahan dependensi layanan pengendali Snapshot"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+       "Layanan pengendali snapshot berada dalam status offline karena permasalah ketergantungan. Beberapa masalah ketergantungan yang ditemukan: \n"
+       "\n"
+       "%s\n"
+       "\n"
+       "Jalankan \"svcs -xv\" dari terminal untuk informasi lebih lanjut tentang masalah ketergantungan."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Layanan pengendali Snapshot error"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "Layanan pengendali snapshot mengalami masalah dan akan di nonaktifkan sampai permasalahan di betulkan.\n"
+       "\n"
+       "Lihat halaman manual svcs(1) untuk informasi lebih lanjut."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "Layanan pengendali snapshot tidak terlihat terinstall pada sistem anda.\n"
+       "\n"
+       "Lihat halaman manual svcs(1) untuk informasi lebih lanjut"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Layanan Pengendali Snapshot membutuhkan hak akses administrasi agar dapat berjalan. Anda belum terdaftar sebagai user yang mempunyai hak akses administrasi.\n"
+       "\n"
+       "Konsultasi dengan sistem administrator anda. "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Invalid karakter pada nama snapshot"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Error"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+       "Karakter yang diperbolehkan untuk nama snapshot adalah :\n"
+       "[a-z][A-Z][0-9][-_.:\n"
+       "Semua karakter yang tidak valid akan di hapus\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Terjadi error ketika membuat snapshot"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Sukses membuat snapshot"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Sukses"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+       "Snapshot dari file sistem zfs %(zfs_fs)s\n"
+       "nama %(valid_name)s\n"
+       "telah dibuat.\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+       "Snapshot Sekarang membutuhkan 2 argumen :\n"
+       "- Path dari direktori yang akan di snapshot.\n"
+       "- File sistem zfs yang sesuai dengan direktori ini."
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Snapshot sekarang membutuhkan hak akses administrasi untuk berjalan. Anda belum terdaftar sebagai user yang mempunyai hak akses administrasi.\n"
+       "\n"
+       "Konsultasi dengan sistem administrator anda "
diff --git a/po/it.gmo b/po/it.gmo
new file mode 100644 (file)
index 0000000..0241b62
Binary files /dev/null and b/po/it.gmo differ
diff --git a/po/it.po b/po/it.po
new file mode 100644 (file)
index 0000000..a99c2d3
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,864 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2009-02-16 18:42+0100\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr ""
+"Configurare il sistema per fare delle istantanee automatiche dei propri dati"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Time Slider"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "Verranno eliminate %d istantanee."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Riepilogo</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "D_eseleziona tutto"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Elimina istantanee"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Eliminazione delle istantanee"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Eliminazione delle istantanee in corso…"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Chiudi al termine dell'operazione. "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "File system:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Nome:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Premere Elimina per continuare."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Scansione delle istantanee in corso…"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr ""
+"Selezionare le istantanee ZFS da eliminare dall’elenco di seguito riportato."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Abilita Time Slider </b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>File system di cui eseguire il backup</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Opzioni avanzate"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "Personali_zzato:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Per utenti avanzati"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Per tutti gli utenti"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Ridurre i backup quando lo spazio di memorizzazione utilizzato supera:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Gestione Time Slider"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+"Time Slider consente di eseguire regolarmente backup dei dati mediante "
+"l'acquisizione di istantanee ZFS a intervalli regolari"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Tutto"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Elimina istantanee…"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "della capacità del file system"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Crea un’istantanea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Crea un’istantanea di "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "con il nome :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Versione corrente</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Versioni precedenti</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Fare doppio clic per aprire il file"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Apri la versione corrente del file"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Ricerca delle versioni precedenti in corso..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Explorer versione del file Time Slider"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "confronta"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "nome file"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "ultima modifica : "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "nome :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "dimensioni : "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "Gestione Time Slider"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Attenzione: '%s' è pieno."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"Spazio del file system '%s' occupato oltre il %s%%.\n"
+"Come misura di emergenza, Time Slider ha eliminato tutti i backup eseguiti.\n"
+"Per risolvere il problema, eliminare i file non necessari in '%s' oppure "
+"aggiungere spazio nel disco (vedere la documentazione di ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Attenzione: '%s' è quasi pieno."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"La capacità totale del file system '%s' è stata superata del %s%%. Come "
+"misura di emergenza, Time Slider ha eliminato tutti o la maggior parte dei "
+"backup per impedire che lo spazio su disco venga esaurito. Per evitare il "
+"ripetersi del problema, eliminare eventuali file non necessari in '%s' "
+"oppure aggiungere spazio su disco (vedere la documentazione di ZFS).\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Avviso: '%s' è quasi pieno."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"La capacità totale del file system '%s' è stata superata del %s%%. Come "
+"rimedio, Time Slider ha eliminato alcuni backup e ne eliminerà altri o tutti "
+"man mano che la capacità diminuisce.\n"
+"Per evitare il ripetersi del problema, eliminare eventuali file non "
+"necessari in '%s' oppure aggiungere spazio sul disco (vedere la "
+"documentazione di ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Avvertenza: lo spazio su '%s' sta per esaurirsi"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"'%s' ha superato la relativa capacità complessiva del %s%%. Per risolvere il "
+"problema, Time Slider ha eliminato alcuni backup recenti e ne eliminerà "
+"altri man mano che la capacità diminuisce.\n"
+"Per evitare il ripetersi del problema, eliminare eventuali file non "
+"necessari in '%s' oppure aggiungere spazio su disco (vedere la "
+"documentazione di ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Legacy"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Punto di attivazione"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Nome file system"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Nome istantanea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Tempo di creazione"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Tutto"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Mensile"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Settimanale"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Ogni giorno"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Ogni ora"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Ogni quarto d’ora"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Impossibile eliminare l’istantanea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s possiede uno o più cloni dipendenti e non verrà eliminata. Per eliminare "
+"questa istantanea, eliminare prima tutti i set di dati e le istantanee "
+"clonate da questa istantanea."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 istantanea verrà eliminata."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Impossibile leggere alcune istantanee"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Impossibile eliminare alcune istantanee "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Privilegi insufficienti"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Per l'esecuzione dell’eliminazione delle istantanee sono necessari privilegi "
+"amministrativi. Non si dispone di privilegi amministrativi necessari.\n"
+"\n"
+"Rivolgersi all'amministratore di sistema. "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Calcolo degli argomenti non valido."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"L’explorer della versione richiede 2 argomenti :\n"
+"- La path della directory radice dell’istantanea .\n"
+"- Il nome file da ricercare."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Seleziona"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Errore di dipendenza del servizio di gestione delle istantanee"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"Il servizio di gestione delle istantanee è stato disconnesso a causa di un "
+"problema di dipendenza. Sono stati riscontrati i seguenti problemi di "
+"dipendenza:\n"
+"\n"
+"%s\n"
+"\n"
+"Eseguire \"svcs -xv\" da un prompt di comando per ottenere maggiori "
+"informazioni su questi problemi di dipendenza."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Errore del servizio di gestione delle istantanee"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"Il servizio di gestione delle istantanee ha riscontrato un problema ed è "
+"stato disabilitato fino alla risoluzione del problema.\n"
+"\n"
+"Per ulteriori informazioni consultare la pagina man svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"Il servizio di gestione delle istantanee non sembra essere installato nel "
+"sistema corrente.\n"
+"\n"
+"Per ulteriori informazioni consultare la pagina man svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Per l'esecuzione del servizio di gestione delle istantanee sono necessari "
+"privilegi amministrativi. Non si dispone di privilegi amministrativi "
+"sufficienti.\n"
+"\n"
+"Rivolgersi all'amministratore di sistema. "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Caratteri invalidi nel nome dell’istantanea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Errore"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"I caratteri ammessi per i nomi delle istantanee sono :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"Tutti i caratteri invalidi saranno rimossi\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Errore durante la creazione dell’istantanea"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Istantanea creata con successo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Operazione riuscita"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"Un’istantanea del file system zfs %(zfs_fs)s\n"
+"denominata %(valid_name)s\n"
+"è stata creata.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"Crea istantanea richiede 2 argomenti :\n"
+"- La path della directory di cui deve essere creata l’istantanea.\n"
+"- Il file system zfs corrispondente a questa directory."
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Per l’esecuzione del comando Crea istantanea sono necessari privilegi "
+"amministrativi. Non si dispone dei privilegi amministrativi necessari.\n"
+"\n"
+"Rivolgersi all'amministratore di sistema. "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid ""
+#~ "A snapshot of zfs filesystem %s\n"
+#~ "named %s\n"
+#~ "has been created.\n"
+#~ msgstr ""
+#~ "Un’istantanea del file system zfs %s\n"
+#~ "denominata %s\n"
+#~ "è stata creata.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr ""
+#~ "Elimina i backup meno recenti quando lo spazio di memorizzazione "
+#~ "utilizzato supera:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "di capacità del pool"
diff --git a/po/ja.gmo b/po/ja.gmo
new file mode 100644 (file)
index 0000000..df91b1e
Binary files /dev/null and b/po/ja.gmo differ
diff --git a/po/ja.po b/po/ja.po
new file mode 100644 (file)
index 0000000..bdc44c7
--- /dev/null
+++ b/po/ja.po
@@ -0,0 +1,944 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2008-10-01 21:35+0900\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "自動的にデータのスナップショットを作成するようにシステムを構成します"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "タイムスライダ"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d 個のスナップショットが削除されます。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>要約</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "すべてを選択解除(_E)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "スナップショットの削除"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "スナップショットを削除しています"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "スナップショットを削除しています..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "完了したら終了します。 "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "ファイルシステム: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "名前: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "続行するには「削除」を押します。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "スナップショットをスキャンしています..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "下の一覧から削除する ZFS スナップショットを選択します。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>タイムスライダを有効にする</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>バックアップするファイルシステム</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "詳細オプション"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "カスタム(_U): "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "上級ユーザー向け"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "ほとんどのユーザーに推奨"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "ストレージスペースの使用量が超過したらバックアップを削減する:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "タイムスライダマネージャー"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+"タイムスライダは、時刻指定の ZFS スナップショットを作成することによって定期的"
+"にデータをバックアップします"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "すべて(_A)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "スナップショットの削除(_D)..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "ファイルシステム容量"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "今すぐスナップショットを取得する"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "スナップショットを取得する対象 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "名前: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>現在のバージョン</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>旧バージョン</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "ダブルクリックしてファイルを開く"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "ファイルの現在のバージョンを開く"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "旧バージョンをスキャンしています"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "タイムスライダファイルバージョンエクスプローラ"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "比較"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "ファイル名"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "最終更新日付:  "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "名前: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "サイズ:  "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "タイムスライダマネージャー"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "緊急: '%s' がいっぱいです。"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"ファイルシステム: '%s' が総容量の %s%% を超えました。\n"
+"緊急の手段として、タイムスライダはすべてのバックアップを破棄しました。\n"
+"この問題を解決するために、'%s' 上の不必要なファイルをすべて削除するか、または"
+"ディスク容量を追加してください (ZFS のマニュアルを参照)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "緊急: '%s' がほぼいっぱいです。"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"ファイルシステム: '%s' が総容量の %s%% を超えました。緊急の手段として、ディス"
+"クがいっぱいになることを避けるために、タイムスライダはほとんどまたはすべての"
+"バックアップを破棄しました。この問題がふたたび発生しないようにするために、'%"
+"s' 上の不必要なファイルをすべて削除するか、またはディスク容量を追加してくださ"
+"い (ZFS のマニュアルを参照)。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "緊急: '%s' がほぼいっぱいです。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"ファイルシステム: '%s' が総容量の %s%% を超えました。是正手段として、タイムス"
+"ライダはすでに一部のバックアップを破棄しており、容量が減り続ければさらに多く"
+"のバックアップ、最終的にはすべてのバックアップを破棄します。\n"
+"この問題がふたたび発生しないようにするために、'%s' 上の不必要なファイルをすべ"
+"て削除するか、またはディスク容量を追加してください (ZFS のマニュアルを参照)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "警告: '%s' がいっぱいになりつつあります"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"'%s' が総容量の %s%% を超えました。この問題を解決するために、タイムスライダは"
+"すでに一部の最新のバックアップを破棄しており、容量が減り続ければさらに多くの"
+"バックアップを破棄します。\n"
+"この問題がふたたび発生しないようにするために、'%s' 上の不必要なファイルをすべ"
+"て削除するか、またはディスク容量を追加してください (ZFS のマニュアルを参照)。"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "旧バージョン"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "マウントポイント"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "ファイルシステム名"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "スナップショット名"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "作成時間"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "すべて"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "毎月"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "毎週"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "毎日"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "毎時"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "15 分ごと"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "スナップショットを削除できません"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s には 1 つ以上の複製が依存しているため、削除されません。このスナップショッ"
+"トを削除するには、まず、このスナップショットから複製されたすべてのデータセッ"
+"トとスナップショットを削除してください。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 つのスナップショットが削除されます。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "いくつかのスナップショットを読み取れませんでした"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "いくつかのスナップショットを削除できませんでした"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "権限が不足しています"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"スナップショットの削除を実行するには管理権限が必要です。必要な管理権限が割り"
+"当てられていません。\n"
+"\n"
+"システム管理者に問い合わせてください"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "引数の数が無効です。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"バージョンエクスプローラには次の 2 つの引数が必要です:\n"
+"- ルートスナップショットディレクトリのパス。\n"
+"- 調査するファイル名。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "選択"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "スナップショットマネージャーサービスの依存関係エラー"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"依存関係の問題が発生したために、スナップショットマネージャーサービスがオフラ"
+"インになりました。次の依存関係の問題が検出されました:\n"
+"\n"
+"%s\n"
+"\n"
+"これらの依存関係の問題の詳細を表示するには、コマンドプロンプトから \"svcs -xv"
+"\" を実行してください。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "スナップショットマネージャーサービスのエラー"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"スナップショットマネージャーサービスが問題を検出し、この問題が解決されるまで"
+"無効になっています。\n"
+"\n"
+"詳細は、svcs(1) のマニュアルページを参照してください。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"このシステムにはスナップショットマネージャーサービスがインストールされていな"
+"いようです。\n"
+"\n"
+"詳細は、svcs(1) のマニュアルページを参照してください。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"スナップショットマネージャーサービスを実行するには管理権限が必要です。必要な"
+"管理権限が割り当てられていません。\n"
+"\n"
+"システム管理者に問い合わせてください"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "スナップショット名の文字が無効です"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "エラー"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"スナップショット名に許可されている文字は次のとおりです:\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"無効な文字はすべて削除されます。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "スナップショットの作成中にエラーが発生しました"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "スナップショットが正常に作成されました"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "成功"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"zfs ファイルシステム %(zfs_fs)s のスナップショット\n"
+"(名前は %(valid_name)s)\n"
+"が作成されました。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"「今すぐスナップショット」には次の 2 つの引数が必要です:\n"
+"- スナップショットを取得するディレクトリのパス。\n"
+"- このディレクトリに対応する zfs ファイルシステム。"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"「今すぐスナップショット」を実行するには管理権限が必要です。必要な管理権限が"
+"割り当てられていません。\n"
+"\n"
+"システム管理者に問い合わせてください"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#~ msgid ""
+#~ "A snapshot of zfs filesystem %s\n"
+#~ "named %s\n"
+#~ "has been created.\n"
+#~ msgstr ""
+#~ "zfs ファイルシステム %s のスナップショット\n"
+#~ "(名前は %s)\n"
+#~ "が作成されました。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr ""
+#~ "ストレージスペースの使用量が超過したらもっとも古いバックアップを破棄する:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN TECH REVIEWED
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "プール容量"
diff --git a/po/ko.gmo b/po/ko.gmo
new file mode 100644 (file)
index 0000000..fed42da
Binary files /dev/null and b/po/ko.gmo differ
diff --git a/po/ko.po b/po/ko.po
new file mode 100644 (file)
index 0000000..6cf0bf3
--- /dev/null
+++ b/po/ko.po
@@ -0,0 +1,856 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2008-10-01 21:35+0900\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "사용자 데이터의 자동 스냅샷을 만들도록 시스템 구성"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "시간 슬라이더"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d개의 스냅샷이 삭제됩니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>요약</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "모두 선택 해제(_E)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "스냅샷 삭제"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "스냅샷 삭제 중"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "스냅샷 삭제 중..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "완료 후 종료합니다. "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "파일 시스템:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "이름:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "계속하려면 삭제를 누르십시오."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "스냅샷 검색 중..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "다음 목록에서 삭제할 ZFS 스냅샷을 선택하십시오."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>시간 슬라이더 활성화</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>백업할 파일 시스템</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "고급 옵션"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "사용자 정의(_U):"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "고급 사용자용"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "대부분의 사용자에게 권장"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "저장소 공간 사용량이 초과되는 경우 백업 줄이기:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "시간 슬라이더 관리자"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+"시간 슬라이더는 시간이 지정된 ZFS 스냅샷을 가져와 데이터를 정기적으로 백업합"
+"니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "모두(_A)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "스냅샷 삭제(_D)..."
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "- 파일 시스템 용량"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "지금 스냅샷 실행"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "다음 항목의 스냅샷 실행 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "이름:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>현재 버전</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>이전 버전</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "파일을 열려면 두 번 누릅니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "파일의 현재 버전을 엽니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "이전 버전 검색 중"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "시간 슬라이더 파일 버전 탐색기"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "비교"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "파일 이름"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "마지막 수정: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "이름:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "크기: "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "시간 슬라이더 관리자"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "긴급: '%s'이(가) 꽉 찼습니다!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"파일 시스템 '%s'이(가) %s%% 이상으로 꽉 찼습니다.\n"
+"긴급 조치로 시간 슬라이더가 모든 백업을 삭제했습니다\n"
+"이 문제를 해결하려면 '%s'에서 불필요한 파일을 삭제하거나 디스크 공간을 추가하"
+"십시오(ZFS 설명서 참조)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "긴급: '%s'이(가) 거의 찼습니다!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"파일 시스템 '%s'이(가) 총 용량의 %s%%을(를) 초과했습니다. 긴급 조치로 시간 슬"
+"라이더가 백업을 모두 삭제하거나 대부분 삭제하여 디스크가 꽉 차는 문제를 방지"
+"했습니다. 이러한 문제가 다시 발생하지 않도록 '%s'에서 불필요한 파일을 삭제하"
+"거나 디스크 공간을 추가합니다(ZFS 설명서 참조).\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "중요: '%s'이(가) 거의 찼습니다!"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"파일 시스템 '%s'이(가) 총 용량의 %s%%을(를) 초과했습니다. 해결 조치로시간 슬"
+"라이더가 일부 백업을 삭제했으며, 용량이 계속 줄어들 때 좀 더 삭제할 예정이며 "
+"결국 모두 삭제합니다.\n"
+"이러한 문제가 다시 발생하지 않도록 '%s'에서 불필요한 파일을 삭제하거나 디스"
+"크 공간을 추가합니다(ZFS 설명서 참조)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "경고: '%s'이(가) 꽉 찼습니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"'%s'이(가) 총 용량의 %s%%을(를) 초과했습니다. 이 문제를 해결하기 위해 시간 슬"
+"라이더가 최근의 일부 백업을 삭제했으며 용량이 계속 줄어들 때 좀 더 삭제할 예"
+"정입니다.\n"
+"이러한 문제가 다시 발생하지 않도록 '%s'에서 불필요한 파일을 삭제하거나 디스"
+"크 공간을 추가합니다(ZFS 설명서 참조)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "레거시"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "마운트 지점"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "파일 시스템 이름"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "스냅샷 이름"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "생성 시간"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "모두"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "매달"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "매주"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "매일"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "매시간"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "매25분"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "스냅샷을 삭제할 수 없습니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s에 하나 이상의 종속 복제가 있어 삭제되지 않습니다. 이 스냅샷을 삭제하려면 "
+"먼저 이 스냅샷에서 복제된 모든 데이터 집합과 스냅샷을 삭제하십시오."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1개의 스냅샷이 삭제됩니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "일부 스냅샷을 읽을 수 없습니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "일부 스냅샷을 삭제할 수 없습니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "권한 부족"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"스냅샷 삭제 기능을 실행하려면 관리 권한이 필요합니다. 필요한 관리 권한이  할"
+"당되지 않았습니다.\n"
+"\n"
+"시스템 관리자에게 문의하십시오. "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "잘못된 인수 카운트입니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"버전 탐색기에 다음과 같은 2개의 인수가 필요합니다.\n"
+"- 루트 스냅샷 디렉토리의 경로\n"
+"- 탐색할 파일 이름"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "선택"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "스냅샷 관리자 서비스 종속성 오류"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"스냅샷 관리자 서비스가 종속성 문제로 인해 오프라인 상태로 설정되었습니다. 다"
+"음과 같은 종속성 문제가 발견되었습니다.\n"
+"\n"
+"%s\n"
+"\n"
+"이러한 종속성 문제에 대한 자세한 내용을 보려면 명령 프롬프트에서 \"svcs -xv"
+"\"를 실행하십시오."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "스냅샷 관리자 서비스 오류"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"스냅샷 관리자 서비스에 문제가 발생하여 문제가 수정될 때까지 비활성화되었습니"
+"다.\n"
+"\n"
+"자세한 내용은 svcs(1) 매뉴얼 페이지를 참조하십시오."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"스냅샷 관리자 서비스가 이 시스템에 설치된 것으로 나타나지 않습니다.\n"
+"\n"
+"자세한 내용은 svcs(1) 매뉴얼 페이지를 참조하십시오."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"스냅샷 관리자 서비스를 실행하려면 관리 권한이 필요합니다. 필요한관리 권한이 "
+"지정되지 않았습니다.\n"
+"\n"
+"시스템 관리자에게 문의하십시오. "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "스냅샷 이름에 잘못된 문자가 있습니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "오류"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"스냅샷 이름에 사용할 수 있는 문자는 다음과 같습니다.\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"잘못된 문자는 모두 제거됩니다.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "스냅샷 생성 중 오류가 발생했습니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "스냅샷이 성공적으로 생성되었습니다."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "성공"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"zfs 파일 시스템 %(zfs_fs)s의 스냅샷\n"
+"%(valid_name)s이(가)\n"
+"생성되었습니다.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"지금 스냅샷 기능에는 다음과 같은 2개의 인수가 필요합니다.\n"
+"- 스냅샷될 디렉토리의 경로\n"
+"- 이 디렉토리에 해당하는 zfs 파일 시스템"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"지금 스냅샷 기능을 실행하려면 관리 권한이 필요합니다. 필요한 관리 권한이 할당"
+"되지 않았습니다.\n"
+"\n"
+"시스템 관리자에게 문의하십시오. "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid ""
+#~ "A snapshot of zfs filesystem %s\n"
+#~ "named %s\n"
+#~ "has been created.\n"
+#~ msgstr ""
+#~ "zfs 파일 시스템 %s의 스냅샷\n"
+#~ "%s이(가)\n"
+#~ "생성되었습니다.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr "저장소 공간 사용량이 초과되는 경우 가장 오래된 백업 삭제:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "풀 용량"
diff --git a/po/nl.gmo b/po/nl.gmo
new file mode 100644 (file)
index 0000000..5d13d52
Binary files /dev/null and b/po/nl.gmo differ
diff --git a/po/nl.po b/po/nl.po
new file mode 100644 (file)
index 0000000..678251c
--- /dev/null
+++ b/po/nl.po
@@ -0,0 +1,550 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+       "Project-Id-Version: time-slider HEAD\n"
+       "Report-Msgid-Bugs-To: \n"
+       "POT-Creation-Date: 2009-02-10 22:37+0900\n"
+       "PO-Revision-Date: 2010-01-20 22:14+0900\n"
+       "Last-Translator: Marlen K. Waaijer\n"
+       "Language-Team: Dutch (Nederlands) <i18n-discuss@opensolaris.org>\n"
+       "MIME-Version: 1.0\n"
+       "Content-Type: text/plain; charset=UTF-8\n"
+       "Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "Configureer het systeem om automatische momentopnamen van je gegevens te nemen"
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Tijd glijder"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d momentopnamen zullen worden verwijdert"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Samenvatting</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "D_eselecteer alle"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Verwijder momentopnamen"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Momentopnames worden verwijdert"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Momentopnamen worden verwijdert..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Sluit af als je klaar bent. "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Bestand systeem:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Naam:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Druk delete om door te gaan."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Momentopnamen aan het scanderen..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Kies de te verwijderen ZFS momentopnamen van de lijst beneden. "
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Schakel tijd slijder in</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Bestand systemen voor backup</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Geavanceerde opties"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "C_ustom:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr "Configuring Time Slider..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Voor geavanceerde gebruikers"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Aanbevolen voor de meeste gebruikers"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Verminder back-ups als opslagruimte gebruik meer bedraagt dan:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Tijd glijder beheerder"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "Tijd glijder maakt reservekopie&#235;n van gegevens door het nemen van een regelmatige ZFS momentopnamen"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Alle"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Verwijder momentopnames..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "van bestand systeem capaciteit"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Neem nu een momentopname"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Neem een momentopname van "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "met de naam :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 MO"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Huidige versie</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Oudere versies</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Dubbelklik om het bestand te openen"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Open de huidige versie van het bestand"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Zoeken naar oudere versies"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Tijd slijder bestand versie onverzoeker"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "vergelijk"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "bestand naam"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-sluiten"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "laatst bewerkt : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "name :"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "grootte : "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr "Time Slider: Low Space Warning"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Alarm: '% s' is vol!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr "The file system: '%s', is over %s%% full."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+       "Het bestandssysteem: '%s' is meer dan% s%% vol. \n"
+       "Als een noodmaatregel, Time Slider heeft alle back-ups vernietigd. \n"
+       "Om dit probleem te verhelpen, verwijdert u overbodige bestanden op '% s' of voeg schijfruimte"
+       "(zie documentatie ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Noodgeval: '% s' is bijna vol!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr "The file system: '%s', exceeded %s%% of its total capacity"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+       "The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+       "measure, Time Slider has has destroyed most or all of its backups to prevent "
+       "the disk becoming full. To prevent this from happening again, delete any "
+       "unnecessary files on '%s', or add disk space (see ZFS documentation)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Urgent: '% s' is bijna vol!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+       "Het bestandssysteem: '%s', heeft %s%% van de totale capaciteit overschreden. Zoals een corrigerende"
+       "maatregel, Time Slider heeft een aantal back-ups vernietigd, en zal daarmee doorgaan , "
+       "totdat uiteindelijk alle back-ups vernietigd zijn, zolang de capaciteit blijft afnemen.\n"
+       "Om te voorkomen dat dit opnieuw gebeurt, verwijder alle overbodige bestanden op '%s',"
+       "of voeg schrijfruimte toe (zie ZFS documentatie)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Waarschuwing: '%s' wordt voller en voller"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+       "'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+       "destroyed some recent backups, and will destroy more as capacity continues "
+       "to diminish.\n"
+       "To prevent this from happening again, delete any unnecessary files on '%s', "
+       "or add disk space (see ZFS documentation).\n"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr "Details..."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Legaat"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Monteer punt"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Bestand systeem naam"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Momentopname naam"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Aanmaaktijd"
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Alle"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Maandelijks"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Wekelijks"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Dagelijks"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Ieder uur"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Ieder kwartier"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Momentopname kan niet gewist worden"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+       "% s heeft een of meer afhankelijke klonen en zal niet worden verwijderd. Om deze momentopname te verwijderen,"
+       "moeten eerst alle gekloonde datasets en momentopnames van deze momentopname verwijdert worden."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 momentopname zal niet verwijdert worden"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Sommige momentopnames konden niet gelezen worden"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Sommige momentopnames konden niet verwijdert worden"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Onvoldoende Privileges"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Momentopname verwijdering vereist administratieve privileges om te lopen. Je hebt niet "
+       "de nodige administratieve privileges.\n"
+       "\n"
+       "Raadpleeg je systeembeheerder "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr "Hint"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+       "Installing the optional meld package will enhance the file comparison "
+       "visualization"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Ongeldige argumenten aantal."
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+       "Versie ontdekker vereist 2 argumenten:\n"
+       "- Het pad van de root locatie voor de momentopname.\n"
+       "- De bestandsnaam te die gezocht wordt."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Selecteer"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Momentopname manager service afhankelijkheid fout"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+       "De momentopname manager dienst is uitgeschakeld wegens een afhankelijkheids"
+       "probleem. De volgende afhankelijkheidsproblemen waren gevonden:\n"
+       "\n"
+       "%s\n"
+       "\n"
+       "Typ de opdrachtregel \" svcs -xv\" in een commandovenster voor meer informatie over deze "
+       "afhankelijkheidsproblemen."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Momentopname manager service fout"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "De momentopname manager dienst heeft een probleem ondergaan en is uitgeschakeld "
+       "totdat het probleem is opgelost.\n"
+       "\n"
+       "Zie de Svcs (1) man pagina voor meer informatie."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "De momentopname manager dienst blijkt niet geïnstalleerd te zijn op dit"
+       "systeem.\n"
+       "\n"
+       "Zie de svcs(1) man pagina voor meer informatie."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "De momentopname manager service vereist administratieve privileges om te lopen. U"
+       "heeft niet de vereiste administratieve privileges. \n"
+       "\n"
+       "Raadpleeg uw systeembeheerder "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Ongeldige tekens in momentopname naam"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Fout"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+       "Geldige tekens voor momentopname namen zijn:\n"
+       "[a-z] [A-Z] [0-9 ][-_.: \n"
+       "Alle ongeldig tekens worden verwijderd\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Fout opgetreden tijdens het maken van de momentopname"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Momentopname gemaakt"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Succes"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+       "Een momentopname van zfs bestandssystem %(zfs_fs)s\n"
+       "genaamd %(valid_name)s\n"
+       "was gemaakt.\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+       "Momentopname vereist nu 2 argumenten :\n"
+       "- Het pad van de locatie waarvan een momentopname van gemaakt wordt.\n"
+       "- De zfs bestandssysteem dat met deze locatie correspondeert."
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Momentopname vereist nu administratieve privileges om te lopen. Je hebt niet "
+       "de nodige administratieve privileges. \n"
+       "\n"
+       "Raadpleeg uw systeembeheerder "
diff --git a/po/pl.gmo b/po/pl.gmo
new file mode 100644 (file)
index 0000000..7f86bae
Binary files /dev/null and b/po/pl.gmo differ
diff --git a/po/pl.po b/po/pl.po
new file mode 100644 (file)
index 0000000..0989f9d
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,538 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+       "Project-Id-Version: time-slider HEAD\n"
+       "Report-Msgid-Bugs-To: \n"
+       "POT-Creation-Date: 2009-12-07 22:37+0900\n"
+       "PO-Revision-Date: 2010-01-20 22:37+0900\n"
+       "Last-Translator: bartus11, geek85\n"
+       "Language-Team: Polish language team <i18n-discuss@opensolaris.org>\n"
+       "MIME-Version: 1.0\n"
+       "Content-Type: text/plain; charset=UTF-8\n"
+       "Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "Skonfiguruj system do automatycznego wykonywania migawek twoich danych "
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d migawki zostaną usunięte"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Podsumowanie</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "O_dznacz wszystkie"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Usuwam migawki"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Usuwanie migawki"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Usuwanie migawek..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Wyjdź kiedy skończysz. "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "System plików:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Nazwa:"
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Naciśnij Delete żeby kontynuować. "
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Wyszukuje migawki..."
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Wybierz migawki ZFS do usunięcia z listy poniżej."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Włącz Time Slider</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>System plików do Back Up</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Zaawansowane opcje"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "C_ustom:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr "Configuring Time Slider..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Dla zaawansowanych użytkowników"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Rekomendowane dla większości użytkowników"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Zmniejsz liczbę backupów kiedy przestrzeń przechowywania przekroczy:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Menadżer Time Slider"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "Time Slider regularnie robi kopię zapasową danych poprzez migawkę ZFS"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Wszystkie"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Usuwanie Migawki..."
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "możliwości systemu plików"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Zrób migawkę teraz"
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Zrób migawkę "
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "z nazwą:"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b> Wersja bieżąca</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "</b>Starsza Wersja</b>"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Kliknij dwa razy, żeby otworzyć plik"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Otwórz bieżącą wersję pliku"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Wyszukuje starsze wersje"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Time Slider File Version Explorer"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "porównaj"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "nazwa pliku"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-zamknij"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "ostatnia modyfikacja : "
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "nazwa:"
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "rozmiar: "
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr "Time Slider: Low Space Warning"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Uwaga: '%s' jest zapełniony"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr "The file system: '%s', is over %s%% full."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+       "System plików: '%s', jest zapełniony w %s%%.\n"
+       "Jako środek zaradczy, Time Slider usunął wszystkie migawki tego systemu plików.\n"
+       "Aby rozwiązać ten problem, usuń niepotrzebne pliki z '%s' lub dodaj przestrzeń dyskową"
+       "(zobacz dokumentację ZFS)"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Uwaga: '%s' jest prawie zapełniony"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr "The file system: '%s', exceeded %s%% of its total capacity"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+       "The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+       "measure, Time Slider has has destroyed most or all of its backups to prevent "
+       "the disk becoming full. To prevent this from happening again, delete any "
+       "unnecessary files on '%s', or add disk space (see ZFS documentation)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Pilne: '%s' jest prawie zapełniony!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+       "System plików: '%s', przekroczył %s%% jego całkowitej pojemności. Jako środek zaradczy Time Slider usunął kilka migawek tego systemu i w końcu usunie wszystkie, jeżeli wolne miejsce będzie nadal ubywać. Aby ta sytuacja się nie powtórzyła, usuń niepotrzebne pliki z '%s' lub dodaj przestrzeń dyskową (zobacz dokumentację ZFS)"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Ostrzeżenie: '%s' staje się pełny"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+       "'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+       "destroyed some recent backups, and will destroy more as capacity continues "
+       "to diminish.\n"
+       "To prevent this from happening again, delete any unnecessary files on '%s', "
+       "or add disk space (see ZFS documentation).\n"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr "Details..."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Legacy"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Punkt montowania"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Nazwa systemu plików"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Nazwa migawki"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Czas utworzenia"
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Wszystkie"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Miesięcznie"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Tygodniowo"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Dziennie"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "Co godzinę"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Co 15 minut"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "Migawka nie może byś usunięta"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+       "%s posiada jeden lub więcej zależnych klonów i nie zostanie usunięty. Aby usunąc tą"
+       "migawkę, najpierw usuń wszystkie datasety i migawki sklonowane z tej migawki."
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 migawka będzie usunięta"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Nie można odczytać niektórych migawek"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Nie można usunąć niektórych migawek"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Niewystarczające uprawnienia"
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Usunięcie migawki wymaga uprawnień administratora. Nie masz przypisanych niezbędnych uprawnień administracyjnych.\n"
+       "\n"
+       "Skontaktuj się ze swoim administratorem systemu. "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr "Hint"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+       "Installing the optional meld package will enhance the file comparison "
+       "visualization"
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Niepoprawna liczba argumentów."
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+       "Wersja przeglądarki potrzebuje 2 argumenty :\n"
+       "-Ścieżkę do głównego katalogu migawek.\n"
+       "Nazwę pliku do zbadania."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Wybierz"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Błąd usługi menadżera migawek"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+       "Menadżer migawek został wyłączony z powodu problemu z zależnościami. Następujące problemy z zależnościami zostały wykryte:\n"
+       "\n"
+       "%s\n"
+       "\n"
+       "Wykonaj \"svcs -xv\" w terminalu aby uzyskać więcej informacji na temat tych problemów."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Błąd menadżera migawek"
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "Menadżer migawek napotkał problem i został wyłączony dopóki problem nie zostanie rozwiązany.\n"
+       "\n"
+       "Zobacz stronę manuala svcs(1) aby uzyskać więcej informacji."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+       "Menadżer migawek nie jest zainstalowany na tym systemie.\n"
+       "\n"
+       "Zobacz stronę manuala svcs(1) aby uzyskać więcej informacji."
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Usługa menadżera migawek wymaga uprawnień administratora do działania. Nie masz przypisanych niezbędnych uprawnień administracyjnych.\n"
+       "\n"
+       "Skontaktuj się ze swoim administratorem systemu. "
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Niedozwolone znaki w nazwie migawki"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Błąd"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+       "Dozwolone znaki w nazwie migawki :\n"
+       "[a-z][A-Z][0-9][-_.:\n"
+       "Wszystkie inne znaki zostaną usunięte\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Wystąpił błąd podczas tworzenia migawki"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Migawka została utworzona"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Powodzenie"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+       "Utworzono migawkę systemu plików zfs %(zfs_fs)s\n"
+       "o nazwie %(valid_name)s\n"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+       "Migawka Teraz potrzebuje 2 argumenty :\n"
+       "- Ścieszkę dostępu do katalogu z którego migawka ma zostać utworzona.\n"
+       "- System plików zfs powiązany z katalogiem."
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+       "Migawka Teraz wymaga uprawnień administratora do działania. Nie masz przypisanych niezbędnych uprawnień administracyjnych.\n"
+       "\n"
+       "Skontaktuj się ze swoim administratorem systemu. "
diff --git a/po/pt_BR.gmo b/po/pt_BR.gmo
new file mode 100644 (file)
index 0000000..4f98331
Binary files /dev/null and b/po/pt_BR.gmo differ
diff --git a/po/pt_BR.po b/po/pt_BR.po
new file mode 100644 (file)
index 0000000..2704c9c
--- /dev/null
@@ -0,0 +1,863 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2009-02-16 18:49+0100\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "Configurar o sistema para realizar instantâneos automáticos dos dados"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "Barra deslizante de tempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d instantâneos serão excluídos."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>Resumo</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "Cancelar s_eleção de todos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "Excluir instantâneos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "Excluindo instantâneos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "Excluindo instantâneos..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "Sair ao concluir. "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "Sistema de arquivos:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "Nome:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "Pressione Delete para continuar."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "Explorando instantâneos..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "Selecione  na lista abaixo os instantâneos do ZFS que serão excluídos."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>Ativar a barra deslizante de tempo</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>Sistemas de arquivos dos quais fazer backup</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "Opções avançadas"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "P_ersonalizado:"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "Para usuários avançados"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "Recomendado para a maioria dos usuários"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "Reduzir os backups quando o espaço de armazenamento for excedido:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "Gerenciador da barra deslizante de tempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+"A barra deslizante de tempo faz backup de dados regularmente realizando "
+"instantâneos programados do ZFS"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "_Todos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "_Excluir instantâneos..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "da capacidade do sistema de arquivos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "Efetuar um instantâneo agora"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "Efetuar um instantâneo de "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "com o nome:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>Versão atual</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>Versões mais antigas</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "Clicar duas vezes para abrir o arquivo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "Abrir a versão atual do arquivo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "Explorando versões mais antigas"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "Explorador de versões de arquivos da barra deslizante de tempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "comparar"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "nome de arquivo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "última modificação: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "nome :"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "tamanho : "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "Gerenciador da barra deslizante de tempo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "Emergência: '%s' está cheio!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"O sistema de arquivos: '%s' está %s%% acima.\n"
+"Como medida de emergência, a barra deslizante de tempo eliminou todos os "
+"backups.\n"
+"Para corrigir este problema, exclua os arquivos desnecessários de '%s' ou "
+"adicione espaço em disco (consulte a documentação do ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "Emergência: '%s' está quase cheio!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"O sistema de arquivos: '%s' excedeu %s%% da capacidade total. Como medida de "
+"emergência, a barra deslizante de tempo eliminou a maioria ou todos os "
+"backups para evitar que o disco ficasse cheio. Para evitar que isso acorra "
+"novamente, exclua os arquivos desnecessários de '%s' ou adicione espaço em "
+"disco (consulte a documentação do ZFS).\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "Urgente: '%s' está quase cheio!"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"O sistema de arquivos: '%s' excedeu %s%% da capacidade total. Como medida de "
+"reforço, a barra deslizante de tempo eliminou alguns backups e eliminará "
+"mais, eventualmente todos, caso a capacidade continue diminuindo.\n"
+"Para evitar que isso acorra novamente, exclua os arquivos desnecessários de "
+"'%s' ou adicione espaço em disco (consulte a documentação do ZFS)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "Aviso: '%s' está ficando cheio"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"'%s' excedeu %s%% da capacidade total. Para corrigir esse problema, a barra "
+"deslizante de tempo eliminou alguns backups recentes e eliminará mais caso a "
+"capacidade continue diminuindo.\n"
+"Para evitar que isso acorra novamente, exclua os arquivos desnecessários de "
+"'%s' ou adicione espaço em disco (consulte a documentação do ZFS)."
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "Legado"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "Ponto de montagem"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "Nome do sistema de arquivos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "Nome do instantâneo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "Hora de criação"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "Todos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "Mensalmente"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "Semanalmente"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "Diariamente"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "De hora em hora"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "Cada 15 minutos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "O instantâneo não pode ser excluído"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s tem um ou mais clones dependentes e não será excluído. Para excluir este "
+"instantâneo, exclua primeiro todos os conjuntos de dados e instantâneos "
+"clonados deste instantâneo."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 instantâneo será excluído."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "Alguns instantâneos não podem ser lidos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "Alguns instantâneos não podem ser excluídos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "Privilégios insuficientes"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"A exclusão de instantâneos requer privilégios administrativos para ser "
+"executada. Os privilégios administrativos necessários não lhe foram "
+"atribuídos.\n"
+"\n"
+"Consulte o administrador de sistema "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "Total de argumentos inválidos."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"O explorador de versão requer 2 argumentos :\n"
+"- O caminho do diretório raiz do instantâneo.\n"
+"- O nome de arquivo para exploração."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "Selecione"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "Erro de dependência do serviço do gerenciador de instantâneos"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"O serviço do gerenciador de instantâneos foi colocado off-line devido a um "
+"problema de dependência. Foram encontrados os seguintes problemas de "
+"dependência:\n"
+"\n"
+"%s\n"
+"\n"
+"Execute \"svcs -xv\" de um prompt de comando para obter mais informações "
+"sobre estes problemas de dependência."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "Erro do serviço do gerenciador de instantâneos"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"O serviço do gerenciador de instantâneos encontrou um problema e ficará "
+"desativado até que o problema seja corrigido.\n"
+"\n"
+"Para obter mais informações, consulte a página do manual svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"O serviço do gerenciador de instantâneos parece não estar instalado neste "
+"sistema.\n"
+"\n"
+"Para obter mais informações, consulte a página do manual svcs(1)."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"O serviço do gerenciador de instantâneos requer privilégios administrativos "
+"para ser executado. Os privilégios administrativos necessários não lhe foram "
+"atribuídos.\n"
+"\n"
+"Consulte o administrador de sistema "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "Caracteres inválidos no nome do instantâneo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "Erro"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"O caracteres permitidos em nomes de instantâneos são :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"Todos os caracteres inválidos serão removidos\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "Erro ocorrido durante a criação do instantâneo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "Instantâneo criado com êxito"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "Êxito"
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"Um instantâneo do sistema de arquivos zfs %(zfs_fs)s\n"
+"denominado %(valid_name)s\n"
+"foi criado.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"Efetuar instantâneo agora requer 2 argumentos :\n"
+"- O caminho do diretório do qual será efetuado o instantâneo.\n"
+"- O sistema de arquivos zfs correspondente a este diretório."
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"Efetuar instantâneo agora requer privilégios administrativos para ser "
+"executado. Os privilégios administrativos necessários não lhe foram "
+"atribuídos.\n"
+"\n"
+"Consulte o administrador de sistema "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid ""
+#~ "A snapshot of zfs filesystem %s\n"
+#~ "named %s\n"
+#~ "has been created.\n"
+#~ msgstr ""
+#~ "Um instantâneo do sistema de arquivos zfs %s\n"
+#~ "denominado %s\n"
+#~ "foi criado.\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr ""
+#~ "Eliminar backups mais antigos quando o espaço de armazenamento for "
+#~ "excedido:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "da capacidade do pool"
diff --git a/po/ru.gmo b/po/ru.gmo
new file mode 100644 (file)
index 0000000..878a5b0
Binary files /dev/null and b/po/ru.gmo differ
diff --git a/po/ru.po b/po/ru.po
new file mode 100644 (file)
index 0000000..19fdbba
--- /dev/null
+++ b/po/ru.po
@@ -0,0 +1,489 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2008-10-01 21:35+0900\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr ""
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr ""
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
diff --git a/po/sv.gmo b/po/sv.gmo
new file mode 100644 (file)
index 0000000..878a5b0
Binary files /dev/null and b/po/sv.gmo differ
diff --git a/po/sv.po b/po/sv.po
new file mode 100644 (file)
index 0000000..19fdbba
--- /dev/null
+++ b/po/sv.po
@@ -0,0 +1,489 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2008-10-01 21:35+0900\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr ""
+
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr ""
+
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+msgid "Time Slider: Low Space Warning"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr ""
+
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
diff --git a/po/zh_CN.gmo b/po/zh_CN.gmo
new file mode 100644 (file)
index 0000000..27d89a5
Binary files /dev/null and b/po/zh_CN.gmo differ
diff --git a/po/zh_CN.po b/po/zh_CN.po
new file mode 100644 (file)
index 0000000..7a6206d
--- /dev/null
@@ -0,0 +1,842 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2008-10-01 21:35+0900\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "将系统配置为自动捕获数据的快照"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "时间滑块"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "%d 个快照将被删除。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>摘要</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "取消全选(_E)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "删除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "正在删除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "正在删除快照..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "完成后退出。 "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "文件系统:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "名称:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "按“删除”以继续。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "正在扫描快照..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "从以下列表中选择要删除的 ZFS 快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>启用时间滑块</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>要备份的文件系统</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "高级选项"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "自定义(_U):"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "适用于高级用户"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "建议大多数用户采用"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "当存储空间使用率超过以下值时减少备份:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "时间滑块管理器"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "时间滑块通过定时拍摄 ZFS 快照来对数据进行定期备份"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "全部(_A)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "删除快照(_D)..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "关于文件系统容量"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "立即捕获快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "捕获以下项的快照 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "名称为:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>当前版本</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>早期版本</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "双击以打开文件"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "打开文件的当前版本"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "正在扫描早期版本"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "时间滑块文件版本资源管理器"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "比较"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "文件名"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "上次修改时间: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "名称:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "大小: "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "时间滑块管理器"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "紧急:'%s' 已满!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"文件系统 '%s' 的占满程度已超过 %s%%。\n"
+"作为一种紧急措施,时间滑块已销毁了它的所有备份。\n"
+"要修复此问题,请删除 '%s' 上所有不必要的文件,或增加磁盘空间(请参见 ZFS 文"
+"档)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "紧急:'%s' 几乎已满!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"文件系统 '%s' 已超过其总容量的 %s%%。作为一种紧急措施,时间滑块已销毁了它的大"
+"部分或所有备份,以防止磁盘被占满。要防止这种情况再次发生,请删除 '%s' 上所有"
+"不必要的文件,或增加磁盘空间(请参见 ZFS 文档)。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "紧急:'%s' 几乎已满!"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"文件系统 '%s' 已超过其总容量的 %s%%。作为一种补救措施,时间滑块已销毁了一些备"
+"份,并随着容量的不断减小,将销毁更多备份,最终销毁所有备份。\n"
+"要防止这种情况再次发生,请删除 '%s' 上所有不必要的文件,或增加磁盘空间(请参"
+"见 ZFS 文档)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "警告:'%s' 即将被占满"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"'%s' 已超过其总容量的 %s%%。为了修复此问题,时间滑块已销毁了一些最新的备份,"
+"并随着容量的不断减小,将销毁更多备份。\n"
+"要防止这种情况再次发生,请删除 '%s' 上所有不必要的文件,或增加磁盘空间(请参"
+"见 ZFS 文档)。"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "传统"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "挂载点"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "文件系统名称"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "快照名称"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "创建时间"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "全部"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "每月"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "每周"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "每天"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "每小时"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "每 1/4 小时"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "无法删除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s 具有一个或多个相关克隆,不会被删除。要删除此快照,请首先删除从此快照克隆的"
+"所有数据集和快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "1 个快照将被删除。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "无法读取某些快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "无法删除某些快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "权限不足"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"需要有管理权限才能删除快照。没有为您指定必要的管理权限。\n"
+"\n"
+"请咨询您的系统管理员 "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "参数计数无效。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"版本资源管理器需要 2 个参数:\n"
+"- 根快照目录的路径。\n"
+"- 要浏览的文件名。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "选择"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "快照管理器服务相关性错误"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"由于相关性问题,快照管理器服务已被置于脱机。已发现以下相关性问题:\n"
+"\n"
+"%s\n"
+"\n"
+"有关这些相关性问题的更多信息,请从命令提示符下运行 \"svcs -xv\"。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "快照管理器服务错误"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"该快照管理器服务出现了问题,并已被禁用,直至问题得以修复。\n"
+"\n"
+"有关更多信息,请参见 svcs(1) 手册页。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"该快照管理器服务似乎没有安装在此系统上。\n"
+"\n"
+"有关更多信息,请参见 svcs(1) 手册页。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"该快照管理器服务需要管理权限才能运行。没有为您指定必要的管理权限。\n"
+"\n"
+"请咨询您的系统管理员 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "快照名称中存在无效字符"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "错误"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"快照名称中允许使用的字符为:\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"所有无效字符都会被删除\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "创建快照时发生错误"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "已成功创建快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "成功"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+# msgid ""
+# "A snapshot of zfs filesystem %s\n"
+# "named %s\n"
+# "has been created.\n"
+# msgstr ""
+# "已创建了一个名为 %1$s 的 zfs 文件\n"
+# "系统 %2$s\n"
+# "的快照。\n"
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"已创建了一个名为 %(valid_name)s 的 zfs 文件\n"
+"系统 %(zfs_fs)s\n"
+"的快照。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"立即进行快照需要 2 个参数:\n"
+"- 要进行快照的目录的路径。\n"
+"- 与此目录相对应的 zfs 文件系统。"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"需要有管理权限才能立即进行快照。没有为您指定必要的管理权限。\n"
+"\n"
+"请咨询您的系统管理员 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr "当存储空间使用率超过以下值时销毁最旧的备份:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "池容量"
diff --git a/po/zh_HK.gmo b/po/zh_HK.gmo
new file mode 100644 (file)
index 0000000..641d673
Binary files /dev/null and b/po/zh_HK.gmo differ
diff --git a/po/zh_HK.po b/po/zh_HK.po
new file mode 100644 (file)
index 0000000..5e0963e
--- /dev/null
@@ -0,0 +1,842 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2008-10-01 21:35+0900\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "將系統配置為自動對資料執行快照"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "時間滑動軸"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "將刪除 %d 個快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>摘要</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "全部取消選取(_E)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "刪除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "正在刪除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "正在刪除快照..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "完成後結束。 "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "檔案系統:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "名稱:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "請按下 [刪除] 繼續。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "正在掃描快照..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "請從以下清單中選取要刪除的 ZFS 快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>啟用時間調整器</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>要備份的檔案系統</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "進階選項"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "自訂(_U):"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "適用於進階使用者"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "建議大多數使用者採用"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "當儲存空間使用量超過下列大小時減少備份:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "時間滑動軸管理員"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "時間調整器會透過擷取定時的 ZFS 快照,定期備份資料"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "全部(_A)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "刪除快照(_D)..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "檔案系統容量"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "立即擷取快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "擷取以下項目的快照 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "名稱為:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>目前版本</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>較舊版本</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "連按兩下以開啟檔案"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "開啟目前版本的檔案"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "掃描較舊版本"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "時間滑動軸檔案版本檔案總管"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "對比"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "檔案名稱"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "上次修改時間: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "名稱:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "大小: "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "時間滑動軸管理員"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "緊急:「%s」已滿!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"檔案系統:「%s」已超過 %s%%。\n"
+"時間調整器所採取的緊急措施是銷毀其所有的備份。\n"
+"若要修正此問題,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文"
+"件)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "緊急:「%s」幾乎已滿!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"檔案系統:「%s」超過了其總容量的 %s%%。時間調整器所採取的緊急措施是銷毀大部分"
+"或其所有的備份,以防止磁碟變滿。若要避免再次發生這種情形,請刪除「%s」上所有"
+"不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文件)。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "緊要:「%s」幾乎已滿!"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"檔案系統:「%s」超過了其總容量的 %s%%。時間調整器所採取的補救措施是銷毀部分備"
+"份,並將會銷毀更多備份,而最終會銷毀所有備份,因為容量一直不斷減少。\n"
+"若要避免再次發生這種情形,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請"
+"參閱 ZFS 文件)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "警告:「%s」快要滿了"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"「%s」已超過其總容量的 %s%%。為修正此問題,時間調整器已銷毀部分最近的備份,並"
+"將會銷毀更多備份,因為容量一直不斷減少。\n"
+"若要避免再次發生此情形,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參"
+"閱 ZFS 文件)。"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "原來的"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "掛載點"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "檔案系統名稱"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "快照名稱"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "建立時間"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "全部"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "每月"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "每週"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "每天"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "每小時"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "每 1/4 小時"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "無法刪除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s 具有一個或多個附屬複製,不會被刪除。要刪除此快照,請先刪除從此快照複製的所"
+"有資料集和快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "將刪除 1 個快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "無法讀取某些快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "無法刪除某些快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "權限不足"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"需要具有管理權限才能執行 [快照刪除] 操作。沒有為您指定所需的管理權限。\n"
+"\n"
+"請諮詢系統管理員 "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "引數計數無效。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"版本檔案總管需要 2 個引數:\n"
+"- 快照根目錄的路徑。\n"
+"- 要瀏覽的檔案名稱。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "選取"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "快照管理員服務相依性錯誤"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"由於相依性問題,已將快照管理員服務置為離線。發現以下相依性問題:\n"
+"\n"
+"%s\n"
+"\n"
+"請從指令提示符號下執行「svcs –xv」,以取得有關這些相依性問題的更多資訊。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "快照管理員服務錯誤"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"快照管理員服務遇到了問題,而且在問題修正之前都處於停用狀態。\n"
+"\n"
+"請參閱「svcs(1) 線上手冊」,以取得更多資訊。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"快照管理員服務似乎並未安裝於此系統上。\n"
+"\n"
+"請參閱「svcs(1) 線上手冊」,以取得更多資訊。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"快照管理員服務需要有管理權限才能執行。您尚未被指定必要的管理權限。\n"
+"\n"
+"請洽詢您的系統管理員 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "快照名稱中有無效字元"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "錯誤"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"允許用於快照名稱的字元如下:\n"
+"[a-z]、[A-Z]、[0-9]、[、-、_、.、:\n"
+"將移除所有無效字元\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "建立快照時發生錯誤"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "已成功建立快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "成功"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+# msgid ""
+# "A snapshot of zfs filesystem %s\n"
+# "named %s\n"
+# "has been created.\n"
+# msgstr ""
+# "已建立一個名為 %2$s 的\n"
+# " zfs 檔案系統 %1$s\n"
+# "的快照。\n"
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"已建立一個名為 %(valid_name)s 的\n"
+" zfs 檔案系統 %(zfs_fs)s\n"
+"的快照。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"[立即擷取快照] 需要 2 個引數:\n"
+"- 要進行快照擷取的目錄的路徑。\n"
+"- 與此目錄對應的 zfs 檔案系統。"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"需要具有管理權限才能執行 [立即擷取快照] 操作。沒有為您指定所需的管理權限。\n"
+"\n"
+"請諮詢系統管理員 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr "當儲存空間使用量超過下列大小時銷毀最舊的備份:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "池容量"
diff --git a/po/zh_TW.gmo b/po/zh_TW.gmo
new file mode 100644 (file)
index 0000000..641d673
Binary files /dev/null and b/po/zh_TW.gmo differ
diff --git a/po/zh_TW.po b/po/zh_TW.po
new file mode 100644 (file)
index 0000000..5e0963e
--- /dev/null
@@ -0,0 +1,842 @@
+# Copyright (C) 2009 Sun Microsystems, Inc
+# This file is distributed under the same license as the time-slider package.
+#
+# Desktop Discuss <desktop-discuss@opensolaris.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: time-slider HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-12-07 22:37+0900\n"
+"PO-Revision-Date: 2008-10-01 21:35+0900\n"
+"Last-Translator: desktop-discuss@opensolaris.org\n"
+"Language-Team: desktop-discuss@opensolaris.org\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:1
+msgid "Configure the system to take automatic snapshots of your data"
+msgstr "將系統配置為自動對資料執行快照"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../data/time-slider.desktop.in.h:2
+#: ../usr/share/time-slider/lib/time_slider/applet.py:185
+msgid "Time Slider"
+msgstr "時間滑動軸"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:2
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:242
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:342
+#, no-c-format, python-format
+msgid "%d snapshots will be deleted."
+msgstr "將刪除 %d 個快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:3
+msgid "<b>Summary</b>"
+msgstr "<b>摘要</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:4
+msgid "D_eselect All"
+msgstr "全部取消選取(_E)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:5
+msgid "Delete Snapshots"
+msgstr "刪除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:6
+msgid "Deleting Snapshots"
+msgstr "正在刪除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:7
+msgid "Deleting snapshots..."
+msgstr "正在刪除快照..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:8
+msgid "Exit when done. "
+msgstr "完成後結束。 "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:9
+msgid "File System:"
+msgstr "檔案系統:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:10
+msgid "Name:"
+msgstr "名稱:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:11
+msgid "Press Delete to continue."
+msgstr "請按下 [刪除] 繼續。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:12
+msgid "Scanning snapshots..."
+msgstr "正在掃描快照..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-delete.glade.h:13
+msgid "Select ZFS snapshots to delete from the list below."
+msgstr "請從以下清單中選取要刪除的 ZFS 快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:1
+msgid "<b>Enable Time Slider</b>"
+msgstr "<b>啟用時間調整器</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:2
+msgid "<b>File Systems To Back Up</b>"
+msgstr "<b>要備份的檔案系統</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:3
+msgid "Advanced Options"
+msgstr "進階選項"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:4
+msgid "C_ustom:"
+msgstr "自訂(_U):"
+
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:5
+msgid "Configuring Time Slider..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:6
+msgid "For advanced users"
+msgstr "適用於進階使用者"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:7
+msgid "Recommended for most users"
+msgstr "建議大多數使用者採用"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:8
+msgid "Reduce backups when storage space usage exceeds:"
+msgstr "當儲存空間使用量超過下列大小時減少備份:"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:9
+msgid "Time Slider Manager"
+msgstr "時間滑動軸管理員"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:10
+msgid "Time Slider backs up data regularly by taking timed ZFS Snapshots"
+msgstr "時間調整器會透過擷取定時的 ZFS 快照,定期備份資料"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:11
+msgid "_All"
+msgstr "全部(_A)"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:12
+msgid "_Delete Snapshots..."
+msgstr "刪除快照(_D)..."
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-setup.glade.h:13
+msgid "of file system capacity"
+msgstr "檔案系統容量"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:1
+msgid "Take a snapshot now"
+msgstr "立即擷取快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:2
+msgid "Take a snapshot of "
+msgstr "擷取以下項目的快照 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-snapshot.glade.h:3
+msgid "with the name :"
+msgstr "名稱為:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:1
+msgid "10 Mo"
+msgstr "10 Mo"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:2
+msgid "19/01/09"
+msgstr "19/01/09"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:3
+msgid "<b>Current Version</b>"
+msgstr "<b>目前版本</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:4
+msgid "<b>Older Versions</b>"
+msgstr "<b>較舊版本</b>"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:5
+msgid "Double click to open the file"
+msgstr "連按兩下以開啟檔案"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:6
+msgid "Open the current version of the file"
+msgstr "開啟目前版本的檔案"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:7
+msgid "Scanning for older versions"
+msgstr "掃描較舊版本"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:8
+msgid "Time Slider File Version Explorer"
+msgstr "時間滑動軸檔案版本檔案總管"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:9
+msgid "compare"
+msgstr "對比"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:10
+msgid "filename"
+msgstr "檔案名稱"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:11
+msgid "gtk-close"
+msgstr "gtk-close"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:12
+msgid "last modified : "
+msgstr "上次修改時間: "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:13
+msgid "name :"
+msgstr "名稱:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/glade/time-slider-version.glade.h:14
+msgid "size : "
+msgstr "大小: "
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:57
+#, fuzzy
+msgid "Time Slider: Low Space Warning"
+msgstr "時間滑動軸管理員"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:75
+#, python-format
+msgid "Emergency: '%s' is full!"
+msgstr "緊急:「%s」已滿!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:76
+#, python-format
+msgid "The file system: '%s', is over %s%% full."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:78
+#, python-format
+msgid ""
+"The file system: '%s', is over %s%% full.\n"
+"As an emergency measure, Time Slider has destroyed all of its backups.\n"
+"To fix this problem, delete any unnecessary files on '%s', or add disk space "
+"(see ZFS documentation)."
+msgstr ""
+"檔案系統:「%s」已超過 %s%%。\n"
+"時間調整器所採取的緊急措施是銷毀其所有的備份。\n"
+"若要修正此問題,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文"
+"件)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:87
+#, python-format
+msgid "Emergency: '%s' is almost full!"
+msgstr "緊急:「%s」幾乎已滿!"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:88
+#: ../usr/share/time-slider/lib/time_slider/applet.py:103
+#: ../usr/share/time-slider/lib/time_slider/applet.py:118
+#, python-format
+msgid "The file system: '%s', exceeded %s%% of its total capacity"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:91
+#, fuzzy, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As an emerency "
+"measure, Time Slider has has destroyed most or all of its backups to prevent "
+"the disk becoming full. To prevent this from happening again, delete any "
+"unnecessary files on '%s', or add disk space (see ZFS documentation)."
+msgstr ""
+"檔案系統:「%s」超過了其總容量的 %s%%。時間調整器所採取的緊急措施是銷毀大部分"
+"或其所有的備份,以防止磁碟變滿。若要避免再次發生這種情形,請刪除「%s」上所有"
+"不必要的檔案,或增加磁碟空間 (請參閱 ZFS 文件)。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:102
+#, python-format
+msgid "Urgent: '%s' is almost full!"
+msgstr "緊要:「%s」幾乎已滿!"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:106
+#, python-format
+msgid ""
+"The file system: '%s', exceeded %s%% of its total capacity. As a remedial "
+"measure, Time Slider has destroyed some backups, and will destroy more, "
+"eventually all, as capacity continues to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation)."
+msgstr ""
+"檔案系統:「%s」超過了其總容量的 %s%%。時間調整器所採取的補救措施是銷毀部分備"
+"份,並將會銷毀更多備份,而最終會銷毀所有備份,因為容量一直不斷減少。\n"
+"若要避免再次發生這種情形,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請"
+"參閱 ZFS 文件)。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:117
+#, python-format
+msgid "Warning: '%s' is getting full"
+msgstr "警告:「%s」快要滿了"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/applet.py:121
+#, fuzzy, python-format
+msgid ""
+"'%s' exceeded %s%% of its total capacity. To fix this, Time Slider has "
+"destroyed some recent backups, and will destroy more as capacity continues "
+"to diminish.\n"
+"To prevent this from happening again, delete any unnecessary files on '%s', "
+"or add disk space (see ZFS documentation).\n"
+msgstr ""
+"「%s」已超過其總容量的 %s%%。為修正此問題,時間調整器已銷毀部分最近的備份,並"
+"將會銷毀更多備份,因為容量一直不斷減少。\n"
+"若要避免再次發生此情形,請刪除「%s」上所有不必要的檔案,或增加磁碟空間 (請參"
+"閱 ZFS 文件)。"
+
+#: ../usr/share/time-slider/lib/time_slider/applet.py:137
+msgid "Details..."
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:116
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:306
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:106
+msgid "Legacy"
+msgstr "原來的"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:147
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:131
+msgid "Mount Point"
+msgstr "掛載點"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:155
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:134
+msgid "File System Name"
+msgstr "檔案系統名稱"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:163
+msgid "Snapshot Name"
+msgstr "快照名稱"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:171
+msgid "Creation Time"
+msgstr "建立時間"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#. Note to developers.
+#. The second element is for internal matching and should not
+#. be i18ned under any circumstances.
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:185
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:198
+msgid "All"
+msgstr "全部"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:199
+msgid "Monthly"
+msgstr "每月"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:200
+msgid "Weekly"
+msgstr "每週"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:201
+msgid "Daily"
+msgstr "每天"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:202
+msgid "Hourly"
+msgstr "每小時"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:203
+msgid "1/4 Hourly"
+msgstr "每 1/4 小時"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:223
+msgid "Snapshot can not be deleted"
+msgstr "無法刪除快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:224
+#, python-format
+msgid ""
+"%s has one or more dependent clones and will not be deleted. To delete this "
+"snapshot, first delete all datasets and snapshots cloned from this snapshot."
+msgstr ""
+"%s 具有一個或多個附屬複製,不會被刪除。要刪除此快照,請先刪除從此快照複製的所"
+"有資料集和快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:240
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:340
+msgid "1 snapshot will be deleted."
+msgstr "將刪除 1 個快照。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:381
+msgid "Some snapshots could not be read"
+msgstr "無法讀取某些快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:405
+msgid "Some snapshots could not be deleted"
+msgstr "無法刪除某些快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:539
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:422
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:215
+msgid "Insufficient Priviliges"
+msgstr "權限不足"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/deletegui.py:540
+msgid ""
+"Snapshot deletion requires administrative privileges to run. You have not "
+"been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"需要具有管理權限才能執行 [快照刪除] 操作。沒有為您指定所需的管理權限。\n"
+"\n"
+"請諮詢系統管理員 "
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:246
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:247
+msgid "Hint"
+msgstr ""
+
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:248
+msgid ""
+"Installing the optional meld package will enhance the file comparison "
+"visualization"
+msgstr ""
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:316
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:179
+msgid "Invalid arguments count."
+msgstr "引數計數無效。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/fileversion.py:318
+msgid ""
+"Version explorer requires 2 arguments :\n"
+"- The path of the root snapshot directory.\n"
+"- The filename to explore."
+msgstr ""
+"版本檔案總管需要 2 個引數:\n"
+"- 快照根目錄的路徑。\n"
+"- 要瀏覽的檔案名稱。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:128
+msgid "Select"
+msgstr "選取"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:154
+msgid "Snapshot manager service dependency error"
+msgstr "快照管理員服務相依性錯誤"
+
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:155
+#, python-format
+msgid ""
+"The snapshot manager service has been placed offline due to a dependency "
+"problem. The following dependency problems were found:\n"
+"\n"
+"%s\n"
+"\n"
+"Run \"svcs -xv\" from a command prompt for more information about these "
+"dependency problems."
+msgstr ""
+"由於相依性問題,已將快照管理員服務置為離線。發現以下相依性問題:\n"
+"\n"
+"%s\n"
+"\n"
+"請從指令提示符號下執行「svcs –xv」,以取得有關這些相依性問題的更多資訊。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:169
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:186
+msgid "Snapshot manager service error"
+msgstr "快照管理員服務錯誤"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:170
+msgid ""
+"The snapshot manager service has encountered a problem and has been disabled "
+"until the problem is fixed.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"快照管理員服務遇到了問題,而且在問題修正之前都處於停用狀態。\n"
+"\n"
+"請參閱「svcs(1) 線上手冊」,以取得更多資訊。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:187
+msgid ""
+"The snapshot manager service does not appear to be installed on this "
+"system.\n"
+"\n"
+"See the svcs(1) man page for more information."
+msgstr ""
+"快照管理員服務似乎並未安裝於此系統上。\n"
+"\n"
+"請參閱「svcs(1) 線上手冊」,以取得更多資訊。"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/setupgui.py:423
+msgid ""
+"The snapshot manager service requires administrative privileges to run. You "
+"have not been assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"快照管理員服務需要有管理權限才能執行。您尚未被指定必要的管理權限。\n"
+"\n"
+"請洽詢您的系統管理員 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:116
+msgid "Invalid characters in snapshot name"
+msgstr "快照名稱中有無效字元"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:117
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:147
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:180
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:216
+msgid "Error"
+msgstr "錯誤"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:118
+msgid ""
+"Allowed characters for snapshot names are :\n"
+"[a-z][A-Z][0-9][-_.:\n"
+"All invalid characters will be removed\n"
+msgstr ""
+"允許用於快照名稱的字元如下:\n"
+"[a-z]、[A-Z]、[0-9]、[、-、_、.、:\n"
+"將移除所有無效字元\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:146
+msgid "Error occured while creating the snapshot"
+msgstr "建立快照時發生錯誤"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:155
+msgid "Snapshot created successfully"
+msgstr "已成功建立快照"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:156
+msgid "Success"
+msgstr "成功"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+# msgid ""
+# "A snapshot of zfs filesystem %s\n"
+# "named %s\n"
+# "has been created.\n"
+# msgstr ""
+# "已建立一個名為 %2$s 的\n"
+# " zfs 檔案系統 %1$s\n"
+# "的快照。\n"
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:157
+#, python-format
+msgid ""
+"A snapshot of zfs filesystem %(zfs_fs)s\n"
+"named %(valid_name)s\n"
+"has been created.\n"
+msgstr ""
+"已建立一個名為 %(valid_name)s 的\n"
+" zfs 檔案系統 %(zfs_fs)s\n"
+"的快照。\n"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:181
+msgid ""
+"Snapshot Now requires 2 arguments :\n"
+"- The path of the directory to be snapshotted.\n"
+"- The zfs filesystem corresponding to this directory."
+msgstr ""
+"[立即擷取快照] 需要 2 個引數:\n"
+"- 要進行快照擷取的目錄的路徑。\n"
+"- 與此目錄對應的 zfs 檔案系統。"
+
+#
+# COMMUNITY MESSAGE
+# COMMUNITY FUZZY
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#: ../usr/share/time-slider/lib/time_slider/snapnowui.py:217
+msgid ""
+"Snapshot Now requires administrative privileges to run. You have not been "
+"assigned the necessaryadministrative priviliges.\n"
+"\n"
+"Consult your system administrator "
+msgstr ""
+"需要具有管理權限才能執行 [立即擷取快照] 操作。沒有為您指定所需的管理權限。\n"
+"\n"
+"請諮詢系統管理員 "
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "Destroy oldest backups when storage space usage exceeds:"
+#~ msgstr "當儲存空間使用量超過下列大小時銷毀最舊的備份:"
+
+# COMMUNITY UNTRANS
+# SUN CHANGED MESSAGE
+# SUN LING REVIEWED
+#~ msgid "of pool capacity"
+#~ msgstr "池容量"
diff --git a/py-compile.py b/py-compile.py
new file mode 100644 (file)
index 0000000..9be615a
--- /dev/null
@@ -0,0 +1,7 @@
+import compileall
+import os
+
+destdir = os.getenv("DESTDIR", ".")
+dir = destdir + "/usr"
+compileall.compile_dir(destdir, force=1)
+
diff --git a/usr/bin/time-slider-setup b/usr/bin/time-slider-setup
new file mode 100755 (executable)
index 0000000..d64f0ac
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env python2.6
+
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, 'share',
+                        'time-slider', 'lib'))
+
+from time_slider.setupgui import main
+
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
+
diff --git a/usr/lib/time-slider-delete b/usr/lib/time-slider-delete
new file mode 100755 (executable)
index 0000000..cc55e44
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env python2.6
+
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, 'share',
+                        'time-slider', 'lib'))
+
+from time_slider.deletegui import main
+
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
+
diff --git a/usr/lib/time-slider-notify b/usr/lib/time-slider-notify
new file mode 100755 (executable)
index 0000000..bd503a0
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/env python2.6
+
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, 'share',
+                        'time-slider', 'lib'))
+
+from time_slider.applet import main
+
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
diff --git a/usr/lib/time-slider-snapshot b/usr/lib/time-slider-snapshot
new file mode 100755 (executable)
index 0000000..33406ae
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env python2.6
+
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, 'share',
+                        'time-slider', 'lib'))
+
+from time_slider.snapnowui import main
+
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
+
diff --git a/usr/lib/time-slider-version b/usr/lib/time-slider-version
new file mode 100755 (executable)
index 0000000..aca093b
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/env python2.6
+
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, 'share',
+                        'time-slider', 'lib'))
+
+from time_slider.fileversion import main
+
+main(abspath(__file__))
+
diff --git a/usr/lib/time-slider/plugins/rsync/rsync-backup b/usr/lib/time-slider/plugins/rsync/rsync-backup
new file mode 100755 (executable)
index 0000000..1129617
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/python2.6
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, pardir, pardir, pardir,
+                        'share', 'time-slider', 'lib', 'plugin'))
+
+from rsync.backup import main
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
diff --git a/usr/lib/time-slider/plugins/rsync/rsync-trigger b/usr/lib/time-slider/plugins/rsync/rsync-trigger
new file mode 100755 (executable)
index 0000000..49e863c
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/python2.6
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, pardir, pardir, pardir,
+                        'share', 'time-slider', 'lib', 'plugin'))
+
+from rsync.trigger import main
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
diff --git a/usr/lib/time-slider/plugins/zfssend/zfssend b/usr/lib/time-slider/plugins/zfssend/zfssend
new file mode 100755 (executable)
index 0000000..17dec8b
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/python2.6
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, pardir, pardir, pardir,
+                        'share', 'time-slider', 'lib', 'plugin'))
+
+from zfssend.zfssend import main
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
diff --git a/usr/lib/time-sliderd b/usr/lib/time-sliderd
new file mode 100755 (executable)
index 0000000..eccac9c
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/python2.6
+import sys
+from os.path import dirname, join, pardir, abspath
+sys.path.insert(0, join(dirname(__file__), pardir, 'share',
+                        'time-slider', 'lib'))
+
+from time_slider.timesliderd import main
+# Pass through the executable path in case it needs to
+# be invoked via gksu (user has insufficient priviliges) 
+main(abspath(__file__))
+
diff --git a/usr/share/applications/time-slider.desktop b/usr/share/applications/time-slider.desktop
new file mode 100644 (file)
index 0000000..dae4339
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Time Slider
+Comment=Configure the system to take automatic snapshots of your data
+Terminal=false
+Type=Application
+StartupNotify=true
+Exec=time-slider-setup
+Icon=time-slider-setup
+Categories=Application;System;Settings
diff --git a/usr/share/icons/hicolor/16x16/apps/time-slider-setup.png b/usr/share/icons/hicolor/16x16/apps/time-slider-setup.png
new file mode 100644 (file)
index 0000000..8591495
Binary files /dev/null and b/usr/share/icons/hicolor/16x16/apps/time-slider-setup.png differ
diff --git a/usr/share/icons/hicolor/24x24/apps/time-slider-setup.png b/usr/share/icons/hicolor/24x24/apps/time-slider-setup.png
new file mode 100644 (file)
index 0000000..d2e3f78
Binary files /dev/null and b/usr/share/icons/hicolor/24x24/apps/time-slider-setup.png differ
diff --git a/usr/share/icons/hicolor/32x32/apps/time-slider-setup.png b/usr/share/icons/hicolor/32x32/apps/time-slider-setup.png
new file mode 100644 (file)
index 0000000..1b20ca9
Binary files /dev/null and b/usr/share/icons/hicolor/32x32/apps/time-slider-setup.png differ
diff --git a/usr/share/icons/hicolor/36x36/apps/time-slider-setup.png b/usr/share/icons/hicolor/36x36/apps/time-slider-setup.png
new file mode 100644 (file)
index 0000000..9d893b1
Binary files /dev/null and b/usr/share/icons/hicolor/36x36/apps/time-slider-setup.png differ
diff --git a/usr/share/icons/hicolor/48x48/apps/time-slider-setup.png b/usr/share/icons/hicolor/48x48/apps/time-slider-setup.png
new file mode 100644 (file)
index 0000000..440fcf1
Binary files /dev/null and b/usr/share/icons/hicolor/48x48/apps/time-slider-setup.png differ
diff --git a/usr/share/icons/hicolor/72x72/apps/time-slider-setup.png b/usr/share/icons/hicolor/72x72/apps/time-slider-setup.png
new file mode 100644 (file)
index 0000000..5b0a5cb
Binary files /dev/null and b/usr/share/icons/hicolor/72x72/apps/time-slider-setup.png differ
diff --git a/usr/share/icons/hicolor/96x96/apps/time-slider-setup.png b/usr/share/icons/hicolor/96x96/apps/time-slider-setup.png
new file mode 100644 (file)
index 0000000..ef6e07f
Binary files /dev/null and b/usr/share/icons/hicolor/96x96/apps/time-slider-setup.png differ
diff --git a/usr/share/time-slider/glade/time-slider-delete.glade b/usr/share/time-slider/glade/time-slider-delete.glade
new file mode 100644 (file)
index 0000000..adf2d88
--- /dev/null
@@ -0,0 +1,567 @@
+<?xml version="1.0"?>
+<glade-interface>
+  <!-- interface-requires gtk+ 2.10 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <widget class="GtkDialog" id="time-slider-delete">
+    <property name="visible">True</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Delete Snapshots</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="icon_name">time-slider-setup</property>
+    <property name="type_hint">dialog</property>
+    <property name="has_separator">False</property>
+    <signal name="delete_event" handler="on_window_delete_event"/>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <child>
+          <widget class="GtkTable" id="table1">
+            <property name="visible">True</property>
+            <property name="n_rows">4</property>
+            <property name="n_columns">2</property>
+            <property name="column_spacing">9</property>
+            <property name="row_spacing">12</property>
+            <child>
+              <widget class="GtkScrolledWindow" id="scrollwin">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <property name="shadow_type">etched-in</property>
+                <child>
+                  <widget class="GtkTreeView" id="snaplist">
+                    <property name="height_request">300</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="reorderable">True</property>
+                    <property name="rules_hint">True</property>
+                    <property name="rubber_banding">True</property>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Select ZFS snapshots to delete from the list below.</property>
+              </widget>
+              <packing>
+                <property name="right_attach">2</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkHBox" id="hbox1">
+                <property name="visible">True</property>
+                <property name="spacing">6</property>
+                <child>
+                  <widget class="GtkLabel" id="label5">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Type:</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkComboBox" id="typefiltercombo">
+                    <property name="visible">True</property>
+                    <signal name="changed" handler="on_typefiltercombo_changed"/>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">File System:</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkComboBoxEntry" id="fsfilterentry">
+                    <property name="visible">True</property>
+                    <signal name="changed" handler="on_fsfilterentry_changed"/>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Name:</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkComboBoxEntry" id="schedfilterentry">
+                    <property name="visible">True</property>
+                    <signal name="changed" handler="on_schedfilterentry_changed"/>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">5</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkHBox" id="hbox2">
+                <property name="height_request">6</property>
+                <property name="visible">True</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </widget>
+              <packing>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkAlignment" id="alignment1">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <property name="right_padding">12</property>
+                <child>
+                  <widget class="GtkVBox" id="vbox2">
+                    <property name="visible">True</property>
+                    <property name="spacing">24</property>
+                    <child>
+                      <widget class="GtkVBox" id="vbox3">
+                        <property name="visible">True</property>
+                        <property name="spacing">6</property>
+                        <property name="homogeneous">True</property>
+                        <child>
+                          <widget class="GtkButton" id="selectbutton">
+                            <property name="label">gtk-select-all</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="use_stock">True</property>
+                            <signal name="clicked" handler="on_selectbutton_clicked"/>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkButton" id="deselectbutton">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <signal name="clicked" handler="on_deselectbutton_clicked"/>
+                            <child>
+                              <widget class="GtkHBox" id="hbox3">
+                                <property name="visible">True</property>
+                                <child>
+                                  <widget class="GtkImage" id="image1">
+                                    <property name="visible">True</property>
+                                    <property name="stock">gtk-clear</property>
+                                  </widget>
+                                  <packing>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkLabel" id="label4">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">D_eselect All</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">deselectbutton</property>
+                                  </widget>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkButton" id="deletebutton">
+                        <property name="label">gtk-delete</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_stock">True</property>
+                        <signal name="clicked" handler="on_deletebutton_clicked"/>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+                <property name="x_options"></property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <widget class="GtkButton" id="closebutton">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="on_closebutton_clicked"/>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="confirmdialog">
+    <property name="width_request">300</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Delete Snapshots</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="icon_name">time-slider-setup</property>
+    <property name="type_hint">dialog</property>
+    <property name="transient_for">time-slider-delete</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox2">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkFrame" id="frame1">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment2">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkVBox" id="vbox1">
+                    <property name="visible">True</property>
+                    <property name="spacing">12</property>
+                    <child>
+                      <widget class="GtkVBox" id="vbox5">
+                        <property name="visible">True</property>
+                        <child>
+                          <widget class="GtkLabel" id="summarylabel">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">%d snapshots will be deleted.</property>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label7">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Press Delete to continue.</property>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkCheckButton" id="exittoggle">
+                        <property name="label" translatable="yes">Exit when done. </property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="draw_indicator">True</property>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label5">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;b&gt;Summary&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area2">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <widget class="GtkButton" id="confirmcancel">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="on_confirmcancel_clicked"/>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="confirmdelete">
+                <property name="label">gtk-delete</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="on_confirmdelete_clicked"/>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="deletingdialog">
+    <property name="width_request">300</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Deleting Snapshots</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="icon_name">time-slider-setup</property>
+    <property name="type_hint">dialog</property>
+    <property name="deletable">False</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox3">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkVBox" id="vbox6">
+            <property name="visible">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label6">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Deleting snapshots...</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkProgressBar" id="deletingprogress">
+                <property name="visible">True</property>
+                <property name="activity_mode">True</property>
+                <property name="show_text">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area3">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="pulsedialog">
+    <property name="border_width">5</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="icon_name">time-slider-setup</property>
+    <property name="type_hint">dialog</property>
+    <property name="deletable">False</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox4">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkVBox" id="vbox4">
+            <property name="visible">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label8">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Scanning snapshots...</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkProgressBar" id="pulsebar">
+                <property name="visible">True</property>
+                <property name="activity_mode">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area4">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/usr/share/time-slider/glade/time-slider-setup.glade b/usr/share/time-slider/glade/time-slider-setup.glade
new file mode 100644 (file)
index 0000000..6117c85
--- /dev/null
@@ -0,0 +1,531 @@
+<?xml version="1.0"?>
+<glade-interface>
+  <!-- interface-requires gtk+ 2.6 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <widget class="GtkWindow" id="toplevel">
+    <property name="visible">True</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Time Slider Manager</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="icon_name">time-slider-setup</property>
+    <property name="type_hint">dialog</property>
+    <signal name="delete_event" handler="on_snapshotmanager_delete_event"/>
+    <child>
+      <widget class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <widget class="GtkVBox" id="vbox2">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">18</property>
+            <child>
+              <widget class="GtkVBox" id="vbox3">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <widget class="GtkCheckButton" id="enablebutton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="draw_indicator">True</property>
+                    <signal name="toggled" handler="on_enablebutton_toggled"/>
+                    <child>
+                      <widget class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Enable Time Slider&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label4">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Time Slider backs up data regularly by taking timed ZFS Snapshots</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkExpander" id="expander">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="use_markup">True</property>
+                <child>
+                  <widget class="GtkVBox" id="advancedbox">
+                    <property name="visible">True</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">12</property>
+                    <child>
+                      <widget class="GtkFrame" id="frame1">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <widget class="GtkAlignment" id="alignment1">
+                            <property name="visible">True</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <widget class="GtkVBox" id="vbox7">
+                                <property name="visible">True</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <widget class="GtkCheckButton" id="rsyncbutton">
+                                    <property name="label" translatable="yes">Replicate backups to an external drive</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="draw_indicator">True</property>
+                                    <signal name="toggled" handler="on_rsyncbutton_toggled"/>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkHBox" id="hbox4">
+                                    <property name="visible">True</property>
+                                    <property name="spacing">6</property>
+                                    <child>
+                                      <widget class="GtkLabel" id="label10">
+                                        <property name="visible">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">Backup Device:</property>
+                                      </widget>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">False</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <widget class="GtkComboBox" id="rsyncdevcombo">
+                                        <property name="visible">True</property>
+                                        <property name="items" translatable="yes"></property>
+                                      </widget>
+                                      <packing>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </widget>
+                            </child>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label8">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;External Back Up&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </widget>
+                          <packing>
+                            <property name="type">label_item</property>
+                          </packing>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkFrame" id="filesysframe">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <widget class="GtkAlignment" id="alignment7">
+                            <property name="visible">True</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <widget class="GtkVBox" id="vbox5">
+                                <property name="visible">True</property>
+                                <property name="orientation">vertical</property>
+                                <property name="spacing">12</property>
+                                <child>
+                                  <widget class="GtkTable" id="table1">
+                                    <property name="visible">True</property>
+                                    <property name="n_rows">2</property>
+                                    <property name="n_columns">2</property>
+                                    <property name="column_spacing">72</property>
+                                    <child>
+                                      <widget class="GtkLabel" id="label9">
+                                        <property name="visible">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">For advanced users</property>
+                                      </widget>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <widget class="GtkLabel" id="label15">
+                                        <property name="visible">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">Recommended for most users</property>
+                                      </widget>
+                                      <packing>
+                                        <property name="left_attach">1</property>
+                                        <property name="right_attach">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <widget class="GtkRadioButton" id="selectfsradio">
+                                        <property name="label" translatable="yes">C_ustom:</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">False</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <property name="group">defaultfsradio</property>
+                                        <signal name="toggled" handler="on_selectfsradio_toggled"/>
+                                      </widget>
+                                      <packing>
+                                        <property name="top_attach">1</property>
+                                        <property name="bottom_attach">2</property>
+                                        <property name="x_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <widget class="GtkRadioButton" id="defaultfsradio">
+                                        <property name="label" translatable="yes">_All</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">False</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="active">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <signal name="toggled" handler="on_defaultfsradio_toggled"/>
+                                      </widget>
+                                      <packing>
+                                        <property name="x_options">GTK_FILL</property>
+                                      </packing>
+                                    </child>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkScrolledWindow" id="scrolledwindow2">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="hscrollbar_policy">automatic</property>
+                                    <property name="vscrollbar_policy">automatic</property>
+                                    <child>
+                                      <widget class="GtkTreeView" id="fstreeview">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="rules_hint">True</property>
+                                      </widget>
+                                    </child>
+                                  </widget>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkVBox" id="vbox6">
+                                    <property name="visible">True</property>
+                                    <property name="orientation">vertical</property>
+                                    <property name="spacing">5</property>
+                                    <child>
+                                      <widget class="GtkLabel" id="label5">
+                                        <property name="visible">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">Reduce backups when storage space usage exceeds:</property>
+                                      </widget>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">False</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <widget class="GtkHBox" id="hbox3">
+                                        <property name="visible">True</property>
+                                        <property name="spacing">5</property>
+                                        <child>
+                                          <widget class="GtkSpinButton" id="capspinbutton">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="invisible_char">&#x25CF;</property>
+                                            <property name="adjustment">0 0 100 1 10 0</property>
+                                            <property name="numeric">True</property>
+                                            <property name="update_policy">if-valid</property>
+                                          </widget>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">False</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <widget class="GtkLabel" id="label6">
+                                            <property name="visible">True</property>
+                                            <property name="xalign">0</property>
+                                            <property name="label">%</property>
+                                          </widget>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">False</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <widget class="GtkLabel" id="label7">
+                                            <property name="visible">True</property>
+                                            <property name="xalign">0</property>
+                                            <property name="label" translatable="yes">of file system capacity</property>
+                                          </widget>
+                                          <packing>
+                                            <property name="position">2</property>
+                                          </packing>
+                                        </child>
+                                      </widget>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="fill">False</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">2</property>
+                                  </packing>
+                                </child>
+                              </widget>
+                            </child>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label2">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;File Systems To Back Up&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </widget>
+                          <packing>
+                            <property name="type">label_item</property>
+                          </packing>
+                        </child>
+                      </widget>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Advanced Options</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="border_width">6</property>
+            <property name="spacing">18</property>
+            <child>
+              <widget class="GtkButton" id="deletesnapshots">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <signal name="clicked" handler="on_deletesnapshots_clicked"/>
+                <child>
+                  <widget class="GtkHBox" id="hbox2">
+                    <property name="visible">True</property>
+                    <property name="spacing">5</property>
+                    <child>
+                      <widget class="GtkImage" id="image1">
+                        <property name="visible">True</property>
+                        <property name="stock">gtk-delete</property>
+                      </widget>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="deletebutton">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Delete Snapshots...</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                      </widget>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkHButtonBox" id="hbuttonbox1">
+                <property name="visible">True</property>
+                <property name="spacing">6</property>
+                <property name="layout_style">end</property>
+                <child>
+                  <widget class="GtkButton" id="cancel">
+                    <property name="label">gtk-cancel</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_stock">True</property>
+                    <signal name="clicked" handler="on_cancel_clicked"/>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkButton" id="ok">
+                    <property name="label">gtk-ok</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_stock">True</property>
+                    <signal name="clicked" handler="on_ok_clicked"/>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkDialog" id="pulsedialog">
+    <property name="border_width">5</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="icon_name">time-slider-setup</property>
+    <property name="type_hint">dialog</property>
+    <property name="deletable">False</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox6">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkVBox" id="vbox4">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkLabel" id="label8">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Configuring Time Slider...</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkProgressBar" id="pulsebar">
+                <property name="visible">True</property>
+                <property name="activity_mode">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area6">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/usr/share/time-slider/glade/time-slider-snapshot.glade b/usr/share/time-slider/glade/time-slider-snapshot.glade
new file mode 100644 (file)
index 0000000..3e883f7
--- /dev/null
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.5 on Fri Jan  9 16:35:14 2009 -->
+<glade-interface>
+  <widget class="GtkDialog" id="dialog">
+    <property name="width_request">400</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Take a snapshot now</property>
+    <property name="modal">True</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="icon_name">time-slider-setup</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="has_separator">False</property>
+    <signal name="delete_event" handler="on_window_delete_event"/>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox2">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="spacing">2</property>
+            <child>
+              <widget class="GtkImage" id="image1">
+                <property name="visible">True</property>
+                <property name="stock">gtk-dialog-question</property>
+                <property name="icon_size">6</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkTable" id="table2">
+                <property name="visible">True</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">2</property>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <widget class="GtkEntry" id="snapshot_name_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                  </widget>
+                  <packing>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="dir_label">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                  </widget>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label2">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Take a snapshot of </property>
+                  </widget>
+                  <packing>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">with the name :</property>
+                  </widget>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="padding">3</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area2">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="confirm_cancel">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="label">gtk-cancel</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="on_cancel_clicked"/>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="confirm_snapshot">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="label">gtk-ok</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="on_ok_clicked"/>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/usr/share/time-slider/glade/time-slider-version.glade b/usr/share/time-slider/glade/time-slider-version.glade
new file mode 100644 (file)
index 0000000..f59fe47
--- /dev/null
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.5 on Fri Jan 23 18:32:59 2009 -->
+<glade-interface>
+  <widget class="GtkWindow" id="toplevel">
+    <property name="width_request">500</property>
+    <property name="height_request">400</property>
+    <property name="visible">True</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Time Slider File Version Explorer</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="icon_name">time-slider-setup</property>
+    <signal name="delete_event" handler="on_toplevel_delete_event"/>
+    <child>
+      <widget class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <property name="spacing">12</property>
+        <child>
+          <widget class="GtkVBox" id="vbox2">
+            <property name="visible">True</property>
+            <child>
+              <widget class="GtkFrame" id="File">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment2">
+                    <property name="visible">True</property>
+                    <property name="top_padding">5</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <child>
+                      <widget class="GtkHBox" id="hbox2">
+                        <property name="visible">True</property>
+                        <child>
+                          <widget class="GtkButton" id="current_file_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip" translatable="yes">Open the current version of the file</property>
+                            <property name="relief">GTK_RELIEF_NONE</property>
+                            <property name="response_id">0</property>
+                            <signal name="clicked" handler="on_current_file_button_clicked"/>
+                            <child>
+                              <widget class="GtkImage" id="icon_image">
+                                <property name="visible">True</property>
+                                <property name="xpad">24</property>
+                                <property name="stock">gtk-file</property>
+                                <property name="icon_size">6</property>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="padding">5</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkTable" id="table1">
+                            <property name="visible">True</property>
+                            <property name="n_rows">3</property>
+                            <property name="n_columns">2</property>
+                            <child>
+                              <widget class="GtkLabel" id="label3">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">last modified : </property>
+                              </widget>
+                              <packing>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="date_label">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">19/01/09</property>
+                              </widget>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="label2">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">size : </property>
+                              </widget>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="size_label">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">10 Mo</property>
+                              </widget>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="filename_label">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">filename</property>
+                              </widget>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="label6">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">name :</property>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label5">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Current Version&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">4</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkFrame" id="frame1">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="top_padding">5</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <widget class="GtkVBox" id="vbox3">
+                        <property name="visible">True</property>
+                        <child>
+                          <widget class="GtkProgressBar" id="progress">
+                            <property name="visible">True</property>
+                            <property name="show_text">True</property>
+                            <property name="text" translatable="yes">Scanning for older versions</property>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkScrolledWindow" id="scrolledwindow1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                            <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                            <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+                            <child>
+                              <widget class="GtkTreeView" id="treeview">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="tooltip" translatable="yes">Double click to open the file</property>
+                                <property name="reorderable">True</property>
+                                <property name="rules_hint">True</property>
+                                <property name="search_column">0</property>
+                                <property name="hover_expand">True</property>
+                                <signal name="row_activated" handler="on_treeview_row_activated"/>
+                                <signal name="cursor_changed" handler="on_treeview_cursor_changed"/>
+                              </widget>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="older_versions_label">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Older Versions&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+        </child>
+        <child>
+          <widget class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="border_width">6</property>
+            <property name="spacing">18</property>
+            <child>
+              <widget class="GtkButton" id="compare_button">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="has_tooltip">True</property>
+                <property name="tooltip_text">Compare the current version and the selected older version</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="on_compare_button_clicked"/>
+                <child>
+                  <widget class="GtkHBox" id="hbox3">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkImage" id="image2">
+                        <property name="visible">True</property>
+                        <property name="stock">gtk-print-preview</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label4">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">compare</property>
+                      </widget>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkHButtonBox" id="hbuttonbox1">
+                <property name="visible">True</property>
+                <property name="spacing">6</property>
+                <property name="layout_style">GTK_BUTTONBOX_END</property>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <widget class="GtkButton" id="ok">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="label" translatable="yes">gtk-close</property>
+                    <property name="use_stock">True</property>
+                    <property name="response_id">0</property>
+                    <signal name="clicked" handler="on_close_clicked"/>
+                  </widget>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/usr/share/time-slider/lib/plugin/__init__.py b/usr/share/time-slider/lib/plugin/__init__.py
new file mode 100644 (file)
index 0000000..649d6ed
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir))
+
diff --git a/usr/share/time-slider/lib/plugin/plugin.py b/usr/share/time-slider/lib/plugin/plugin.py
new file mode 100644 (file)
index 0000000..1b820ff
--- /dev/null
@@ -0,0 +1,167 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import sys
+import subprocess
+import pluginsmf
+
+from time_slider import smf, autosnapsmf, util
+
+PLUGINBASEFMRI = "svc:/application/time-slider/plugin"
+
+
+class Plugin(Exception):
+
+    def __init__(self, instanceName, debug=False):
+        self.verbose = debug
+        util.debug("Instantiating plugin for:\t%s" % (instanceName), self.verbose)
+        self.smfInst = pluginsmf.PluginSMF(instanceName)
+        self._proc = None
+
+        # Note that the associated plugin service's start method checks
+        # that the command is defined and executable. But SMF doesn't 
+        # bother to do this for offline services until all dependencies
+        # (ie. time-slider) are brought online.
+        # So we also check the permissions here.
+        command = self.smfInst.get_trigger_command()
+        try:
+            statinfo = os.stat(command)
+            other_x = (statinfo.st_mode & 01)
+            if other_x == 0:
+              raise RuntimeError, 'Plugin: %s:\nConfigured trigger command is not ' \
+                                  'executable:\n%s' \
+                                  % (self.smfInst.instanceName, command)  
+        except OSError:
+            raise RuntimeError, 'Plugin: %s:\nCan not access the configured ' \
+                                'plugin/trigger_command:\n%s' \
+                                % (self.smfInst.instanceName, command)      
+
+
+    def execute(self, schedule, label):
+
+        triggers = self.smfInst.get_trigger_list()
+        try:
+            triggers.index("all")
+        except ValueError:
+            try:
+                triggers.index(schedule)
+            except ValueError:
+                return
+
+        # Skip if already running
+        if self.is_running() == True:
+            util.debug("Plugin: %s is already running. Skipping execution" \
+                       % (self.smfInst.instanceName), \
+                       self.verbose)
+            return
+        # Skip if plugin FMRI has been disabled or placed into maintenance
+        cmd = [smf.SVCSCMD, "-H", "-o", "state", self.smfInst.instanceName]
+        outdata,errdata = util.run_command(cmd)
+        state = outdata.strip()
+        if state == "disabled" or state == "maintenance":
+            util.debug("Plugin: %s is in %s state. Skipping execution" \
+                       % (self.smfInst.instanceName, state), \
+                       self.verbose)
+            return
+
+        cmd = self.smfInst.get_trigger_command()
+        util.debug("Executing plugin command: %s" % str(cmd), self.verbose)
+        svcFmri = "%s:%s" % (autosnapsmf.BASESVC, schedule)
+
+        os.putenv("AUTOSNAP_FMRI", svcFmri)
+        os.putenv("AUTOSNAP_LABEL", label)
+        try:
+            os.putenv("PLUGIN_FMRI", self.smfInst.instanceName) 
+            self._proc = subprocess.Popen(cmd,
+                                          stdout=subprocess.PIPE,
+                                          stderr=subprocess.PIPE,
+                                          close_fds=True)
+        except OSError, message:
+            raise RuntimeError, "%s subprocess error:\n %s" % \
+                                (cmd, str(message))
+            self._proc = None
+
+    def is_running(self):
+        if self._proc == None:
+            util.debug("Plugin child process is not started", self.verbose)
+            return False
+        else:
+            self._proc.poll()
+            if self._proc.returncode == None:
+                util.debug("Plugin child process is still running",
+                           self.verbose)
+                return True
+            else:
+                util.debug("Plugin child process has ended", self.verbose)
+                return False
+
+
+class PluginManager():
+
+    def __init__(self, debug=False):
+        self.plugins = []
+        self.verbose = debug
+
+    def execute_plugins(self, schedule, label):
+        util.debug("Executing plugins for \"%s\" with label: \"%s\"" \
+                   % (schedule, label), \
+                   self.verbose)
+        for plugin in self.plugins:
+            plugin.execute(schedule, label)
+
+
+    def refresh(self):
+        self.plugins = []
+        cmd = [smf.SVCSCMD, "-H", "-o", "state,FMRI", PLUGINBASEFMRI]
+
+        p = subprocess.Popen(cmd,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE,
+                             close_fds=True)
+        outdata,errdata = p.communicate()
+        err = p.wait()
+        if err != 0:
+            self._refreshLock.release()
+            raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                (str(cmd), err, errdata)
+        for line in outdata.rstrip().split('\n'):
+            line = line.rstrip().split()
+            state = line[0]
+            fmri = line[1]
+
+            # Note that the plugins, being dependent on the time-slider service
+            # themselves will typically be in an offline state when enabled. They will
+            # transition to an "online" state once time-slider itself comes
+            # "online" to satisfy it's dependency
+            if state == "online" or state == "offline" or state == "degraded":
+                util.debug("Found enabled plugin:\t%s" % (fmri), self.verbose)
+                try:
+                    plugin = Plugin(fmri, self.verbose)
+                    self.plugins.append(plugin)
+                except RuntimeError, message:
+                    sys.stderr.write("Ignoring misconfigured plugin: %s\n" \
+                                     % (fmri))
+                    sys.stderr.write("Reason:\n%s\n" % (message))
+            else:
+                util.debug("Found disabled plugin:\t%s" + fmri, self.verbose)
+
diff --git a/usr/share/time-slider/lib/plugin/pluginsmf.py b/usr/share/time-slider/lib/plugin/pluginsmf.py
new file mode 100644 (file)
index 0000000..c71df82
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import sys
+import subprocess
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir))
+from time_slider import smf, autosnapsmf, util
+
+
+PLUGINBASEFMRI = "svc:/application/time-slider/plugin"
+PLUGINPROPGROUP = "plugin"
+
+class PluginSMF(smf.SMFInstance):
+
+    def __init__(self, instanceName):
+        smf.SMFInstance.__init__(self, instanceName)
+        self.triggerCommand = None
+        self.triggers = None
+
+    def get_trigger_command(self):
+        # FIXME Use mutex locking for MT safety
+        if self.triggerCommand == None:
+            value = self.get_prop(PLUGINPROPGROUP, "trigger_command")
+            self.triggerCommand = value.strip()
+        return self.triggerCommand            
+
+    def get_trigger_list(self):
+        #FIXME Use mutex locking to make MT-safe
+        if self.triggers == None:
+            self.triggers = []
+            value = self.get_prop(PLUGINPROPGROUP, "trigger_on")
+            
+            # Strip out '\' characters inserted by svcprop
+            triggerList = value.strip().replace('\\', '').split(',')
+            for trigger in triggerList:
+                self.triggers.append(trigger.strip())
+        return self.triggers
+
+    def get_verbose(self):
+        value = self.get_prop(PLUGINPROPGROUP, "verbose")
+        if value == "true":
+            return True
+        else:
+            return False
+
diff --git a/usr/share/time-slider/lib/plugin/pluginsmf.py~ b/usr/share/time-slider/lib/plugin/pluginsmf.py~
new file mode 100644 (file)
index 0000000..e6c44df
--- /dev/null
@@ -0,0 +1,67 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import sys
+import subprocess
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir))
+print join (dirname(__file__), pardir)
+from time_slider import smf, autosnapsmf, util
+
+
+PLUGINBASEFMRI = "svc:/application/time-slider/plugin"
+PLUGINPROPGROUP = "plugin"
+
+class PluginSMF(smf.SMFInstance):
+
+    def __init__(self, instanceName):
+        smf.SMFInstance.__init__(self, instanceName)
+        self.triggerCommand = None
+        self.triggers = None
+
+    def get_trigger_command(self):
+        # FIXME Use mutex locking for MT safety
+        if self.triggerCommand == None:
+            value = self.get_prop(PLUGINPROPGROUP, "trigger_command")
+            self.triggerCommand = value.strip()
+        return self.triggerCommand            
+
+    def get_trigger_list(self):
+        #FIXME Use mutex locking to make MT-safe
+        if self.triggers == None:
+            self.triggers = []
+            value = self.get_prop(PLUGINPROPGROUP, "trigger_on")
+            
+            # Strip out '\' characters inserted by svcprop
+            triggerList = value.strip().replace('\\', '').split(',')
+            for trigger in triggerList:
+                self.triggers.append(trigger.strip())
+        return self.triggers
+
+    def get_verbose(self):
+        value = self.get_prop(PLUGINPROPGROUP, "verbose")
+        if value == "true":
+            return True
+        else:
+            return False
+
diff --git a/usr/share/time-slider/lib/plugin/rsync/__init__.py b/usr/share/time-slider/lib/plugin/rsync/__init__.py
new file mode 100644 (file)
index 0000000..a2667b2
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, pardir))
+
diff --git a/usr/share/time-slider/lib/plugin/rsync/backup.py b/usr/share/time-slider/lib/plugin/rsync/backup.py
new file mode 100644 (file)
index 0000000..ce44090
--- /dev/null
@@ -0,0 +1,1260 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import os.path
+import fcntl
+import tempfile
+import sys
+import subprocess
+import statvfs
+import time
+import threading
+import math
+import syslog
+import gobject
+import gio
+import dbus
+import shutil
+import copy
+from bisect import insort, bisect_left
+
+from time_slider import util, zfs, dbussvc, autosnapsmf, timeslidersmf
+import rsyncsmf
+
+
+# Set to True if SMF property value of "plugin/command" is "true"
+verboseprop = "plugin/verbose"
+propbasename = "org.opensolaris:time-slider-plugin"
+
+class RsyncError(Exception):
+    """Generic base class for RsyncError
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __str__(self):
+        return repr(self.msg)
+
+
+class RsyncTargetDisconnectedError(RsyncError):
+    """Exception raised when the backup device goes offline during
+       the rsync transfer.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, source, dest, message):
+        msg = "Target directory error during rsync backup from " \
+              "%s to target \'%s\' Rsync error details:\n%s" \
+              % (source, dest, message)
+        RsyncError.__init__(self, msg)
+
+
+class RsyncTransferInterruptedError(RsyncError):
+    """Exception raised when the rsync transfer process pid was
+       interrupted or killed during the rsync transfer.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, source, dest, message):
+        msg = "Interrputed rsync transfer from %s to %s " \
+              "Rsync error details:\n%s" % (source, dest, message)
+        RsyncError.__init__(self, msg)
+
+
+class RsyncSourceVanishedError(RsyncError):
+    """Exception raised when rsync could only partially transfer
+       due to the contents of the source directory being removed.
+       Possibly due to a snapshot being destroyed during transfer
+       because of immediate or deferred (holds released) destruction.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, source, dest, message):
+        msg = "Rsync source directory vanished during transfer of %s to %s" \
+              "Rsync error details:\n%s" % (source, dest, message)
+        RsyncError.__init__(self, msg)
+
+
+class RsyncProcess(threading.Thread):
+
+
+    def __init__(self, source, target, latest=None, verbose=False, logfile=None):
+
+        self._sourceDir = source
+        self._backupDir = target
+        self._latest = latest
+        self._verbose = verbose
+        self._proc = None
+        self._forkError = None
+        self._logFile = logfile
+        # Init done. Now initiaslise threading.
+        threading.Thread.__init__ (self)
+
+    def run(self):
+        try:
+            self._proc = subprocess.Popen(self._cmd,
+                                          stderr=subprocess.PIPE,
+                                          close_fds=True)
+        except OSError as e:
+            # _check_exit_code() will pick up this and raise an
+            # exception in the original thread.
+            self._forkError = "%s: %s" % (self._cmd[0], str(e))
+        else:
+            self._stdout,self._stderr = self._proc.communicate()
+            self._exitValue = self._proc.wait()
+
+    def _check_exit_code(self):
+        if self._forkError:
+            # The rsync process failed to execute, probably
+            # received an OSError exception. Pass it up.
+            raise RsyncError(self._forkError)
+
+        if self._exitValue == 0:
+            return
+        # Non zero return code means rsync encountered an
+        # error which may be transient or require sys-admin
+        # intervention to fix.
+        
+        # This method basically just maps known rsync exit codes
+        # to exception classes.
+        
+        # Rsync exit value codes (non-zero)
+        
+        # 11/12 Indicates backup drive was disconnected during
+        # transfer. Recoverable once drive reconnected:
+        # 11   Error in file I/O
+        # 12   Error in rsync protocol data stream
+        if self._exitValue == 11 or \
+            self._exitValue == 12:
+            raise RsyncTargetDisconnectedError(self._sourceDir,
+                                               self._backupDir,
+                                               self._stderr)
+        # Transfer pid interrupted by SIGUSR1 or SIGINT. Recoverable:
+        # 20   Received SIGUSR1 or SIGINT
+        elif self._proc.returncode == 20:
+            raise RsyncTransferInterruptedError(self._sourceDir,
+                                                self._backupDir,
+                                                self._stderr)
+
+        # For everything else unknown or unexpected, treat it as 
+        # fatal and provide the rsync stderr output.
+        else:
+            raise RsyncError(self._stderr)
+
+    def start_backup(self):
+        # First, check to see if the rsync destination
+        # directory is accessible.
+        try:
+            os.stat(self._backupDir)
+        except OSError:
+            util.debug("Backup directory is not " \
+                       "currently accessible: %s" \
+                       % (self._backupDir),
+                       self._verbose)
+            #FIXME exit/exception needs to be raise here
+            # or status needs to be set.
+            return
+
+        try:
+            os.stat(self._sourceDir)
+        except OSError:
+            util.debug("Backup source directory is not " \
+                       "currently accessible: %s" \
+                       % (self._sourceDir),
+                       self._verbose)
+            #FIXME exit/excpetion needs to be raise here
+            # or status needs to be set.
+            return
+
+        if self._latest:
+            self._cmd = ["/usr/bin/rsync", "-a", "--inplace",\
+                   "%s/." % (self._sourceDir), \
+                   "--link-dest=%s" % (self._latest), \
+                   self._backupDir]
+        else:
+            self._cmd = ["/usr/bin/rsync", "-a", "--inplace",\
+                   "%s/." % (self._sourceDir), \
+                   self._backupDir]
+
+        if self._logFile:
+            self._cmd.insert(1, "--log-file=%s" % (self._logFile))
+        if self._verbose:
+            self._cmd.insert(1, "-vv")
+
+        self.start()
+
+
+class BackupQueue():
+
+    def __init__(self, fmri, dbus, mainLoop=None):
+        self._bus = dbus
+        self._mainLoop = mainLoop
+        self._started = False
+        self._pluginFMRI = fmri
+        self._smfInst = rsyncsmf.RsyncSMF(self._pluginFMRI)
+        self._verbose = self._smfInst.get_verbose()
+        self._rsyncVerbose = self._smfInst.get_rsync_verbose()
+        self._propName = "%s:%s" % (propbasename, fmri.rsplit(':', 1)[1])
+
+        # Variables to quickly access time sorted backups and 
+        # to map directory names to mtimes.
+        self._backupDirs = None
+        self._backups = None
+        self._backupTimes = {}
+
+        released = release_held_snapshots(self._propName)
+        for snapName in released:
+            util.debug("Released dangling userref on: " + snapName,
+                       self._verbose)
+
+        self._tempSchedules = None
+        # List of all snapshots currently in our backup queue
+        self._pendingList = list_pending_snapshots(self._propName)
+
+        # Try to backup in sets of snapshots grouped by a common
+        # snapshot label. These get taken from the head of the
+        # pending list. After a working set has been completed,
+        # pending list gets refreshed and a new working set is
+        # extracted.
+        self._currentQueueSet = []
+        self._skipList = []
+        self._queueLength = 0
+
+        self._cleanupThreshold = self._smfInst.get_cleanup_threshold()
+        if self._cleanupThreshold < 1 or \
+           self._cleanupThreshold > 99:
+            # Stupid value. #FIXME Plugin should be checked by SMF start
+            # method and placed into maintenance if this happens.
+            # For now, go with default
+            util.log_error(syslog.LOG_ERR,
+                           "Invalid value for SMF property " \
+                           "<rsync/cleanup_threshold>: %d." \
+                           "Using default value of 95%" \
+                           % (self._cleanupThreshold))
+
+        # Base variables for backup device. Will be initialised
+        # later in _find_backup_device()
+        self._smfTargetKey = self._smfInst.get_target_key()
+        sys,self._nodeName,rel,ver,arch = os.uname()
+        self._rsyncBaseDir = None
+        self._rsyncDir = None
+        self._keyFile = None
+
+        tsSMF = timeslidersmf.TimeSliderSMF()
+        self._labelSeparator = tsSMF.get_separator()
+        del tsSMF
+        # Finally go look for the backup device
+        self._find_backup_device()
+
+    def empty_trash_folders(self):
+        trashDirs = []
+        trashedBackups = []
+        os.chdir(self._rsyncDir)
+        for root, dirs, files in os.walk(self._rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove ('.time-slider')
+                trashDir = os.path.join(root,
+                                        rsyncsmf.RSYNCTRASHSUFFIX)
+                if os.path.exists(trashDir):
+                    trashDirs.append(trashDir)
+        for trashDir in trashDirs:
+            os.chdir(trashDir)
+            trashItems = []
+            trashItems = [d for d in os.listdir(trashDir) \
+                          if os.path.isdir(d) and
+                          not os.path.islink(d)]
+            if len(trashItems) > 0:
+                util.debug("Deleting trash backups in %s" % (trashDir),
+                           self._verbose)
+            for trashItem in trashItems:
+                util.debug("Deleting trash item: %s" % (trashItem),
+                           self._verbose)
+                # FIXME add some dbus notification here to let the
+                # applet know what's going on.
+                shutil.rmtree(trashItem)
+
+    def _get_temp_schedules(self):
+        # Get retention rule for non archival snapshots as per
+        # rules defined in:
+        # svc://system/filesystem/zfs/auto-snapshot:<schedule>
+        archived = self._smfInst.get_archived_schedules()
+        triggers = self._smfInst.get_trigger_list()
+        defScheds = autosnapsmf.get_default_schedules()
+        customScheds = autosnapsmf.get_custom_schedules()
+        try:
+            triggers.index('all')
+            # Expand the wildcard value 'all' 
+            triggers = [sched for sched,i,p,k in defScheds]
+            customTriggers = [sched for sched,i,p,k in customScheds]
+            triggers.extend(customTriggers)
+        except ValueError:
+            pass
+
+        self._tempSchedules = [schedule for schedule in defScheds if \
+                               schedule[0] not in archived]
+        self._tempSchedules.extend([schedule for schedule in customScheds if \
+                                   schedule[0] not in archived])
+
+    def _remove_dead_backups(self):
+        """
+           Identifies and removes partially completed backups whose origin
+           snapshot is no longer in the pending queue, indicating that the
+           backup will never get completed, in which case it's just a waste
+           of space
+        """
+        backupDirs = []
+        partialDirs = []
+        deadBackups = []
+        os.chdir(self._rsyncDir)
+        for root, dirs, files in os.walk(self._rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove ('.time-slider')
+                partialDir = os.path.join(root,
+                                          rsyncsmf.RSYNCPARTIALSUFFIX)
+                partialDirs.append(partialDir)
+        for dirName in partialDirs:
+            if not os.path.exists(partialDir):
+                continue
+            os.chdir(dirName)
+            partials = [d for d in os.listdir(dirName) \
+                        if os.path.isdir(d)]
+            if len(partials) == 0:
+                continue
+            suffix = rsyncsmf.RSYNCPARTIALSUFFIX
+            prefix = self._rsyncDir
+            # Reconstruct the origin ZFS filesystem name
+            baseName = dirName.replace(prefix, '', 1).lstrip('/')
+            fsName = baseName.replace(suffix, '', 1).rstrip('/')
+            for snapshotLabel in partials:
+                pending = False
+                # Reconstruct the origin snapshot name and see
+                # if it's still pending rsync backup. If it is
+                # then leave it alone since it can be used to
+                # resume a partial backup later. Otherwise it's
+                # never going to be backed up and needs to be
+                # manually deleted.
+                snapshotName = "%s@%s" % (fsName, snapshotLabel)
+                for ctime,name in self._pendingList:
+                    if name == snapshotName:
+                        pending = True
+                        continue
+                if pending == False:
+                    util.debug("Deleting zombied partial backup: %s" \
+                               % (os.path.abspath(snapshotLabel)),
+                               self._verbose)
+                    shutil.rmtree(snapshotLabel)
+                    # Don't forget the log file too.
+                    logFile = os.path.join(os.path.pardir,
+                                           os.path.pardir,
+                                           rsyncsmf.RSYNCLOGSUFFIX,
+                                           snapshotLabel + ".log")
+                    try:
+                        os.stat(logFile)
+                        util.debug("Deleting zombie log file: %s" \
+                                   % (os.path.abspath(logFile)),
+                                   self._verbose)
+                        os.unlink(logFile)
+                    except OSError:
+                        util.debug("Expected rsync log file not " \
+                                   "found: %s"\
+                                   % (os.path.abspath(logFile)),
+                                   self._verbose)
+
+    def _discover_backups(self):
+        self._backupDirs = []
+        self._backups = []
+        self._backupTimes = {}
+        # backupTimes dictionary is not primarily used
+        # to store directory listings, but to map 
+        # mtimes to directories for quick lookups.
+        
+        os.chdir (self._rsyncDir)
+        for root, dirs, files in os.walk(self._rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove('.time-slider')
+                backupDir = os.path.join(root, rsyncsmf.RSYNCDIRSUFFIX)
+                if os.path.exists(backupDir):
+                    insort(self._backupDirs, os.path.abspath(backupDir))
+        for dirName in self._backupDirs:
+            self._backupTimes[dirName] = {}
+            os.chdir(dirName)
+            dirList = [d for d in os.listdir(dirName) \
+                        if os.path.isdir(d) and
+                        not os.path.islink(d)]
+            for d in dirList:
+                mtime = os.stat(d).st_mtime
+                insort(self._backups, [long(mtime), os.path.abspath(d)])
+                self._backupTimes[dirName][d] = mtime
+
+    def _find_backup_device(self):
+        # Determine the rsync backup dir. This is the target dir
+        # defined by the SMF instance plus the "TIMESLIDER/<nodename>"
+        # suffix. Try finding it at the preconfigured path first,
+        # then failing that, scan removable media mounts, in case it
+        # got remounted under a different path than at setup time.
+        self._rsyncBaseDir = None
+        path = self._smfInst.get_target_dir()
+        if self._validate_rsync_target(path) == True:
+            self._rsyncBaseDir = path
+            util.debug("Backup target device online: %s" % (path),
+                       self._verbose)
+        else:
+            util.debug("Backup target device not mounted at: %s" \
+                       "Scanning removable devices.." \
+                       % (path),
+                       self._verbose)
+            volMonitor = gio.volume_monitor_get()
+            mounts = volMonitor.get_mounts()
+            for mount in mounts:
+                root = mount.get_root()
+                path = root.get_path()
+                if self._validate_rsync_target(path) == True:
+                    util.debug("Located backup target device at: %s" \
+                               % (path),
+                               self._verbose)
+                    self._rsyncBaseDir = path
+
+        if self._rsyncBaseDir != None:
+            self._rsyncDir = os.path.join(self._rsyncBaseDir,
+                                         rsyncsmf.RSYNCDIRPREFIX,
+                                         self._nodeName)
+            self._keyFile = os.path.join(self._rsyncBaseDir,
+                                         rsyncsmf.RSYNCDIRPREFIX,
+                                         rsyncsmf.RSYNCCONFIGFILE)
+
+        
+    def _validate_rsync_target(self, path):
+        """
+           Tests path to see if it is the pre-configured
+           rsync backup device path.
+           Returns True on success, otherwise False
+        """
+        # FIXME - this is duplicate in the applet and should
+        # be moved into a shared module
+        if not os.path.exists(path):
+            return False
+        testDir = os.path.join(path,
+                               rsyncsmf.RSYNCDIRPREFIX,
+                               self._nodeName)
+        testKeyFile = os.path.join(path,
+                                   rsyncsmf.RSYNCDIRPREFIX,
+                                   rsyncsmf.RSYNCCONFIGFILE)
+        if os.path.exists(testDir) and \
+            os.path.exists(testKeyFile):
+            testKeyVal = None
+            f = open(testKeyFile, 'r')
+            for line in f.readlines():
+                key, val = line.strip().split('=')
+                if key.strip() == "target_key":
+                    targetKey = val.strip()
+                    break
+            f.close()
+            if targetKey == self._smfTargetKey:
+                return True
+        return False
+
+    def _find_deleteable_backups(self, timestamp):
+        """
+           Returns a list of backup directory paths that are older than
+           timestamp, and can be deleted in order to make room for newer
+           backups. Certain restrictions apply such as:
+           - The backup cannot be locked (indicating it's being or about
+             to be deleted by another process
+           - The last remaining backup in it's parent directory, which
+             would mean it is the only backup of a given fileystem on the
+             device. We always keep at least 1 full backup of a filesystem
+             on the device if it belongs to a currently selected filesystem.
+        """
+        deleteables = []
+        # This should have already occured in
+        # backup_snapshot() mainloop method
+        if self._backupDirs == None:
+            self._discover_backups()
+
+        if len(self._backupDirs) == 0:
+            # We were not able to find any backups to delete. Try again later
+            return []
+
+        # Extract the subset of self._backupDirs that are older than timestamp
+        idx = bisect_left(self._backups, [timestamp, ''])
+        subset = self._backups[0:idx]
+
+        # Copy the backupTimes dictionary since so we can
+        # modify it safely.
+        copiedTimes = copy.deepcopy(self._backupTimes)
+        for mtime, dirName in subset:
+            head,tail = os.path.split(dirName)
+            if len(copiedTimes[head]) < 2:
+                # We can only delete this single backup provided
+                # it's filesystem is no longer tagged for rsync
+                # replication. Othewise we need to leave at least
+                # one backup on the device at all times, and also
+                # to provide an incremental backup point for
+                # future backups.
+                snapName = backup_name_to_snapshot_name(dirName)
+                snapshot = zfs.Snapshot(snapName)
+                fs = zfs.Filesystem(snapshot.fsname)
+                if fs.get_user_property(rsyncsmf.RSYNCFSTAG) == "true":
+                    continue
+                else:
+                    # If we are going to actually remove this final
+                    # remaining backup of this filesystem then we need
+                    # to unqueue any pending snapshots of it,
+                    # otherwise after deleting this one, we'll just 
+                    # start backing up the older snapshots of this 
+                    # filesystem afterwards, which is a waste of time
+                    # and space.
+                    pending = [name for time,name in \
+                               list_pending_snapshots(self._propName) if \
+                               name.find(snapshot.fsname + '@') == 0]
+                    cmd = [zfs.PFCMD, zfs.ZFSCMD, "inherit", self._propName]
+                    util.debug("Unqueuing pending backups of deselected " \
+                               "filesystem: " + snapshot.fsname + '\n' + \
+                               str(pending),
+                               self._verbose)
+                    cmd.extend(pending)
+                    util.run_command(cmd)
+
+            lockFileDir = os.path.join(head,
+                                       os.path.pardir,
+                                       os.path.pardir,
+                                       rsyncsmf.RSYNCLOCKSUFFIX)
+            lockFile = os.path.join(lockFileDir, tail)
+
+            if not os.path.exists(lockFile):
+                # No lock file so we are free to delete it.
+                deleteables.append([mtime, dirName])
+                # Remove it from copiedTimes so it doesn't get
+                # double counted
+                del copiedTimes[head][tail]
+                continue
+            # Lock file so probably can't delete this, but try it out
+            # anyway incase it's stale/unlocked
+            try:
+                lockFp = open(lockFile, 'w')
+                fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+            except IOError:
+                util.debug("Can't delete backup %s because it " \
+                           "is locked by another process." \
+                           "Skipping" % (dirName),
+                           self._verbose)
+                continue
+            # Ok, we can still delete it, but get rid of the stale lock file
+            lockFp.close()
+            os.unlink(lockFile)
+            deleteabled.append([mtime, dirName])
+            # Remove it from copiedTimes so it doesn't get
+            # double counted
+            del copiedTimes[head][tail]
+        return deleteables
+
+    def _recover_space(self, deleteables):
+
+        # Important:
+        # Don't actually loop throught this list fully. Break out
+        # as soon as pool capacity is beneath the threshhold level
+        # again.
+        remainder = deleteables[:]
+        for mtime,dirName in deleteables:
+            if util.get_filesystem_capacity(self._rsyncDir) < \
+               self._cleanupThreshold:
+                # No need to delete anything further
+                return remainder
+            lockFile = None
+            lockFp = None
+            head,tail = os.path.split(dirName)
+                
+            # Check if it has a lock file and try to grab it.
+            # If that fails we need to move onto the next backup in
+            # the list.
+            lockFileDir = os.path.join(head,
+                                       os.path.pardir,
+                                       os.path.pardir,
+                                       rsyncsmf.RSYNCLOCKSUFFIX)
+            lockFile = os.path.join(lockFileDir, tail)
+
+            if not os.path.exists(lockFileDir):
+                os.makedirs(lockFileDir, 0755)
+            try:
+                lockFp = open(lockFile, 'w')
+                fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+            except IOError:
+                util.debug("Can't delete backup %s because it " \
+                           "is locked by another process." \
+                           "Skipping" % (dirName),
+                           self._verbose)
+                # Remove if from the remainder list
+                idx = bisect_left(remainder, [mtime, dirName])
+                del remainder[idx]
+                continue
+
+            trash = os.path.join(head,
+                                 os.path.pardir,
+                                 os.path.pardir,
+                                 rsyncsmf.RSYNCTRASHSUFFIX)
+            trashDir = os.path.join(trash, tail)
+
+            if not os.path.exists(trash):
+                os.makedirs(trash, 0755)
+
+            util.debug("Deleting rsync backup to recover space: %s"\
+                % (dirName), self._verbose)
+            os.rename(dirName, trashDir)
+            lockFp.close()
+            os.unlink(lockFile)
+            shutil.rmtree(trashDir)
+            # Remove the log file if it exists
+            logFile = os.path.join(head,
+                                   os.path.pardir,
+                                   os.path.pardir,
+                                   rsyncsmf.RSYNCLOGSUFFIX,
+                                   tail + ".log")
+            if os.path.exists(logFile):
+                os.unlink(logFile)
+            else:
+                util.debug("Expected to find log file %s when deleting %s " \
+                           "during space recovery" % (logFile, dirName),
+                           self._verbose)
+            # Remove dirName from the backup list
+            idx = bisect_left(self._backups, [mtime, dirName])
+            del self._backups[idx]
+            # Remove if from the remainder list too
+            idx = bisect_left(remainder, [mtime, dirName])
+            del remainder[idx]
+        return remainder
+
+    def backup_snapshot(self):
+        # First, check to see if the rsync destination
+        # directory is accessible.
+
+        if self._rsyncBaseDir == None:
+            util.debug("Backup target device is not " \
+                       "accessible right now: %s" \
+                       % (self._smfInst.get_target_dir()),
+                       self._verbose)
+            self._bus.rsync_unsynced(len(self._pendingList))
+            if self._mainLoop:
+                self._mainLoop.quit()
+            sys.exit(0)
+
+        # Extra paranoia
+        if self._validate_rsync_target(self._rsyncBaseDir) == False:
+            util.debug("Backup target directory does not " \
+                       "have a matching configuration key. " \
+                       "Possibly old or wrong device: %s" \
+                       % (self._keyFile),
+                       self._verbose)
+            self._bus.rsync_unsynced(len(self._pendingList))
+            if self._mainLoop:
+                self._mainLoop.quit()
+            sys.exit(0)
+
+        # Before getting started. Identify what needs to be cleaned up on 
+        # the backup target.
+        if self._tempSchedules == None:
+            self._get_temp_schedules()
+        
+        # Remove incompleteable partial backups, then find out what
+        # complete backups we already have on the target device
+        if self._started == False:
+            self._remove_dead_backups()
+            self._discover_backups()
+
+        if len(self._currentQueueSet) == 0:
+            # Means we are just getting started or have just completed
+            # backup of one full set of snapshots. Clear out anything
+            # we may have moved to the trash during the previous 
+            # backup set iterations.
+            self.empty_trash_folders()
+            # Refresh the pending list and build a new working set queue
+            self._pendingList = list_pending_snapshots(self._propName)
+            # Remove skipped items to avoid infinite looping.
+            for item in self._skipList:
+                try:
+                    self._pendingList.remove(item)
+                except ValueError:
+                    pass
+            if len(self._pendingList) == 0:
+                # If something was actually backed up, signal
+                # that it is now completed.
+                if self._started == True:
+                    self._bus.rsync_complete(self._rsyncBaseDir)
+                self._bus.rsync_synced()
+                # Nothing to do exit
+                if self._mainLoop:
+                    self._mainLoop.quit()
+                sys.exit(0)
+            else:
+                # Construct a new working set queue
+                # Identify the newest snapshot and then all
+                # snapshots with a matching snapshot label
+                self._queueLength = len(self._pendingList)
+                ctime,headSnapName = self._pendingList[0]
+                label = headSnapName.rsplit("@", 1)[1]
+                self._currentQueueSet = \
+                    [(ctime,snapName) for \
+                     ctime,snapName in self._pendingList if \
+                     snapName.rsplit("@", 1)[1] == label]
+
+
+        if len(self._backups) > 0:
+            oldestBackupTime, oldestBackup = self._backups[0]
+            qTime, qItem = self._currentQueueSet[0]
+
+            # If the backup device is nearly full, don't
+            # bother trying to backup anything unless it's
+            # newer than the oldest backup set already on
+            # the device.
+            # This avoids potential situations where if the
+            # backup device has severely limited capacity and
+            # older backups sets were in the queue, newer backups
+            # might get deleted in order to make room for older
+            # ones, creating a downward spiral.
+            capacity = util.get_filesystem_capacity(self._rsyncDir)
+            if capacity > self._cleanupThreshold:
+                # Find backups older than qTime that could in theory
+                # be deleted in order to make room for the curtent
+                # pending item.
+                deleteables = self._find_deleteable_backups(qTime)
+
+                if len(deleteables) == 0 and \
+                   qTime < oldestBackupTime:
+                    util.debug("%s has exceeded %d%% of its capacity. " \
+                                "Skipping pending backups prior to: " \
+                                "%s" % (self._rsyncDir,
+                                        self._cleanupThreshold,
+                                        time.ctime(oldestBackupTime)),
+                                self._verbose)
+                    if self._started == True:
+                        self._bus.rsync_complete(self._rsyncBaseDir)
+                    self._bus.rsync_synced()
+                    # Nothing to do exit
+                    if self._mainLoop:
+                        self._mainLoop.quit()
+                    sys.exit(0)
+
+        if self._started == False:
+            self._started = True
+            self._bus.rsync_started(self._rsyncBaseDir)
+
+        ctime,snapName = self._currentQueueSet[0]
+        snapshot = zfs.Snapshot(snapName, long(ctime))
+        # Make sure the snapshot didn't get destroyed since we last
+        # checked it.
+        remainingList = self._currentQueueSet[1:]
+        if snapshot.exists() == False:
+            util.debug("Snapshot: %s no longer exists. Skipping" \
+                        % (snapName), self._verbose)
+            self._currentQueueSet = remainingList
+            return True
+
+        # Place a hold on the snapshot so it doesn't go anywhere
+        # while rsync is trying to back it up.
+        snapshot.hold(self._propName)
+        self._queueLength -= 1
+        fs = zfs.Filesystem(snapshot.fsname)
+        sourceDir = None
+        if fs.is_mounted() == True:
+            # Get the mountpoint
+            mountPoint = fs.get_mountpoint()
+            sourceDir = "%s/.zfs/snapshot/%s" \
+                        % (mountPoint, snapshot.snaplabel)
+        else:
+            # If the filesystem is not mounted just skip it. If it's
+            # not mounted then nothing is being written to it. And
+            # we can just catch up with it again later if it doesn't
+            # get expired by time-sliderd
+            util.debug("%s is not mounted. Skipping." \
+                        % (snapshot.fsname), self._verbose)
+            snapshot.release(self._propName)
+            self._skipList.append(ctime, snapName)
+            self._currentQueueSet = remainingList
+            return True
+
+        # targetDir is the parent folder of all backups
+        # for a given filesystem
+        targetDir = os.path.join(self._rsyncDir,
+                                 snapshot.fsname,
+                                 rsyncsmf.RSYNCDIRSUFFIX)
+        # partialDir is a separate directory in which
+        # snapshots are initially backed up to. Upon successful
+        # completion they are moved to the backupDir.
+        partialDir = os.path.join(self._rsyncDir,
+                                  snapshot.fsname,
+                                  rsyncsmf.RSYNCPARTIALSUFFIX,
+                                  snapshot.snaplabel)
+        lockFileDir = os.path.join(self._rsyncDir,
+                                   snapshot.fsname,
+                                   rsyncsmf.RSYNCLOCKSUFFIX)
+        logDir = os.path.join(self._rsyncDir,
+                              snapshot.fsname,
+                              rsyncsmf.RSYNCLOGSUFFIX)
+        logFile = os.path.join(logDir,
+                               snapshot.snaplabel + ".log")
+
+        
+        # backupDir is the full directory path where the new
+        # backup will be located ie <targetDir>/<snapshot label>
+        backupDir = os.path.join(targetDir, snapshot.snaplabel)
+
+        # Figure out the closest previous backup. Since we
+        # backup newest first instead of oldest first it's
+        # determined as follows:
+        # If queued backup item is newer than the most recent
+        # backup on the backup target, use the most recent 
+        # backup as the incremental source.
+        # Othewise identify the backup on the device that is
+        # nearest to but newer than the queued backup.
+        nearestOlder = None
+        nearestNewer = None
+        dirList = []
+
+        if not os.path.exists(partialDir):
+            os.makedirs(partialDir, 0755)
+        if not os.path.exists(logDir):
+            os.makedirs(logDir, 0755)
+
+        if not os.path.exists(targetDir):
+            os.makedirs(targetDir, 0755)
+            # Add the new directory to our internal
+            # mtime dictionary and sorted list.
+            self._backupTimes[targetDir] = {}
+            insort(self._backupDirs, targetDir)
+        else:
+            for name,value in self._backupTimes[targetDir].items():
+                if ctime > value:
+                    if nearestOlder == None or \
+                       value > nearestOlder[1]:
+                        nearestOlder = [name, value]
+                else:
+                    if nearestNewer == None or \
+                       value < nearestNewer[1]:
+                        nearestNewer = [name, value]
+
+        os.chdir(targetDir)
+        link = None
+        linkDest = None
+        lockFile = None
+        lockFp = None
+        if nearestNewer:
+            link = nearestNewer[0]
+        elif nearestOlder:
+            link = nearestOlder[0]
+        if link:
+            linkDest = os.path.realpath(link)
+            # Create a lock for linkDest. We need to ensure that
+            # nautilus' restore view or the time-slider-delete
+            # GUI doesn't attempt to delete it or move it to the
+            # trash while it is being used by rsync for incremental
+            # backup.
+            lockFile = os.path.join(lockFileDir,
+                                    link + ".lock")
+
+            if not os.path.exists(lockFileDir):
+                os.makedirs(lockFileDir, 0755)
+
+            try:
+                lockFp = open(lockFile, 'w')
+                fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+            except IOError:
+                util.debug("Can't perform incremental rsync of %s because " \
+                           "unable to obtain exclusive lock on incremental " \
+                           "backup reference point: %s. Exiting" \
+                           % (lockFile), self._verbose)
+                os.chdir("/")
+                snapshot.release(self._propName)
+                sys.exit(1)
+
+        self._rsyncProc = RsyncProcess(sourceDir,
+                                       partialDir,
+                                       linkDest,
+                                       self._rsyncVerbose,
+                                       logFile)
+
+        # Notify the applet of current status via dbus
+        self._bus.rsync_current(snapshot.name, self._queueLength)
+
+        # Set umask temporarily so that rsync backups are read-only to
+        # the owner by default. Rync will override this to match the
+        # permissions of each snapshot as appropriate.
+        origmask = os.umask(0222)
+        util.debug("Starting rsync backup of '%s' to: %s" \
+                   % (sourceDir, partialDir),
+                   self._verbose)
+        self._rsyncProc.start_backup()
+
+        warningDone = False
+        while self._rsyncProc.is_alive():
+            if len(self._backups) > 0:
+                # Monitor backup target capacity while we wait for rsync.
+                capacity = util.get_filesystem_capacity(self._rsyncDir)
+                if capacity > self._cleanupThreshold:
+                    # Find backups older than qTime that could in theory
+                    # be deleted in order to make room for the curtent
+                    # pending item.
+                    deleteables = self._find_deleteable_backups(qTime)
+                    # Only generate annoying debug message once instead of
+                    # every 5 seconds.
+                    if warningDone == False:
+                        util.debug("Backup device capacity exceeds %d%%. " \
+                                   "Found %d deleteable backups for space " \
+                                   "recovery." \
+                                    % (capacity, len(deleteables)),
+                                    self._verbose)
+                        warningDone = True
+                    if len(deleteables) > 0:
+                        deleteables = self._recover_space(deleteables)
+            time.sleep(5)
+
+        try:
+            self._rsyncProc._check_exit_code()
+        except (RsyncTransferInterruptedError,
+                RsyncTargetDisconnectedError,
+                RsyncSourceVanishedError) as e:
+            os.chdir("/")
+            snapshot.release(self._propName)
+            util.log_error(syslog.LOG_ERR, str(e))
+            # These are recoverable, so exit for now and try again
+            # later
+            sys.exit(-1)
+
+        except RsyncError as e:
+            # If the backup device went offline we need to chdir
+            # out of it or running further commands might fail.
+            os.chdir("/")
+            util.log_error(syslog.LOG_ERR,
+                           "Unexpected rsync error encountered: \n" + \
+                           str(e))
+            util.log_error(syslog.LOG_ERR,
+                           "Rsync log file location: %s" \
+                           % (os.path.abspath(logFile)))
+            util.log_error(syslog.LOG_ERR,
+                           "Placing plugin into maintenance mode")
+            self._smfInst.mark_maintenance()
+            snapshot.release(self._propName)
+            sys.exit(-1)
+
+        finally:
+            if lockFp:
+                lockFp.close()
+                os.unlink(lockFile)
+
+        util.debug("Rsync process exited", self._verbose)
+        os.umask(origmask)
+
+        # Move the completed backup from the partial dir to the
+        # the propert backup directory 
+        util.debug("Renaming completed backup from %s to %s" \
+                   % (partialDir, backupDir), self._verbose)
+        os.rename(partialDir, backupDir)
+
+        # Reset the mtime and atime properties of the backup directory so that
+        # they match the snapshot creation time. This is extremely important
+        # because the backup mechanism relies on it to determine backup times
+        # and nearest matches for incremental rsync (linkDest)
+        os.utime(backupDir, (long(ctime), long(ctime)))
+        # Update the dictionary and time sorted list with ctime also
+        self._backupTimes[targetDir][snapshot.snaplabel] = long(ctime)
+        insort(self._backups, [long(ctime), os.path.abspath(backupDir)]) 
+        snapshot.set_user_property(self._propName, "completed")
+        snapshot.release(self._propName)
+        self._currentQueueSet = remainingList
+        
+        # Now is a good time to clean out the directory:
+        # Check to see if the backup just completed belonged to an
+        # auto-snapshot schedule and whether older backups should get
+        # deleted.
+        if snapshot.snaplabel.find(autosnapsmf.SNAPLABELPREFIX) == 0:
+            tempSchedule = None
+            label = None
+            for schedule in self._tempSchedules:
+                label = "%s%s%s" % (autosnapsmf.SNAPLABELPREFIX,
+                                    self._labelSeparator,
+                                    schedule[0])
+                if snapshot.snaplabel.find(label) == 0:
+                    tempSchedule = schedule
+                    break
+            if tempSchedule == None:
+                # Backup doesn't belong to a temporary schedule so 
+                # nothing left to do
+                return True
+
+            keep = tempSchedule[3] # [schedule,interval,period,keep]
+            schedBackups = [d for d in os.listdir(targetDir) if 
+                            d.find(label) == 0]
+            # The minimum that can be kept around is one:
+            # keeping zero is stupid since it might trigger
+            # a total replication rather than an incremental
+            # rsync replication.
+            if len(schedBackups) <= 1:
+                return True
+            if len(schedBackups) <= keep:
+                return True
+
+            sortedBackupList = []
+            for backup in schedBackups:
+                stInfo = os.stat(backup)
+                # List is sorted by mtime, oldest first
+                insort(sortedBackupList, [stInfo.st_mtime, backup])
+            purgeList = sortedBackupList[0:-keep]
+
+            trash = os.path.join(self._rsyncDir,
+                                 snapshot.fsname,
+                                 rsyncsmf.RSYNCTRASHSUFFIX)
+            if not os.path.exists(trash):
+                os.makedirs(trash, 0755)
+            for mtime,dirName in purgeList:
+                trashDir = os.path.join(trash,
+                                        dirName)
+                # Perform a final sanity check to make sure a backup
+                # directory and not a system directory is being purged.
+                # If it doesn't contain the RSYNCDIRSUFFIX string a
+                # ValueError will be raised.
+                try:
+                    os.getcwd().index(rsyncsmf.RSYNCDIRSUFFIX)
+                    lockFp = None
+                    lockFile = os.path.join(lockFileDir,
+                                            dirName + ".lock")
+
+                    if not os.path.exists(lockFileDir):
+                        os.makedirs(lockFileDir, 0755)
+
+                    try:
+                        lockFp = open(lockFile, 'w')
+                        fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+                    except IOError:
+                        util.debug("Can't move expired  backup %s to trash " \
+                                   "because it is locked by another " \
+                                   "process. Skipping" % (dirName),
+                                   self._verbose)
+
+                    util.debug("Moving expired rsync backup to trash:" \
+                               " %s -> %s" % (dirName, trash),
+                               self._verbose)
+                    os.rename(dirName, trashDir)
+                    # Release and delete lock file
+                    lockFp.close()
+                    os.unlink(lockFile)
+                    # Remove its mtime key/value from self._backupTimes
+                    del self._backupTimes[targetDir][dirName]
+                    # Log file needs to be deleted too.
+                    logFile = os.path.join(logDir,
+                                            dirName + ".log")
+                    try:
+                        os.stat(logFile)
+                        util.debug("Deleting rsync log file: %s" \
+                                    % (os.path.abspath(logFile)),
+                                    self._verbose)
+                        os.unlink(logFile)
+                    except OSError:
+                        util.debug("Expected rsync log file not " \
+                                    "found: %s"\
+                                    % (os.path.abspath(logFile)),
+                                    self._verbose)
+                                                
+                except ValueError:
+                    util.log_error(syslog.LOG_ALERT,
+                                    "Invalid attempt to delete " \
+                                    "non-backup directory: %s\n" \
+                                    "Placing plugin into " \
+                                    "maintenance state" % (dirName))
+                    self._smfInst.mark_maintenance()
+                    sys.exit(-1)
+        return True
+
+def release_held_snapshots(propName):
+    """
+    Releases dangling user snapshot holds that could
+    have occured during abnormal termination of a
+    previous invocation of this command during a 
+    previous rsync transfer.
+    Returns a list of snapshots that had holds mathcing
+    propName released.
+    """ 
+    # First narrow the list down by finding snapshots
+    # with userref count > 0
+    heldList = []
+    released = []
+    cmd = [zfs.ZFSCMD, "list", "-H",
+           "-t", "snapshot",
+           "-o", "userrefs,name"]
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        holdCount,name = line.split()
+        if int(holdCount) > 0:
+            heldList.append(name)
+    # Now check to see if any of those holds
+    # match 'propName'
+    for snapName in heldList:
+        snapshot = zfs.Snapshot(snapName)
+        holds = snapshot.holds()
+        try:
+            holds.index(propName)
+            snapshot.release(propName)
+            released.append(snapName)
+        except ValueError:
+            pass
+    return released
+
+
+def backup_name_to_snapshot_name(path):
+    """Reconstructs the original snapshot based on an
+       rsync backup's full path.
+       Returns a zfs snapshot name.
+    """
+    head,snapLabel = os.path.split(path)
+    sys,nodeName,rel,ver,arch = os.uname()
+    prefix = os.path.join(rsyncsmf.RSYNCDIRPREFIX,
+                          nodeName + '/')
+    suffix = rsyncsmf.RSYNCDIRSUFFIX
+
+    rsyncBaseDir,tail = head.split(prefix , 1)
+    fsName = tail.split(suffix, 1)[0].rstrip('/')
+    snapshotName = "%s@%s" % (fsName, snapLabel)
+    return snapshotName
+
+def list_pending_snapshots(propName):
+    """
+    Lists all snaphots which have 'propName" set locally.
+    Resulting list is returned sorted in descending order
+    of creation time (ie.newest first).
+    Each element in the returned list is tuple of the form:
+    [creationtime, snapshotname]
+    """
+    results = []
+    snaplist = []
+    sortsnaplist = []
+    # The process for backing up snapshots is:
+    # Identify all filesystem snapshots that have the (propName)
+    # property set to "pending" on them. Back them up starting
+    # with the oldest first.
+    #
+    # Unfortunately, there's no single zfs command that can
+    # output a locally set user property and a creation timestamp
+    # in one go. So this is done in two passes. The first pass
+    # identifies snapshots that are tagged as "pending". The 
+    # second pass uses the filtered results from the first pass
+    # as arguments to zfs(1) to get creation times.
+    cmd = [zfs.ZFSCMD, "get", "-H",
+            "-s", "local",
+            "-o", "name,value",
+            propName]
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        if len(line) > 1:
+            line = line.split()
+            results.append(line)
+
+    for name,value in results:
+        if value != "pending":
+            # Already backed up. Skip it."
+            continue
+        if name.find('@') == -1:
+            # Not a snapshot, and should not be set on a filesystem/volume
+            # Ignore it.
+            util.log_error(syslog.LOG_WARNING,
+                           "Dataset: %s shouldn't have local property: %s" \
+                           % (name, propName))
+            continue
+        snaplist.append(name)
+
+    # Nothing pending so just return the empty list
+    if len(snaplist) == 0:
+        return snaplist
+
+    cmd = [zfs.ZFSCMD, "get", "-p", "-H",
+            "-o", "value,name",
+            "creation"]
+    cmd.extend(snaplist)
+
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        ctimeStr,name = line.split()
+        insort(sortsnaplist, tuple((long(ctimeStr), name)))
+    sortsnaplist.reverse()
+    return sortsnaplist
+
+
+def main(argv):
+    # This command needs to be executed by the super user (root) to
+    # ensure that rsync has permissions to access all local filesystem
+    # snapshots and to replicate permissions and ownership on the target
+    # device
+    if os.geteuid() != 0:
+        head,tail = os.path.split(sys.argv[0])
+        sys.stderr.write(tail + " can only be executed by root")
+        sys.exit(-1)
+
+    # This process needs to be run as a system wide single instance
+    # only at any given time. So create a lockfile in /tmp and try
+    # to obtain an exclusive lock on it. If we can't then another 
+    # instance is running and already has a lock on it so just exit.
+    lockFileDir = os.path.normpath(tempfile.gettempdir() + '/' + \
+                                                       ".time-slider")
+    if not os.path.exists(lockFileDir):
+            os.makedirs(lockFileDir, 0755)
+    lockFile = os.path.join(lockFileDir, 'rsync-backup.lock')
+
+    lockFp = open(lockFile, 'w')
+    try:
+        fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+    except IOError:
+        sys.exit(2)
+
+    # The SMF fmri of the time-slider plugin instance associated with
+    # this command needs to be supplied as the argument immeditately
+    # proceeding the command. ie. argv[1]
+    try:
+        pluginFMRI = sys.argv[1]
+    except IndexError:
+        # No FMRI provided. Probably a user trying to invoke the command
+        # from the command line.
+        sys.stderr.write("No time-slider plugin SMF instance FMRI defined. " \
+                         "This plugin does not support command line " \
+                         "execution. Exiting\n")
+        sys.exit(-1)
+
+    # Open up a syslog session
+    syslog.openlog(sys.argv[0], 0, syslog.LOG_DAEMON)
+
+    gobject.threads_init()
+    # Tell dbus to use the gobject mainloop for async ops
+    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+    dbus.mainloop.glib.threads_init()
+    # Register a bus name with the system dbus daemon
+    sysbus = dbus.SystemBus()
+    busName = dbus.service.BusName("org.opensolaris.TimeSlider.plugin.rsync", sysbus)
+    dbusObj = dbussvc.RsyncBackup(sysbus, \
+        "/org/opensolaris/TimeSlider/plugin/rsync")
+
+    mainLoop = gobject.MainLoop()
+    backupQueue = BackupQueue(pluginFMRI, dbusObj, mainLoop)
+    gobject.idle_add(backupQueue.backup_snapshot)
+    mainLoop.run()
+    sys.exit(0)
+
diff --git a/usr/share/time-slider/lib/plugin/rsync/backup.py.orig b/usr/share/time-slider/lib/plugin/rsync/backup.py.orig
new file mode 100644 (file)
index 0000000..540f06a
--- /dev/null
@@ -0,0 +1,1264 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import os.path
+import fcntl
+import tempfile
+import sys
+import subprocess
+import statvfs
+import time
+import threading
+import math
+import syslog
+import gobject
+import gio
+import dbus
+import shutil
+import copy
+from bisect import insort, bisect_left
+
+from time_slider import util, zfs, dbussvc, autosnapsmf, timeslidersmf
+import rsyncsmf
+
+
+# Set to True if SMF property value of "plugin/command" is "true"
+verboseprop = "plugin/verbose"
+propbasename = "org.opensolaris:time-slider-plugin"
+
+class RsyncError(Exception):
+    """Generic base class for RsyncError
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __str__(self):
+        return repr(self.msg)
+
+
+class RsyncTargetDisconnectedError(RsyncError):
+    """Exception raised when the backup device goes offline during
+       the rsync transfer.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, source, dest, message):
+        msg = "Target directory error during rsync backup from " \
+              "%s to target \'%s\' Rsync error details:\n%s" \
+              % (source, dest, message)
+        RsyncError.__init__(self, msg)
+
+
+class RsyncTransferInterruptedError(RsyncError):
+    """Exception raised when the rsync transfer process pid was
+       interrupted or killed during the rsync transfer.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, source, dest, message):
+        msg = "Interrputed rsync transfer from %s to %s " \
+              "Rsync error details:\n%s" % (source, dest, message)
+        RsyncError.__init__(self, msg)
+
+
+class RsyncSourceVanishedError(RsyncError):
+    """Exception raised when rsync could only partially transfer
+       due to the contents of the source directory being removed.
+       Possibly due to a snapshot being destroyed during transfer
+       because of immediate or deferred (holds released) destruction.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, source, dest, message):
+        msg = "Rsync source directory vanished during transfer of %s to %s" \
+              "Rsync error details:\n%s" % (source, dest, message)
+        RsyncError.__init__(self, msg)
+
+
+class RsyncProcess(threading.Thread):
+
+
+    def __init__(self, source, target, latest=None, verbose=False, logfile=None):
+
+        self._sourceDir = source
+        self._backupDir = target
+        self._latest = latest
+        self._verbose = verbose
+        self._proc = None
+        self._forkError = None
+        self._logFile = logfile
+        # Init done. Now initiaslise threading.
+        threading.Thread.__init__ (self)
+
+    def run(self):
+        try:
+            self._proc = subprocess.Popen(self._cmd,
+                                          stderr=subprocess.PIPE,
+                                          close_fds=True)
+        except OSError as e:
+            # _check_exit_code() will pick up this and raise an
+            # exception in the original thread.
+            self._forkError = "%s: %s" % (self._cmd[0], str(e))
+        else:
+            self._stdout,self._stderr = self._proc.communicate()
+            self._exitValue = self._proc.wait()
+
+    def _check_exit_code(self):
+        if self._forkError:
+            # The rsync process failed to execute, probably
+            # received an OSError exception. Pass it up.
+            raise RsyncError(self._forkError)
+
+        if self._exitValue == 0:
+            return
+        # Non zero return code means rsync encountered an
+        # error which may be transient or require sys-admin
+        # intervention to fix.
+        
+        # This method basically just maps known rsync exit codes
+        # to exception classes.
+        
+        # Rsync exit value codes (non-zero)
+        
+        # 11/12 Indicates backup drive was disconnected during
+        # transfer. Recoverable once drive reconnected:
+        # 11   Error in file I/O
+        # 12   Error in rsync protocol data stream
+        if self._exitValue == 11 or \
+            self._exitValue == 12:
+            raise RsyncTargetDisconnectedError(self._sourceDir,
+                                               self._backupDir,
+                                               self._stderr)
+        # Transfer pid interrupted by SIGUSR1 or SIGINT. Recoverable:
+        # 20   Received SIGUSR1 or SIGINT
+        elif self._proc.returncode == 20:
+            raise RsyncTransferInterruptedError(self._sourceDir,
+                                                self._backupDir,
+                                                self._stderr)
+
+        # For everything else unknown or unexpected, treat it as 
+        # fatal and provide the rsync stderr output.
+        else:
+            raise RsyncError(self._stderr)
+
+    def start_backup(self):
+        # First, check to see if the rsync destination
+        # directory is accessible.
+        try:
+            os.stat(self._backupDir)
+        except OSError:
+            util.debug("Backup directory is not " \
+                       "currently accessible: %s" \
+                       % (self._backupDir),
+                       self._verbose)
+            #FIXME exit/exception needs to be raise here
+            # or status needs to be set.
+            return
+
+        try:
+            os.stat(self._sourceDir)
+        except OSError:
+            util.debug("Backup source directory is not " \
+                       "currently accessible: %s" \
+                       % (self._sourceDir),
+                       self._verbose)
+            #FIXME exit/excpetion needs to be raise here
+            # or status needs to be set.
+            return
+
+        if self._latest:
+            self._cmd = ["/usr/bin/rsync", "-a", "--inplace",\
+                   "%s/." % (self._sourceDir), \
+                   "--link-dest=%s" % (self._latest), \
+                   self._backupDir]
+        else:
+            self._cmd = ["/usr/bin/rsync", "-a", "--inplace",\
+                   "%s/." % (self._sourceDir), \
+                   self._backupDir]
+
+        if self._logFile:
+            self._cmd.insert(1, "--log-file=%s" % (self._logFile))
+        if self._verbose:
+            self._cmd.insert(1, "-vv")
+
+        self.start()
+
+
+class BackupQueue():
+
+    def __init__(self, fmri, dbus, mainLoop=None):
+        self._bus = dbus
+        self._mainLoop = mainLoop
+        self._started = False
+        self._pluginFMRI = fmri
+        self._smfInst = rsyncsmf.RsyncSMF(self._pluginFMRI)
+        self._verbose = self._smfInst.get_verbose()
+        self._rsyncVerbose = self._smfInst.get_rsync_verbose()
+        self._propName = "%s:%s" % (propbasename, fmri.rsplit(':', 1)[1])
+
+        # Variables to quickly access time sorted backups and 
+        # to map directory names to mtimes.
+        self._backupDirs = None
+        self._backups = None
+        self._backupTimes = {}
+
+        released = release_held_snapshots(self._propName)
+        for snapName in released:
+            util.debug("Released dangling userref on: " + snapName,
+                       self._verbose)
+
+        self._tempSchedules = None
+        # List of all snapshots currently in our backup queue
+        self._pendingList = list_pending_snapshots(self._propName)
+
+        # Try to backup in sets of snapshots grouped by a common
+        # snapshot label. These get taken from the head of the
+        # pending list. After a working set has been completed,
+        # pending list gets refreshed and a new working set is
+        # extracted.
+        self._currentQueueSet = []
+        self._skipList = []
+        self._queueLength = 0
+
+        self._cleanupThreshold = self._smfInst.get_cleanup_threshold()
+        if self._cleanupThreshold < 1 or \
+           self._cleanupThreshold > 99:
+            # Stupid value. #FIXME Plugin should be checked by SMF start
+            # method and placed into maintenance if this happens.
+            # For now, go with default
+            util.log_error(syslog.LOG_ERR,
+                           "Invalid value for SMF property " \
+                           "<rsync/cleanup_threshold>: %d." \
+                           "Using default value of 95%" \
+                           % (self._cleanupThreshold))
+
+        # Base variables for backup device. Will be initialised
+        # later in _find_backup_device()
+        self._smfTargetKey = self._smfInst.get_target_key()
+        sys,self._nodeName,rel,ver,arch = os.uname()
+        self._rsyncBaseDir = None
+        self._rsyncDir = None
+        self._keyFile = None
+
+        tsSMF = timeslidersmf.TimeSliderSMF()
+        self._labelSeparator = tsSMF.get_separator()
+        del tsSMF
+        # Finally go look for the backup device
+        self._find_backup_device()
+
+    def empty_trash_folders(self):
+        trashDirs = []
+        trashedBackups = []
+        os.chdir(self._rsyncDir)
+        for root, dirs, files in os.walk(self._rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove ('.time-slider')
+                trashDir = os.path.join(root,
+                                        rsyncsmf.RSYNCTRASHSUFFIX)
+                if os.path.exists(trashDir):
+                    trashDirs.append(trashDir)
+        for trashDir in trashDirs:
+            os.chdir(trashDir)
+            trashItems = []
+            trashItems = [d for d in os.listdir(trashDir) \
+                          if os.path.isdir(d) and
+                          not os.path.islink(d)]
+            if len(trashItems) > 0:
+                util.debug("Deleting trash backups in %s" % (trashDir),
+                           self._verbose)
+            for trashItem in trashItems:
+                util.debug("Deleting trash item: %s" % (trashItem),
+                           self._verbose)
+                # FIXME add some dbus notification here to let the
+                # applet know what's going on.
+                shutil.rmtree(trashItem)
+
+    def _get_temp_schedules(self):
+        # Get retention rule for non archival snapshots as per
+        # rules defined in:
+        # svc://system/filesystem/zfs/auto-snapshot:<schedule>
+        archived = self._smfInst.get_archived_schedules()
+        triggers = self._smfInst.get_trigger_list()
+        defScheds = autosnapsmf.get_default_schedules()
+        customScheds = autosnapsmf.get_custom_schedules()
+        try:
+            triggers.index('all')
+            # Expand the wildcard value 'all' 
+            triggers = [sched for sched,i,p,k in defScheds]
+            customTriggers = [sched for sched,i,p,k in customScheds]
+            triggers.extend(customTriggers)
+        except ValueError:
+            pass
+
+        self._tempSchedules = [schedule for schedule in defScheds if \
+                               schedule[0] not in archived]
+        self._tempSchedules.extend([schedule for schedule in customScheds if \
+                                   schedule[0] not in archived])
+
+    def _remove_dead_backups(self):
+        """
+           Identifies and removes partially completed backups whose origin
+           snapshot is no longer in the pending queue, indicating that the
+           backup will never get completed, in which case it's just a waste
+           of space
+        """
+        backupDirs = []
+        partialDirs = []
+        deadBackups = []
+        os.chdir(self._rsyncDir)
+        for root, dirs, files in os.walk(self._rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove ('.time-slider')
+                partialDir = os.path.join(root,
+                                          rsyncsmf.RSYNCPARTIALSUFFIX)
+                partialDirs.append(partialDir)
+        for dirName in partialDirs:
+            if not os.path.exists(partialDir):
+                continue
+            os.chdir(dirName)
+            partials = [d for d in os.listdir(dirName) \
+                        if os.path.isdir(d)]
+            if len(partials) == 0:
+                continue
+            suffix = rsyncsmf.RSYNCPARTIALSUFFIX
+            prefix = self._rsyncDir
+            # Reconstruct the origin ZFS filesystem name
+            baseName = dirName.replace(prefix, '', 1).lstrip('/')
+            fsName = baseName.replace(suffix, '', 1).rstrip('/')
+            for snapshotLabel in partials:
+                pending = False
+                # Reconstruct the origin snapshot name and see
+                # if it's still pending rsync backup. If it is
+                # then leave it alone since it can be used to
+                # resume a partial backup later. Otherwise it's
+                # never going to be backed up and needs to be
+                # manually deleted.
+                snapshotName = "%s@%s" % (fsName, snapshotLabel)
+                for ctime,name in self._pendingList:
+                    if name == snapshotName:
+                        pending = True
+                        continue
+                if pending == False:
+                    util.debug("Deleting zombied partial backup: %s" \
+                               % (os.path.abspath(snapshotLabel)),
+                               self._verbose)
+                    shutil.rmtree(snapshotLabel)
+                    # Don't forget the log file too.
+                    logFile = os.path.join(os.path.pardir,
+                                           os.path.pardir,
+                                           rsyncsmf.RSYNCLOGSUFFIX,
+                                           snapshotLabel + ".log")
+                    try:
+                        os.stat(logFile)
+                        util.debug("Deleting zombie log file: %s" \
+                                   % (os.path.abspath(logFile)),
+                                   self._verbose)
+                        os.unlink(logFile)
+                    except OSError:
+                        util.debug("Expected rsync log file not " \
+                                   "found: %s"\
+                                   % (os.path.abspath(logFile)),
+                                   self._verbose)
+
+    def _discover_backups(self):
+        self._backupDirs = []
+        self._backups = []
+        self._backupTimes = {}
+        # backupTimes dictionary is not primarily used
+        # to store directory listings, but to map 
+        # mtimes to directories for quick lookups.
+        
+        os.chdir (self._rsyncDir)
+        for root, dirs, files in os.walk(self._rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove('.time-slider')
+                backupDir = os.path.join(root, rsyncsmf.RSYNCDIRSUFFIX)
+                if os.path.exists(backupDir):
+                    insort(self._backupDirs, os.path.abspath(backupDir))
+        for dirName in self._backupDirs:
+            self._backupTimes[dirName] = {}
+            os.chdir(dirName)
+            dirList = [d for d in os.listdir(dirName) \
+                        if os.path.isdir(d) and
+                        not os.path.islink(d)]
+            for d in dirList:
+                mtime = os.stat(d).st_mtime
+                insort(self._backups, [long(mtime), os.path.abspath(d)])
+                self._backupTimes[dirName][d] = mtime
+
+    def _find_backup_device(self):
+        # Determine the rsync backup dir. This is the target dir
+        # defined by the SMF instance plus the "TIMESLIDER/<nodename>"
+        # suffix. Try finding it at the preconfigured path first,
+        # then failing that, scan removable media mounts, in case it
+        # got remounted under a different path than at setup time.
+        self._rsyncBaseDir = None
+        path = self._smfInst.get_target_dir()
+        if self._validate_rsync_target(path) == True:
+            self._rsyncBaseDir = path
+            util.debug("Backup target device online: %s" % (path),
+                       self._verbose)
+        else:
+            util.debug("Backup target device not mounted at: %s" \
+                       "Scanning removable devices.." \
+                       % (path),
+                       self._verbose)
+            volMonitor = gio.volume_monitor_get()
+            mounts = volMonitor.get_mounts()
+            for mount in mounts:
+                root = mount.get_root()
+                path = root.get_path()
+                if self._validate_rsync_target(path) == True:
+                    util.debug("Located backup target device at: %s" \
+                               % (path),
+                               self._verbose)
+                    self._rsyncBaseDir = path
+
+        if self._rsyncBaseDir != None:
+            self._rsyncDir = os.path.join(self._rsyncBaseDir,
+                                         rsyncsmf.RSYNCDIRPREFIX,
+                                         self._nodeName)
+            self._keyFile = os.path.join(self._rsyncBaseDir,
+                                         rsyncsmf.RSYNCDIRPREFIX,
+                                         rsyncsmf.RSYNCCONFIGFILE)
+
+        
+    def _validate_rsync_target(self, path):
+        """
+           Tests path to see if it is the pre-configured
+           rsync backup device path.
+           Returns True on success, otherwise False
+        """
+        # FIXME - this is duplicate in the applet and should
+        # be moved into a shared module
+        if not os.path.exists(path):
+            return False
+        testDir = os.path.join(path,
+                               rsyncsmf.RSYNCDIRPREFIX,
+                               self._nodeName)
+        testKeyFile = os.path.join(path,
+                                   rsyncsmf.RSYNCDIRPREFIX,
+                                   rsyncsmf.RSYNCCONFIGFILE)
+        if os.path.exists(testDir) and \
+            os.path.exists(testKeyFile):
+            testKeyVal = None
+            f = open(testKeyFile, 'r')
+            for line in f.readlines():
+                key, val = line.strip().split('=')
+                if key.strip() == "target_key":
+                    targetKey = val.strip()
+                    break
+            f.close()
+            if targetKey == self._smfTargetKey:
+                return True
+        return False
+
+    def _find_deleteable_backups(self, timestamp):
+        """
+           Returns a list of backup directory paths that are older than
+           timestamp, and can be deleted in order to make room for newer
+           backups. Certain restrictions apply such as:
+           - The backup cannot be locked (indicating it's being or about
+             to be deleted by another process
+           - The last remaining backup in it's parent directory, which
+             would mean it is the only backup of a given fileystem on the
+             device. We always keep at least 1 full backup of a filesystem
+             on the device if it belongs to a currently selected filesystem.
+        """
+        deleteables = []
+        # This should have already occured in
+        # backup_snapshot() mainloop method
+        if self._backupDirs == None:
+            self._discover_backups()
+
+        if len(self._backupDirs) == 0:
+            # We were not able to find any backups to delete. Try again later
+            return []
+
+        # Extract the subset of self._backupDirs that are older than timestamp
+        idx = bisect_left(self._backups, [timestamp, ''])
+        subset = self._backups[0:idx]
+
+        # Copy the backupTimes dictionary since so we can
+        # modify it safely.
+        copiedTimes = copy.deepcopy(self._backupTimes)
+        for mtime, dirName in subset:
+            head,tail = os.path.split(dirName)
+            if len(copiedTimes[head]) < 2:
+                # We can only delete this single backup provided
+                # it's filesystem is no longer tagged for rsync
+                # replication. Othewise we need to leave at least
+                # one backup on the device at all times, and also
+                # to provide an incremental backup point for
+                # future backups.
+                snapName = backup_name_to_snapshot_name(dirName)
+                snapshot = zfs.Snapshot(snapName)
+                fs = zfs.Filesystem(snapshot.fsname)
+                if fs.get_user_property(rsyncsmf.RSYNCFSTAG) == "true":
+                    continue
+                else:
+                    # If we are going to actually remove this final
+                    # remaining backup of this filesystem then we need
+                    # to unqueue any pending snapshots of it,
+                    # otherwise after deleting this one, we'll just 
+                    # start backing up the older snapshots of this 
+                    # filesystem afterwards, which is a waste of time
+                    # and space.
+                    pending = [name for time,name in \
+                               list_pending_snapshots(self._propName) if \
+                               name.find(snapshot.fsname + '@') == 0]
+                    cmd = [zfs.PFCMD, zfs.ZFSCMD, "inherit", self._propName]
+                    util.debug("Unqueuing pending backups of deselected " \
+                               "filesystem: " + snapshot.fsname + '\n' + \
+                               str(pending),
+                               self._verbose)
+                    cmd.extend(pending)
+                    util.run_command(cmd)
+
+            lockFileDir = os.path.join(head,
+                                       os.path.pardir,
+                                       os.path.pardir,
+                                       rsyncsmf.RSYNCLOCKSUFFIX)
+            lockFile = os.path.join(lockFileDir, tail)
+
+            if not os.path.exists(lockFile):
+                # No lock file so we are free to delete it.
+                deleteables.append([mtime, dirName])
+                # Remove it from copiedTimes so it doesn't get
+                # double counted
+                del copiedTimes[head][tail]
+                continue
+            # Lock file so probably can't delete this, but try it out
+            # anyway incase it's stale/unlocked
+            try:
+                lockFp = open(lockFile, 'w')
+                fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+            except IOError:
+                util.debug("Can't delete backup %s because it " \
+                           "is locked by another process." \
+                           "Skipping" % (dirName),
+                           self._verbose)
+                continue
+            # Ok, we can still delete it, but get rid of the stale lock file
+            lockFp.close()
+            os.unlink(lockFile)
+            deleteabled.append([mtime, dirName])
+            # Remove it from copiedTimes so it doesn't get
+            # double counted
+            del copiedTimes[head][tail]
+        return deleteables
+
+    def _recover_space(self, deleteables):
+
+        # Important:
+        # Don't actually loop throught this list fully. Break out
+        # as soon as pool capacity is beneath the threshhold level
+        # again.
+        remainder = deleteables[:]
+        for mtime,dirName in deleteables:
+            if util.get_filesystem_capacity(self._rsyncDir) < \
+               self._cleanupThreshold:
+                # No need to delete anything further
+                return remainder
+            lockFile = None
+            lockFp = None
+            head,tail = os.path.split(dirName)
+                
+            # Check if it has a lock file and try to grab it.
+            # If that fails we need to move onto the next backup in
+            # the list.
+            lockFileDir = os.path.join(head,
+                                       os.path.pardir,
+                                       os.path.pardir,
+                                       rsyncsmf.RSYNCLOCKSUFFIX)
+            lockFile = os.path.join(lockFileDir, tail)
+
+            if not os.path.exists(lockFileDir):
+                os.makedirs(lockFileDir, 0755)
+            try:
+                lockFp = open(lockFile, 'w')
+                fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+            except IOError:
+                util.debug("Can't delete backup %s because it " \
+                           "is locked by another process." \
+                           "Skipping" % (dirName),
+                           self._verbose)
+                # Remove if from the remainder list
+                idx = bisect_left(remainder, [mtime, dirName])
+                del remainder[idx]
+                continue
+
+            trash = os.path.join(head,
+                                 os.path.pardir,
+                                 os.path.pardir,
+                                 rsyncsmf.RSYNCTRASHSUFFIX)
+            trashDir = os.path.join(trash, tail)
+
+            if not os.path.exists(trash):
+                os.makedirs(trash, 0755)
+
+            util.debug("Deleting rsync backup to recover space: %s"\
+                % (dirName), self._verbose)
+            os.rename(dirName, trashDir)
+            lockFp.close()
+            os.unlink(lockFile)
+            shutil.rmtree(trashDir)
+            # Remove the log file if it exists
+            logFile = os.path.join(head,
+                                   os.path.pardir,
+                                   os.path.pardir,
+                                   rsyncsmf.RSYNCLOGSUFFIX,
+                                   tail + ".log")
+            if os.path.exists(logFile):
+                os.unlink(logFile)
+            else:
+                util.debug("Expected to find log file %s when deleting %s " \
+                           "during space recovery" % (logFile, dirName),
+                           self._verbose)
+            # Remove dirName from the backup list
+            idx = bisect_left(self._backups, [mtime, dirName])
+            del self._backups[idx]
+            # Remove if from the remainder list too
+            idx = bisect_left(remainder, [mtime, dirName])
+            del remainder[idx]
+        return remainder
+
+    def backup_snapshot(self):
+        # First, check to see if the rsync destination
+        # directory is accessible.
+
+        if self._rsyncBaseDir == None:
+            util.debug("Backup target device is not " \
+                       "accessible right now: %s" \
+                       % (self._smfInst.get_target_dir()),
+                       self._verbose)
+            self._bus.rsync_unsynced(len(self._pendingList))
+            if self._mainLoop:
+                self._mainLoop.quit()
+            sys.exit(0)
+
+        # Extra paranoia
+        if self._validate_rsync_target(self._rsyncBaseDir) == False:
+            util.debug("Backup target directory does not " \
+                       "have a matching configuration key. " \
+                       "Possibly old or wrong device: %s" \
+                       % (self._keyFile),
+                       self._verbose)
+            self._bus.rsync_unsynced(len(self._pendingList))
+            if self._mainLoop:
+                self._mainLoop.quit()
+            sys.exit(0)
+
+        # Before getting started. Identify what needs to be cleaned up on 
+        # the backup target.
+        if self._tempSchedules == None:
+            self._get_temp_schedules()
+        
+        # Remove incompleteable partial backups, then find out what
+        # complete backups we already have on the target device
+        if self._started == False:
+            self._remove_dead_backups()
+            self._discover_backups()
+
+        if len(self._currentQueueSet) == 0:
+            # Means we are just getting started or have just completed
+            # backup of one full set of snapshots. Clear out anything
+            # we may have moved to the trash during the previous 
+            # backup set iterations.
+            self.empty_trash_folders()
+            # Refresh the pending list and build a new working set queue
+            self._pendingList = list_pending_snapshots(self._propName)
+            # Remove skipped items to avoid infinite looping.
+            for item in self._skipList:
+                try:
+                    self._pendingList.remove(item)
+                except ValueError:
+                    pass
+            if len(self._pendingList) == 0:
+                # If something was actually backed up, signal
+                # that it is now completed.
+                if self._started == True:
+                    self._bus.rsync_complete(self._rsyncBaseDir)
+                self._bus.rsync_synced()
+                # Nothing to do exit
+                if self._mainLoop:
+                    self._mainLoop.quit()
+                sys.exit(0)
+            else:
+                # Construct a new working set queue
+                # Identify the newest snapshot and then all
+                # snapshots with a matching snapshot label
+                self._queueLength = len(self._pendingList)
+                ctime,headSnapName = self._pendingList[0]
+                label = headSnapName.rsplit("@", 1)[1]
+                self._currentQueueSet = \
+                    [(ctime,snapName) for \
+                     ctime,snapName in self._pendingList if \
+                     snapName.rsplit("@", 1)[1] == label]
+
+
+        if len(self._backups) > 0:
+            oldestBackupTime, oldestBackup = self._backups[0]
+            qTime, qItem = self._currentQueueSet[0]
+
+            # If the backup device is nearly full, don't
+            # bother trying to backup anything unless it's
+            # newer than the oldest backup set already on
+            # the device.
+            # This avoids potential situations where if the
+            # backup device has severely limited capacity and
+            # older backups sets were in the queue, newer backups
+            # might get deleted in order to make room for older
+            # ones, creating a downward spiral.
+            capacity = util.get_filesystem_capacity(self._rsyncDir)
+            if capacity > self._cleanupThreshold:
+                # Find backups older than qTime that could in theory
+                # be deleted in order to make room for the curtent
+                # pending item.
+                deleteables = self._find_deleteable_backups(qTime)
+
+                if len(deleteables) == 0 and \
+                   qTime < oldestBackupTime:
+                    util.debug("%s has exceeded %d%% of its capacity. " \
+                                "Skipping pending backups prior to: " \
+                                "%s" % (self._rsyncDir,
+                                        self._cleanupThreshold,
+                                        time.ctime(oldestBackupTime)),
+                                self._verbose)
+                    if self._started == True:
+                        self._bus.rsync_complete(self._rsyncBaseDir)
+                    self._bus.rsync_synced()
+                    # Nothing to do exit
+                    if self._mainLoop:
+                        self._mainLoop.quit()
+                    sys.exit(0)
+
+        if self._started == False:
+            self._started = True
+            self._bus.rsync_started(self._rsyncBaseDir)
+
+        ctime,snapName = self._currentQueueSet[0]
+        snapshot = zfs.Snapshot(snapName, long(ctime))
+        # Make sure the snapshot didn't get destroyed since we last
+        # checked it.
+        remainingList = self._currentQueueSet[1:]
+        if snapshot.exists() == False:
+            util.debug("Snapshot: %s no longer exists. Skipping" \
+                        % (snapName), self._verbose)
+            self._currentQueueSet = remainingList
+            return True
+
+        # Place a hold on the snapshot so it doesn't go anywhere
+        # while rsync is trying to back it up.
+        snapshot.hold(self._propName)
+        self._queueLength -= 1
+        fs = zfs.Filesystem(snapshot.fsname)
+        sourceDir = None
+        if fs.is_mounted() == True:
+            # Get the mountpoint
+            mountPoint = fs.get_mountpoint()
+            sourceDir = "%s/.zfs/snapshot/%s" \
+                        % (mountPoint, snapshot.snaplabel)
+        else:
+            # If the filesystem is not mounted just skip it. If it's
+            # not mounted then nothing is being written to it. And
+            # we can just catch up with it again later if it doesn't
+            # get expired by time-sliderd
+            util.debug("%s is not mounted. Skipping." \
+                        % (snapshot.fsname), self._verbose)
+            snapshot.release(self._propName)
+            self._skipList.append(ctime, snapName)
+            self._currentQueueSet = remainingList
+            return True
+
+        # targetDir is the parent folder of all backups
+        # for a given filesystem
+        targetDir = os.path.join(self._rsyncDir,
+                                 snapshot.fsname,
+                                 rsyncsmf.RSYNCDIRSUFFIX)
+        # partialDir is a separate directory in which
+        # snapshots are initially backed up to. Upon successful
+        # completion they are moved to the backupDir.
+        partialDir = os.path.join(self._rsyncDir,
+                                  snapshot.fsname,
+                                  rsyncsmf.RSYNCPARTIALSUFFIX,
+                                  snapshot.snaplabel)
+        lockFileDir = os.path.join(self._rsyncDir,
+                                   snapshot.fsname,
+                                   rsyncsmf.RSYNCLOCKSUFFIX)
+        logDir = os.path.join(self._rsyncDir,
+                              snapshot.fsname,
+                              rsyncsmf.RSYNCLOGSUFFIX)
+        logFile = os.path.join(logDir,
+                               snapshot.snaplabel + ".log")
+
+        
+        # backupDir is the full directory path where the new
+        # backup will be located ie <targetDir>/<snapshot label>
+        backupDir = os.path.join(targetDir, snapshot.snaplabel)
+
+        # Figure out the closest previous backup. Since we
+        # backup newest first instead of oldest first it's
+        # determined as follows:
+        # If queued backup item is newer than the most recent
+        # backup on the backup target, use the most recent 
+        # backup as the incremental source.
+        # Othewise identify the backup on the device that is
+        # nearest to but newer than the queued backup.
+        nearestOlder = None
+        nearestNewer = None
+        dirList = []
+
+        if not os.path.exists(partialDir):
+            os.makedirs(partialDir, 0755)
+        if not os.path.exists(logDir):
+            os.makedirs(logDir, 0755)
+
+        if not os.path.exists(targetDir):
+            os.makedirs(targetDir, 0755)
+            # Add the new directory to our internal
+            # mtime dictionary and sorted list.
+            self._backupTimes[targetDir] = {}
+            insort(self._backupDirs, targetDir)
+        else:
+            for name,value in self._backupTimes[targetDir].items():
+                if ctime > value:
+                    if nearestOlder == None or \
+                       value > nearestOlder[1]:
+                        nearestOlder = [name, value]
+                else:
+                    if nearestNewer == None or \
+                       value < nearestNewer[1]:
+                        nearestNewer = [name, value]
+
+        os.chdir(targetDir)
+        link = None
+        linkDest = None
+        lockFile = None
+        lockFp = None
+        if nearestNewer:
+            link = nearestNewer[0]
+        elif nearestOlder:
+            link = nearestOlder[0]
+        if link:
+            linkDest = os.path.realpath(link)
+            # Create a lock for linkDest. We need to ensure that
+            # nautilus' restore view or the time-slider-delete
+            # GUI doesn't attempt to delete it or move it to the
+            # trash while it is being used by rsync for incremental
+            # backup.
+            lockFile = os.path.join(lockFileDir,
+                                    link + ".lock")
+
+            if not os.path.exists(lockFileDir):
+                os.makedirs(lockFileDir, 0755)
+
+            try:
+                lockFp = open(lockFile, 'w')
+                fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+            except IOError:
+                util.debug("Can't perform incremental rsync of %s because " \
+                           "unable to obtain exclusive lock on incremental " \
+                           "backup reference point: %s. Exiting" \
+                           % (lockFile), self._verbose)
+                os.chdir("/")
+                snapshot.release(self._propName)
+                sys.exit(1)
+
+        self._rsyncProc = RsyncProcess(sourceDir,
+                                       partialDir,
+                                       linkDest,
+                                       self._rsyncVerbose,
+                                       logFile)
+
+        # Notify the applet of current status via dbus
+        self._bus.rsync_current(snapshot.name, self._queueLength)
+
+        # Set umask temporarily so that rsync backups are read-only to
+        # the owner by default. Rync will override this to match the
+        # permissions of each snapshot as appropriate.
+        origmask = os.umask(0222)
+        util.debug("Starting rsync backup of '%s' to: %s" \
+                   % (sourceDir, partialDir),
+                   self._verbose)
+        self._rsyncProc.start_backup()
+
+        warningDone = False
+        while self._rsyncProc.is_alive():
+            if len(self._backups) > 0:
+                # Monitor backup target capacity while we wait for rsync.
+                capacity = util.get_filesystem_capacity(self._rsyncDir)
+                if capacity > self._cleanupThreshold:
+                    # Find backups older than qTime that could in theory
+                    # be deleted in order to make room for the curtent
+                    # pending item.
+                    deleteables = self._find_deleteable_backups(qTime)
+                    # Only generate annoying debug message once instead of
+                    # every 5 seconds.
+                    if warningDone == False:
+                        util.debug("Backup device capacity exceeds %d%%. " \
+                                   "Found %d deleteable backups for space " \
+                                   "recovery." \
+                                    % (capacity, len(deleteables)),
+                                    self._verbose)
+                        warningDone = True
+                    if len(deleteables) > 0:
+                        deleteables = self._recover_space(deleteables)
+            time.sleep(5)
+
+        try:
+            self._rsyncProc._check_exit_code()
+        except (RsyncTransferInterruptedError,
+                RsyncTargetDisconnectedError,
+                RsyncSourceVanishedError) as e:
+            os.chdir("/")
+            snapshot.release(self._propName)
+            util.log_error(syslog.LOG_ERR, str(e))
+            # These are recoverable, so exit for now and try again
+            # later
+            sys.exit(-1)
+
+        except RsyncError as e:
+            # If the backup device went offline we need to chdir
+            # out of it or running further commands might fail.
+            os.chdir("/")
+            util.log_error(syslog.LOG_ERR,
+                           "Unexpected rsync error encountered: \n" + \
+                           str(e))
+            util.log_error(syslog.LOG_ERR,
+                           "Rsync log file location: %s" \
+                           % (os.path.abspath(logFile)))
+            util.log_error(syslog.LOG_ERR,
+                           "Placing plugin into maintenance mode")
+            self._smfInst.mark_maintenance()
+            snapshot.release(self._propName)
+            sys.exit(-1)
+
+        finally:
+            if lockFp:
+                lockFp.close()
+                os.unlink(lockFile)
+
+        util.debug("Rsync process exited", self._verbose)
+        os.umask(origmask)
+
+        # Move the completed backup from the partial dir to the
+        # the propert backup directory 
+        util.debug("Renaming completed backup from %s to %s" \
+                   % (partialDir, backupDir), self._verbose)
+        os.rename(partialDir, backupDir)
+
+        # Reset the mtime and atime properties of the backup directory so that
+        # they match the snapshot creation time. This is extremely important
+        # because the backup mechanism relies on it to determine backup times
+        # and nearest matches for incremental rsync (linkDest)
+        os.utime(backupDir, (long(ctime), long(ctime)))
+        # Update the dictionary and time sorted list with ctime also
+        self._backupTimes[targetDir][snapshot.snaplabel] = long(ctime)
+        insort(self._backups, [long(ctime), os.path.abspath(backupDir)]) 
+        snapshot.set_user_property(self._propName, "completed")
+        snapshot.release(self._propName)
+        self._currentQueueSet = remainingList
+        
+        # Now is a good time to clean out the directory:
+        # Check to see if the backup just completed belonged to an
+        # auto-snapshot schedule and whether older backups should get
+        # deleted.
+        if snapshot.snaplabel.find(autosnapsmf.SNAPLABELPREFIX) == 0:
+            tempSchedule = None
+            label = None
+            for schedule in self._tempSchedules:
+                label = "%s%s%s" % (autosnapsmf.SNAPLABELPREFIX,
+                                    self._labelSeparator,
+                                    schedule[0])
+                if snapshot.snaplabel.find(label) == 0:
+                    tempSchedule = schedule
+                    break
+            if tempSchedule == None:
+                # Backup doesn't belong to a temporary schedule so 
+                # nothing left to do
+                return True
+
+            keep = tempSchedule[3] # [schedule,interval,period,keep]
+            schedBackups = [d for d in os.listdir(targetDir) if 
+                            d.find(label) == 0]
+            
+
+            schedBackups = [d for d in dirList if 
+                            d.find(label) == 0]
+            # The minimum that can be kept around is one:
+            # keeping zero is stupid since it might trigger
+            # a total replication rather than an incremental
+            # rsync replication.
+            if len(schedBackups) <= 1:
+                return True
+            if len(schedBackups) <= keep:
+                return True
+
+            sortedBackupList = []
+            for backup in schedBackups:
+                stInfo = os.stat(backup)
+                # List is sorted by mtime, oldest first
+                insort(sortedBackupList, [stInfo.st_mtime, backup])
+            purgeList = sortedBackupList[0:-keep]
+
+            trash = os.path.join(self._rsyncDir,
+                                 snapshot.fsname,
+                                 rsyncsmf.RSYNCTRASHSUFFIX)
+            if not os.path.exists(trash):
+                os.makedirs(trash, 0755)
+            for mtime,dirName in purgeList:
+                trashDir = os.path.join(trash,
+                                        dirName)
+                # Perform a final sanity check to make sure a backup
+                # directory and not a system directory is being purged.
+                # If it doesn't contain the RSYNCDIRSUFFIX string a
+                # ValueError will be raised.
+                try:
+                    os.getcwd().index(rsyncsmf.RSYNCDIRSUFFIX)
+                    lockFp = None
+                    lockFile = os.path.join(lockFileDir,
+                                            dirName + ".lock")
+
+                    if not os.path.exists(lockFileDir):
+                        os.makedirs(lockFileDir, 0755)
+
+                    try:
+                        lockFp = open(lockFile, 'w')
+                        fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+                    except IOError:
+                        util.debug("Can't move expired  backup %s to trash " \
+                                   "because it is locked by another " \
+                                   "process. Skipping" % (dirName),
+                                   self._verbose)
+
+                    util.debug("Moving expired rsync backup to trash:" \
+                               " %s -> %s" % (dirName, trash),
+                               self._verbose)
+                    os.rename(dirName, trashDir)
+                    # Release and delete lock file
+                    lockFp.close()
+                    os.unlink(lockFile)
+                    # Remove its mtime key/value from self._backupTimes
+                    del self._backupTimes[targetDir][dirName]
+                    # Log file needs to be deleted too.
+                    logFile = os.path.join(logDir,
+                                            dirName + ".log")
+                    try:
+                        os.stat(logFile)
+                        util.debug("Deleting rsync log file: %s" \
+                                    % (os.path.abspath(logFile)),
+                                    self._verbose)
+                        os.unlink(logFile)
+                    except OSError:
+                        util.debug("Expected rsync log file not " \
+                                    "found: %s"\
+                                    % (os.path.abspath(logFile)),
+                                    self._verbose)
+                                                
+                except ValueError:
+                    util.log_error(syslog.LOG_ALERT,
+                                    "Invalid attempt to delete " \
+                                    "non-backup directory: %s\n" \
+                                    "Placing plugin into " \
+                                    "maintenance state" % (dirName))
+                    self._smfInst.mark_maintenance()
+                    sys.exit(-1)
+        return True
+
+def release_held_snapshots(propName):
+    """
+    Releases dangling user snapshot holds that could
+    have occured during abnormal termination of a
+    previous invocation of this command during a 
+    previous rsync transfer.
+    Returns a list of snapshots that had holds mathcing
+    propName released.
+    """ 
+    # First narrow the list down by finding snapshots
+    # with userref count > 0
+    heldList = []
+    released = []
+    cmd = [zfs.ZFSCMD, "list", "-H",
+           "-t", "snapshot",
+           "-o", "userrefs,name"]
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        holdCount,name = line.split()
+        if int(holdCount) > 0:
+            heldList.append(name)
+    # Now check to see if any of those holds
+    # match 'propName'
+    for snapName in heldList:
+        snapshot = zfs.Snapshot(snapName)
+        holds = snapshot.holds()
+        try:
+            holds.index(propName)
+            snapshot.release(propName)
+            released.append(snapName)
+        except ValueError:
+            pass
+    return released
+
+
+def backup_name_to_snapshot_name(path):
+    """Reconstructs the original snapshot based on an
+       rsync backup's full path.
+       Returns a zfs snapshot name.
+    """
+    head,snapLabel = os.path.split(path)
+    sys,nodeName,rel,ver,arch = os.uname()
+    prefix = os.path.join(rsyncsmf.RSYNCDIRPREFIX,
+                          nodeName + '/')
+    suffix = rsyncsmf.RSYNCDIRSUFFIX
+
+    rsyncBaseDir,tail = head.split(prefix , 1)
+    fsName = tail.split(suffix, 1)[0].rstrip('/')
+    snapshotName = "%s@%s" % (fsName, snapLabel)
+    return snapshotName
+
+def list_pending_snapshots(propName):
+    """
+    Lists all snaphots which have 'propName" set locally.
+    Resulting list is returned sorted in descending order
+    of creation time (ie.newest first).
+    Each element in the returned list is tuple of the form:
+    [creationtime, snapshotname]
+    """
+    results = []
+    snaplist = []
+    sortsnaplist = []
+    # The process for backing up snapshots is:
+    # Identify all filesystem snapshots that have the (propName)
+    # property set to "pending" on them. Back them up starting
+    # with the oldest first.
+    #
+    # Unfortunately, there's no single zfs command that can
+    # output a locally set user property and a creation timestamp
+    # in one go. So this is done in two passes. The first pass
+    # identifies snapshots that are tagged as "pending". The 
+    # second pass uses the filtered results from the first pass
+    # as arguments to zfs(1) to get creation times.
+    cmd = [zfs.ZFSCMD, "get", "-H",
+            "-s", "local",
+            "-o", "name,value",
+            propName]
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        if len(line) > 1:
+            line = line.split()
+            results.append(line)
+
+    for name,value in results:
+        if value != "pending":
+            # Already backed up. Skip it."
+            continue
+        if name.find('@') == -1:
+            # Not a snapshot, and should not be set on a filesystem/volume
+            # Ignore it.
+            util.log_error(syslog.LOG_WARNING,
+                           "Dataset: %s shouldn't have local property: %s" \
+                           % (name, propName))
+            continue
+        snaplist.append(name)
+
+    # Nothing pending so just return the empty list
+    if len(snaplist) == 0:
+        return snaplist
+
+    cmd = [zfs.ZFSCMD, "get", "-p", "-H",
+            "-o", "value,name",
+            "creation"]
+    cmd.extend(snaplist)
+
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        ctimeStr,name = line.split()
+        insort(sortsnaplist, tuple((long(ctimeStr), name)))
+    sortsnaplist.reverse()
+    return sortsnaplist
+
+
+def main(argv):
+    # This command needs to be executed by the super user (root) to
+    # ensure that rsync has permissions to access all local filesystem
+    # snapshots and to replicate permissions and ownership on the target
+    # device
+    if os.geteuid() != 0:
+        head,tail = os.path.split(sys.argv[0])
+        sys.stderr.write(tail + " can only be executed by root")
+        sys.exit(-1)
+
+    # This process needs to be run as a system wide single instance
+    # only at any given time. So create a lockfile in /tmp and try
+    # to obtain an exclusive lock on it. If we can't then another 
+    # instance is running and already has a lock on it so just exit.
+    lockFileDir = os.path.normpath(tempfile.gettempdir() + '/' + \
+                                                       ".time-slider")
+    if not os.path.exists(lockFileDir):
+            os.makedirs(lockFileDir, 0755)
+    lockFile = os.path.join(lockFileDir, 'rsync-backup.lock')
+
+    lockFp = open(lockFile, 'w')
+    try:
+        fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+    except IOError:
+        sys.exit(2)
+
+    # The SMF fmri of the time-slider plugin instance associated with
+    # this command needs to be supplied as the argument immeditately
+    # proceeding the command. ie. argv[1]
+    try:
+        pluginFMRI = sys.argv[1]
+    except IndexError:
+        # No FMRI provided. Probably a user trying to invoke the command
+        # from the command line.
+        sys.stderr.write("No time-slider plugin SMF instance FMRI defined. " \
+                         "This plugin does not support command line " \
+                         "execution. Exiting\n")
+        sys.exit(-1)
+
+    # Open up a syslog session
+    syslog.openlog(sys.argv[0], 0, syslog.LOG_DAEMON)
+
+    gobject.threads_init()
+    # Tell dbus to use the gobject mainloop for async ops
+    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+    dbus.mainloop.glib.threads_init()
+    # Register a bus name with the system dbus daemon
+    sysbus = dbus.SystemBus()
+    busName = dbus.service.BusName("org.opensolaris.TimeSlider.plugin.rsync", sysbus)
+    dbusObj = dbussvc.RsyncBackup(sysbus, \
+        "/org/opensolaris/TimeSlider/plugin/rsync")
+
+    mainLoop = gobject.MainLoop()
+    backupQueue = BackupQueue(pluginFMRI, dbusObj, mainLoop)
+    gobject.idle_add(backupQueue.backup_snapshot)
+    mainLoop.run()
+    sys.exit(0)
+
diff --git a/usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py b/usr/share/time-slider/lib/plugin/rsync/rsyncsmf.py
new file mode 100755 (executable)
index 0000000..e29ee8e
--- /dev/null
@@ -0,0 +1,89 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import subprocess
+import threading
+#from string import letters, digits
+from plugin import pluginsmf
+
+RSYNCPROPGROUP = "rsync"
+RSYNCDIRPREFIX = "TIMESLIDER"
+RSYNCDIRSUFFIX = ".time-slider/rsync"
+RSYNCPARTIALSUFFIX = ".time-slider/.rsync-partial"
+RSYNCTRASHSUFFIX = ".time-slider/.trash"
+RSYNCLOCKSUFFIX = ".time-slider/.rsync-lock"
+RSYNCLOGSUFFIX = ".time-slider/.rsync-log"
+RSYNCCONFIGFILE = ".rsync-config"
+RSYNCFSTAG = "org.opensolaris:time-slider-rsync"
+
+class RsyncSMF(pluginsmf.PluginSMF):
+
+    def __init__(self, instanceName):
+        pluginsmf.PluginSMF.__init__(self, instanceName)
+        self._archivedSchedules = None
+
+    def get_cleanup_threshold(self):
+        result = self.get_prop(RSYNCPROPGROUP, "cleanup_threshold").strip()
+        return int(result)
+
+    def get_target_dir(self):
+        result = self.get_prop(RSYNCPROPGROUP, "target_dir").strip()
+        # Strip out '\' characters inserted by svcprop
+        return result.strip().replace('\\', '')
+
+    def get_target_key(self):
+        return self.get_prop(RSYNCPROPGROUP, "target_key").strip()
+
+    def set_target_dir(self, path):
+        self.set_string_prop(RSYNCPROPGROUP, "target_dir", path)
+
+    def set_target_key(self, key):
+        self.set_string_prop(RSYNCPROPGROUP, "target_key", key)
+
+    def get_archived_schedules(self):
+        #FIXME Use mutex locking to make MT-safe
+        if self._archivedSchedules == None:
+            self._archivedSchedules = []
+            value = self.get_prop(RSYNCPROPGROUP, "archived_schedules")
+            
+            # Strip out '\' characters inserted by svcprop
+            archiveList = value.strip().replace('\\', '').split(',')
+            for schedule in archiveList:
+                self._archivedSchedules.append(schedule.strip())
+        return self._archivedSchedules
+
+    def get_rsync_verbose(self):
+        value = self.get_prop(RSYNCPROPGROUP, "verbose")
+        if value == "true":
+            return True
+        else:
+            return False
+
+    def __str__(self):
+        ret = "SMF Instance:\n" +\
+              "\tName:\t\t\t%s\n" % (self.instance_name) +\
+              "\tState:\t\t\t%s\n" % (self.svcstate) + \
+              "\tTriggers:\t\t%s\n" % str(self.get_triggers()) + \
+              "\tTarget Dir:\t%s\n" % self.get_target_dir() + \
+              "\tVerbose:\t\t\'%s\'" % str((self.get_verbose()))
+        return ret
+
diff --git a/usr/share/time-slider/lib/plugin/rsync/trigger.py b/usr/share/time-slider/lib/plugin/rsync/trigger.py
new file mode 100644 (file)
index 0000000..0616cb8
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import sys
+import subprocess
+import syslog
+
+import rsyncsmf
+from time_slider import util, smf, zfs
+
+# Set to True if SMF property value of "plugin/command" is "true"
+verboseprop = "plugin/verbose"
+propbasename = "org.opensolaris:time-slider-plugin"
+
+
+def main(argv):
+    # Check that appropriate environment variables have been
+    # provided by time-sliderd
+    #
+    # The label used for the snapshot set just taken, ie. the
+    # component proceeding the "@" in the snapshot name
+    snaplabel = os.getenv("AUTOSNAP_LABEL")
+    # The SMF fmri of the auto-snapshot instance corresponding to
+    # the snapshot set just taken.
+    snapfmri = os.getenv("AUTOSNAP_FMRI")
+    # The SMF fmri of the time-slider plugin instance associated with
+    # this command.
+    pluginfmri = os.getenv("PLUGIN_FMRI")
+
+    if pluginfmri == None:
+        sys.stderr.write("No time-slider plugin SMF instance FMRI defined. " \
+                         "This plugin does not support command line "
+                         "execution. Exiting\n")
+        sys.exit(-1)
+    syslog.openlog(pluginfmri, 0, syslog.LOG_DAEMON)
+
+    cmd = [smf.SVCPROPCMD, "-p", verboseprop, pluginfmri]
+    outdata,errdata = util.run_command(cmd)
+    if outdata.rstrip() == "true":
+        verbose = True
+    else:
+        verbose = False
+
+    if snaplabel == None:
+        log_error(syslog.LOG_ERR,
+                  "No snapshot label provided. Exiting")
+        sys.exit(-1)
+    if snapfmri == None:
+        log_error(syslog.LOG_ERR,
+                  "No auto-snapshot SMF instance FMRI provided. Exiting")
+        sys.exit(-1)
+
+    schedule = snapfmri.rsplit(':', 1)[1]
+    plugininstance = pluginfmri.rsplit(':', 1)[1]
+
+    # The user property/tag used when tagging and holding zfs datasets
+    propname = "%s:%s" % (propbasename, plugininstance)
+
+    # Identifying snapshots is a 3 stage process.
+    #
+    # First: identify all snapshots matching the AUTOSNAP_LABEL
+    # value passed in by the time-slider daemon.
+    #
+       # Second: Filter out snapshots of volumes, since rsync can only
+    # back up filesystems.
+    #
+    # Third: we need to filter the results and ensure that the
+    # filesystem corresponding to each snapshot is actually
+    # tagged with the property (com.sun:auto-snapshot<:schedule>)
+    #
+    # This is necessary to avoid confusion whereby a snapshot might
+    # have been sent|received from one zpool to another on the same
+    # system. The received snapshot will show up in the first pass
+    # results but is not actually part of the auto-snapshot set
+    # created by time-slider. It also avoids incorrectly placing
+    # zfs holds on the imported snapshots.
+
+
+    datasets = zfs.Datasets()
+    candidates = datasets.list_snapshots(snaplabel)
+    autosnapsets = datasets.list_auto_snapshot_sets(schedule)
+    autosnapfs = [name for [name,mount] in datasets.list_filesystems() \
+                   if name in autosnapsets]
+    snappeddatasets = []
+    snapnames = [name for [name,ctime] in candidates \
+                 if name.split('@',1)[0] in autosnapfs]
+
+    # Mark the snapshots with a user property. Doing this instead of
+    # placing a physical hold on the snapshot allows time-slider to
+    # expire the snapshots naturally or destroy them if a zpool fills
+    # up and triggers a remedial cleanup.
+    # It also prevents the possiblity of leaving snapshots lying around
+    # indefinitely on the system if the plugin SMF instance becomes 
+    # disabled or having to release a pile of held snapshots.
+    # We set org.opensolaris:time-slider-plugin:<instance> to "pending",
+    # indicate
+    snapshots = []
+    for snap in snapnames:
+        snapshot = zfs.Snapshot(snap)
+        fs = zfs.Filesystem(snapshot.fsname)
+        if fs.get_user_property(rsyncsmf.RSYNCFSTAG) == "true":
+            if fs.is_mounted() == True:
+                snapshot.set_user_property(propname, "pending")
+                util.debug("Marking %s as pending rsync" % (snap), verbose)
+            else:
+                util.debug("Ignoring snapshot of unmounted fileystem: %s" \
+                           % (snap), verbose)
+
+def maintenance(svcfmri):
+    log_error(syslog.LOG_ERR,
+              "Placing plugin into maintenance state")
+    cmd = [smf.SVCADMCMD, "mark", "maintenance", svcfmri]
+    subprocess.Popen(cmd, close_fds=True)
+
+def log_error(loglevel, message):
+    syslog.syslog(loglevel, message + '\n')
+    sys.stderr.write(message + '\n')
+
diff --git a/usr/share/time-slider/lib/plugin/zfssend/__init__.py b/usr/share/time-slider/lib/plugin/zfssend/__init__.py
new file mode 100644 (file)
index 0000000..a2667b2
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, pardir))
+
diff --git a/usr/share/time-slider/lib/plugin/zfssend/zfssend.py b/usr/share/time-slider/lib/plugin/zfssend/zfssend.py
new file mode 100644 (file)
index 0000000..42f3975
--- /dev/null
@@ -0,0 +1,241 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import sys
+import subprocess
+import syslog
+from bisect import insort
+
+import time_slider.util
+import time_slider.smf
+import time_slider.zfs
+
+# Set to True if SMF property value of "plugin/command" is "true"
+verboseprop = "plugin/verbose"
+propbasename = "org.opensolaris:time-slider-plugin"
+print _("Do I work?")
+
+def main(argv):
+
+    # Check appropriate environment variables habe been supplied
+    # by time-slider
+    #
+    # The label used for the snapshot set just taken, ie. the
+    # component proceeding the "@" in the snapshot name
+    snaplabel = os.getenv("AUTOSNAP_LABEL")
+    # The SMF fmri of the auto-snapshot instance corresponding to
+    # the snapshot set just taken.
+    snapfmri = os.getenv("AUTOSNAP_FMRI")
+    # The SMF fmri of the time-slider plugin instance associated with
+    # this command.
+    pluginfmri = os.getenv("PLUGIN_FMRI")
+
+    if pluginfmri == None:
+        sys.stderr.write("No time-slider plugin SMF instance FMRI defined. " \
+                         "This plugin does not support command line "
+                         "execution. Exiting\n")
+        sys.exit(-1)
+    syslog.openlog(pluginfmri, 0, syslog.LOG_DAEMON)
+
+    cmd = [smf.SVCPROPCMD, "-p", verboseprop, pluginfmri]
+    outdata,errdata = util.run_command(cmd)
+    if outdata.rstrip() == "true":
+        verbose = True
+    else:
+        verbose = False
+
+    if snaplabel == None:
+        log_error(syslog.LOG_ERR,
+                  "No snapshot label defined. Exiting")
+        sys.exit(-1)
+    if snapfmri == None:
+        log_error(syslog.LOG_ERR,
+                  "No auto-snapshot SMF instance FMRI defined. Exiting")
+        sys.exit(-1)
+
+    schedule = snapfmri.rsplit(':', 1)[1]
+    plugininstance = pluginfmri.rsplit(':', 1)[1]
+
+    # The user property/tag used when tagging and holding zfs datasets
+    propname = "%s:%s" % (propbasename, plugininstance)
+
+    # Identifying snapshots is a two stage process.
+    #
+    # First: identify all snapshots matching the AUTOSNAP_LABEL
+    # value passed in by the time-slider daemon.
+    #
+    # Second: we need to filter the results and ensure that the
+    # filesystem/voluem corresponding to each snapshot is actually
+    # tagged with the property (com.sun:auto-snapshot<:schedule>)
+    #
+    # This is necessary to avoid confusion whereby a snapshot might
+    # have been sent|received from one zpool to another on the same
+    # system. The received snapshot will show up in the first pass
+    # results but is not actually part of the auto-snapshot set
+    # created by time-slider. It also avoids incorrectly placing
+    # zfs holds on the imported snapshots.
+
+    datasets = zfs.Datasets()
+    candidates = datasets.list_snapshots(snaplabel)
+    originsets = datasets.list_auto_snapshot_sets(schedule)
+    snappeddatasets = []
+    snapnames = [name for [name,ctime] in candidates \
+                 if name.split('@',1)[0] in originsets]
+
+
+    # Place a hold on the the newly created snapshots so
+    # they can be backed up without fear of being destroyed
+    # before the backup gets a chance to complete.
+    for snap in snapnames:
+        snapshot = zfs.Snapshot(snap)
+        holds = snapshot.holds()
+        try:
+            holds.index(propname)
+        except ValueError:
+            util.debug("Placing hold on %s" % (snap), verbose)
+            snapshot.hold(propname)
+        datasetname = snapshot.fsname
+        # Insert datasetnames in alphabetically sorted order because
+        # zfs receive falls over if it receives a child before the
+        # parent if the "-F" option is not used.
+        insort(snappeddatasets, datasetname)
+
+    # Find out the receive command property value
+    cmd = [smf.SVCPROPCMD, "-c", "-p", "receive/command", pluginfmri]
+    outdata,errdata = util.run_command(cmd)
+    # Strip out '\' characters inserted by svcprop
+    recvcmd = outdata.strip().replace('\\', '').split()
+
+    # Check to see if the receive command is accessible and executable
+    try:
+        statinfo = os.stat(recvcmd[0])
+        other_x = (statinfo.st_mode & 01)
+        if other_x == 0:
+            log_error(syslog.LOG_ERR,
+                      "Plugin: %s: Configured receive/command is not " \
+                      "executable: %s" \
+                      % (pluginfmri, outdata))
+            maintenance(pluginfmri)
+            sys.exit(-1)
+    except OSError:
+        log_error(syslog.LOG_ERR,
+                  "Plugin: %s: Can not access the configured " \
+                  "receive/command: %s" \
+                  % (pluginfmri, outdata)) 
+        maintenance(pluginfmri)   
+        sys.exit(-1)
+
+    for dataset in snappeddatasets:
+        sendcmd = None
+        prevsnapname = None
+        ds = zfs.ReadableDataset(dataset)
+        prevlabel = ds.get_user_property(propname)
+
+        snapname = "%s@%s" % (ds.name, snaplabel)
+        if (prevlabel == None or len(prevlabel) == 0):
+            # No previous backup - send a full replication stream
+            sendcmd = [zfs.ZFSCMD, "send", snapname]
+            util.debug("No previous backup registered for %s" % ds.name, verbose)
+        else:
+            # A record of a previous backup exists.
+            # Check that it exists to enable send of an incremental stream.
+            prevsnapname = "%s@%s" % (ds.name, prevlabel)
+            util.debug("Previously sent snapshot: %s" % prevsnapname, verbose)
+            prevsnap = zfs.Snapshot(prevsnapname)
+            if prevsnap.exists():
+                sendcmd = [zfs.ZFSCMD, "send", "-i", prevsnapname, snapname]
+            else:
+                # This should not happen under normal operation since we
+                # place a hold on the snapshot until it gets sent. So
+                # getting here suggests that something else released the
+                # hold on the snapshot, allowing it to get destroyed
+                # prematurely.
+                log_error(syslog.LOG_ERR,
+                          "Previously sent snapshot no longer exists: %s" \
+                          % prevsnapname)
+                maintenance(pluginfmri)
+                sys.exit(-1)
+        
+        
+        # Invoke the send and receive commands via pfexec(1) since
+        # we are not using the role's shell to take care of that
+        # for us.
+        sendcmd.insert(0, smf.PFCMD)
+        recvcmd.insert(0, smf.PFCMD)
+
+        try:
+            sendP = subprocess.Popen(sendcmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+            recvP = subprocess.Popen(recvcmd,
+                                     stdin=sendP.stdout,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+
+            recvout,recverr = recvP.communicate()
+            recverrno = recvP.wait()
+            sendout,senderr = sendP.communicate()
+            senderrno = sendP.wait()
+
+            if senderrno != 0:
+                raise RuntimeError, "Send command: %s failed with exit code" \
+                                    "%d. Error message: \n%s" \
+                                    % (str(sendcmd), senderrno, senderr)
+            if recverrno != 0:
+                raise RuntimeError, "Receive command %s failed with exit " \
+                                    "code %d. Error message: \n%s" \
+                                    % (str(recvcmd), recverrno, recverr)
+
+            if prevsnapname != None:
+                util.debug("Releasing hold on %s" % (prevsnapname), verbose)
+                snapshot = zfs.Snapshot(prevsnapname)
+                util.debug("Releasing hold on previous snapshot: %s" \
+                      % (prevsnapname),
+                      verbose)
+                snapshot.release(propname)
+        except Exception, message:
+            log_error(syslog.LOG_ERR,
+                      "Error during snapshot send/receive operation: %s" \
+                      % (message))
+
+            maintenance(pluginfmri)
+            sys.exit(-1)            
+
+        # Finally, after success, make a record of the latest backup
+        # and release the old snapshot.
+        ds.set_user_property(propname, snaplabel)
+        util.debug("Sending of \"%s\"snapshot streams completed" \
+              % (snaplabel),
+              verbose)
+
+def maintenance(svcfmri):
+    log_error(syslog.LOG_ERR,
+              "Placing plugin into maintenance state")
+    cmd = [smf.SVCADMCMD, "mark", "maintenance", svcfmri]
+    subprocess.Popen(cmd, close_fds=True)
+
+def log_error(loglevel, message):
+    syslog.syslog(loglevel, message + '\n')
+    sys.stderr.write(message + '\n')
+
diff --git a/usr/share/time-slider/lib/time_slider/.swp b/usr/share/time-slider/lib/time_slider/.swp
new file mode 100644 (file)
index 0000000..7d10ede
Binary files /dev/null and b/usr/share/time-slider/lib/time_slider/.swp differ
diff --git a/usr/share/time-slider/lib/time_slider/__init__.py b/usr/share/time-slider/lib/time_slider/__init__.py
new file mode 100755 (executable)
index 0000000..4d7d17c
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = abspath(join(dirname(__file__), pardir, pardir))
+LOCALE_PATH = join('/usr', 'share', 'locale')
+RESOURCE_PATH = join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the gettext system and locales
+import gettext
+import locale
+
+locale.setlocale(locale.LC_ALL, '')
+gettext.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gettext.textdomain(GETTEXT_DOMAIN)
+
+# register the gettext function for the whole interpreter as "_"
+import __builtin__
+__builtin__._ = gettext.gettext
+
+
+
diff --git a/usr/share/time-slider/lib/time_slider/applet.py b/usr/share/time-slider/lib/time_slider/applet.py
new file mode 100755 (executable)
index 0000000..7d722a6
--- /dev/null
@@ -0,0 +1,645 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import subprocess
+import threading
+import gobject
+import dbus
+import dbus.decorators
+import dbus.glib
+import dbus.mainloop
+import dbus.mainloop.glib
+import gio
+import gtk
+import pygtk
+import pynotify
+
+from time_slider import util, rbac
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import backup, rsyncsmf
+
+class Note:
+    _iconConnected = False
+
+    def __init__(self, icon, menu):
+        self._note = None
+        self._msgDialog = None
+        self._menu = menu
+        self._icon = icon
+        if Note._iconConnected == False:
+            self._icon.connect("popup-menu", self._popup_menu)
+            Note._iconConnected = True
+        self._icon.set_visible(True)
+
+    def _popup_menu(self, icon, button, time):
+        if button == 3:
+            # Don't popup an empty menu
+            if len(self._menu.get_children()) > 0:
+                self._menu.popup(None, None,
+                                 gtk.status_icon_position_menu,
+                                 button, time, icon)
+
+    def _dialog_response(self, dialog, response):
+        dialog.destroy()
+
+    def _notification_closed(self, notifcation):
+        self._note = None
+        self._icon.set_blinking(False)
+
+    def _show_notification(self):
+        if self._icon.is_embedded() == True:
+            self._note.attach_to_status_icon(self._icon)
+        self._note.show()
+        return False
+
+    def _connect_to_object(self):
+        pass
+
+    def refresh(self):
+        pass
+
+    def _watch_handler(self, new_owner = None):
+        if new_owner == None or len(new_owner) == 0:
+            pass
+        else:
+            self._connect_to_object()
+
+    def _setup_icon_for_note(self, themed=None):
+        if themed:
+            iconList = themed.get_names()
+        else:
+            iconList = ['gnome-dev-harddisk']
+
+        iconTheme = gtk.icon_theme_get_default()
+        iconInfo = iconTheme.choose_icon(iconList, 48, 0)
+        pixbuf = iconInfo.load_icon()
+
+        self._note.set_category("device")
+        self._note.set_icon_from_pixbuf(pixbuf)
+
+
+class RsyncNote(Note):
+
+    def __init__(self, icon, menu):
+        Note.__init__(self, icon, menu)
+        dbus.bus.NameOwnerWatch(bus,
+                                "org.opensolaris.TimeSlider.plugin.rsync",
+                                self._watch_handler)
+
+        self.smfInst = rsyncsmf.RsyncSMF("%s:rsync" \
+                                         % (plugin.PLUGINBASEFMRI))
+        self._lock = threading.Lock()
+        self._masterKey = None
+        sys,self._nodeName,rel,ver,arch = os.uname()
+        # References to gio.File and handler_id of a registered
+        # monitor callback on gio.File
+        self._fm = None
+        self._fmID = None
+        # References to gio.VolumeMonitor and handler_ids of
+        # registered mount-added and mount-removed callbacks.
+        self._vm = None
+        self._vmAdd = None
+        self._vmRem = None
+        # Every time the rsync backup script runs it will
+        # register with d-bus and trigger self._watch_handler().
+        # Use this variable to keep track of it's running status.
+        self._scriptRunning = False
+        self._targetDirAvail = False
+        self._syncNowItem = gtk.MenuItem(_("Update Backups Now"))
+        self._syncNowItem.set_sensitive(False)
+        self._syncNowItem.connect("activate",
+                                  self._sync_now)
+        self._menu.append(self._syncNowItem)
+
+        self.refresh()
+
+    def _validate_rsync_target(self, path):
+        """
+           Tests path to see if it is the pre-configured
+           rsync backup device path.
+           Returns True on success, otherwise False
+        """
+        if not os.path.exists(path):
+            return False
+        testDir = join(path,
+                       rsyncsmf.RSYNCDIRPREFIX,
+                       self._nodeName)
+        testKeyFile = join(path,
+                           rsyncsmf.RSYNCDIRPREFIX,
+                           rsyncsmf.RSYNCCONFIGFILE)
+        if os.path.exists(testDir) and \
+            os.path.exists(testKeyFile):
+            testKeyVal = None
+            f = open(testKeyFile, 'r')
+            for line in f.readlines():
+                key, val = line.strip().split('=')
+                if key.strip() == "target_key":
+                    targetKey = val.strip()
+                    break
+            f.close()
+            if targetKey == self._masterKey:
+                return True
+        return False
+
+    def _setup_monitor(self):
+        # Disconnect any previously registered signal
+        # handlers
+        if self._fm:
+            self._fm.disconnect(self._fmID)
+            self._fm = None
+
+        useVolMonitor = False        
+
+        # We always compare against masterKey to validate
+        # an rsync backup device.
+        self._masterKey = self.smfInst.get_target_key()
+        self._baseTargetDir = None
+        online = False
+
+        self._masterTargetDir = self.smfInst.get_target_dir()
+
+        if self._validate_rsync_target(self._masterTargetDir) == True:
+            self._baseTargetDir = self._masterTargetDir
+            online = True
+
+        if self._vm == None:
+            self._vm = gio.volume_monitor_get()
+
+        # If located, see if it's also managed by the volume monitor.
+        # Or just try to find it otherwise.
+        mounts = self._vm.get_mounts()
+        for mount in mounts:
+            root = mount.get_root()
+            path = root.get_path()
+            if self._baseTargetDir != None and \
+                path == self._baseTargetDir:
+                # Means the directory we found is gio monitored,
+                # so just monitor it using gio.VolumeMonitor.
+                useVolMonitor = True
+                break
+            elif self._validate_rsync_target(path) == True:
+                # Found it but not where we expected it to be so override
+                # the target path defined by SMF for now.
+                useVolMonitor = True
+                self._baseTargetDir = path
+                online = True
+                break
+
+        if self._baseTargetDir == None:
+            # Means we didn't find it, and we don't know where to expect
+            # it either - via a hotpluggable device or other nfs/zfs etc.
+            # We need to hedge our bets and monitor for both.
+            self._setup_file_monitor(self._masterTargetDir)
+            self._setup_volume_monitor()
+        else:
+            # Found it
+            if useVolMonitor == True:
+                # Looks like a removable device. Use gio.VolumeMonitor
+                # as the preferred monitoring mechanism.
+                self._setup_volume_monitor()
+            else:
+                # Found it on a static mount point like a zfs or nfs
+                # mount point.
+                # Can't use gio.VolumeMonitor so use a gio.File monitor
+                # instead.
+                self._setup_file_monitor(self._masterTargetDir)
+
+        # Finally, update the UI menu state
+        self._lock.acquire()
+        self._targetDirAvail = online
+        self._update_menu_state()
+        self._lock.release()
+            
+            
+    def _setup_file_monitor(self, expectedPath):
+        # Use gio.File monitor as a fallback in 
+        # case gio.VolumeMonitor can't track the device.
+        # This is the case for static/manual mount points
+        # such as NFS, ZFS and other non-hotpluggables.
+        gFile = gio.File(path=expectedPath)
+        self._fm = gFile.monitor_file(gio.FILE_MONITOR_WATCH_MOUNTS)
+        self._fmID = self._fm.connect("changed",
+                                      self._file_monitor_changed)
+
+    def _setup_volume_monitor(self):
+        # Check the handler_ids first to see if they have 
+        # already been connected. Avoids multiple callbacks
+        # for a single event
+        if self._vmAdd == None:
+            self._vmAdd = self._vm.connect("mount-added",
+                                           self._mount_added)
+        if self._vmRem == None:
+            self._vmRem = self._vm.connect("mount-removed",
+                                           self._mount_removed)
+            
+    def _mount_added(self, monitor, mount):
+        root = mount.get_root()
+        path = root.get_path()
+        if self._validate_rsync_target(path) == True:
+            # Since gio.VolumeMonitor found the rsync target, don't
+            # bother relying on gio.File to find it any more. Disconnect
+            # it's registered callbacks.
+            if self._fm:
+                self._fm.disconnect(self._fmID)
+                self._fm = None
+            self._lock.acquire()
+            self._baseTargetDir = path
+            self._targetDirAvail = True
+            self._update_menu_state()
+            self._lock.release()
+
+    def _mount_removed(self, monitor, mount):
+        root = mount.get_root()
+        path = root.get_path()
+        if path == self._baseTargetDir:
+            self._lock.acquire()
+            self._targetDirAvail = False
+            self._update_menu_state()
+            self._lock.release()
+
+    def _file_monitor_changed(self, filemonitor, file, other_file, event_type):
+        if file.get_path() == self._masterTargetDir:
+            self._lock.acquire()
+            if self._validate_rsync_target(self._masterTargetDir) == True:
+                self._targetDirAvail = True
+            else:
+                self._targetDirAvail = False
+            self._update_menu_state()
+            self._lock.release()            
+
+    def _update_menu_state(self):
+        if self._syncNowItem:
+            if self._targetDirAvail == True and \
+                self._scriptRunning == False:
+                self._syncNowItem.set_sensitive(True)
+            else:
+                self._syncNowItem.set_sensitive(False)
+
+    def _watch_handler(self, new_owner = None):
+        self._lock.acquire()
+        if new_owner == None or len(new_owner) == 0:
+            # Script not running or exited
+            self._scriptRunning = False
+        else:
+            self._scriptRunning = True
+            self._connect_to_object()
+        self._update_menu_state()
+        self._lock.release()
+
+    def _rsync_started_handler(self, target, sender=None, interface=None, path=None):
+        urgency = pynotify.URGENCY_NORMAL
+        if (self._note != None):
+            self._note.close()
+        # Try to pretty things up a bit by displaying volume name
+        # and hinted icon instead of the raw device path,
+        # and standard harddisk icon if possible.
+        icon = None
+        volume = util.path_to_volume(target)
+        if volume == None:
+            volName = target
+        else:
+            volName = volume.get_name()
+            icon = volume.get_icon()
+                      
+        self._note = pynotify.Notification(_("Backup Started"),
+                                           _("Backing up snapshots to:\n<b>%s</b>\n" \
+                                           "Do not disconnect the backup device.") \
+                                            % (volName))
+        self._note.connect("closed", \
+                           self._notification_closed)
+        self._note.set_urgency(urgency)
+        self._setup_icon_for_note(icon)
+        gobject.idle_add(self._show_notification)
+
+    def _rsync_current_handler(self, snapshot, remaining, sender=None, interface=None, path=None):
+        self._icon.set_tooltip_markup(_("Backing up: <b>\'%s\'\n%d</b> snapshots remaining.\n" \
+                                      "Do not disconnect the backup device.") \
+                                      % (snapshot, remaining))
+
+    def _rsync_complete_handler(self, target, sender=None, interface=None, path=None):
+        urgency = pynotify.URGENCY_NORMAL
+        if (self._note != None):
+            self._note.close()
+        # Try to pretty things up a bit by displaying volume name
+        # and hinted icon instead of the raw device path,
+        # and standard harddisk icon if possible.
+        icon = None
+        volume = util.path_to_volume(target)
+        if volume == None:
+            volName = target
+        else:
+            volName = volume.get_name()
+            icon = volume.get_icon()
+
+        self._note = pynotify.Notification(_("Backup Complete"),
+                                           _("Your snapshots have been backed up to:\n<b>%s</b>") \
+                                           % (volName))
+        self._note.connect("closed", \
+                           self._notification_closed)
+        self._note.set_urgency(urgency)
+        self._setup_icon_for_note(icon)
+        self._icon.set_has_tooltip(False)
+        self.queueSize = 0
+        gobject.idle_add(self._show_notification)
+
+    def _rsync_synced_handler(self, sender=None, interface=None, path=None):
+        self._icon.set_tooltip_markup(_("Your backups are up to date."))
+        self.queueSize = 0
+
+    def _rsync_unsynced_handler(self, queueSize, sender=None, interface=None, path=None):
+        self._icon.set_tooltip_markup(_("%d snapshots are queued for backup.") \
+                                      % (queueSize))
+        self.queueSize = queueSize
+
+    def _connect_to_object(self):
+        try:
+            remote_object = bus.get_object("org.opensolaris.TimeSlider.plugin.rsync",
+                                           "/org/opensolaris/TimeSlider/plugin/rsync")
+        except dbus.DBusException:
+            sys.stderr.write("Failed to connect to remote D-Bus object: " + \
+                             "/org/opensolaris/TimeSlider/plugin/rsync")
+            return
+
+        # Create an Interface wrapper for the remote object
+        iface = dbus.Interface(remote_object, "org.opensolaris.TimeSlider.plugin.rsync")
+
+        iface.connect_to_signal("rsync_started", self._rsync_started_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_current", self._rsync_current_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_complete", self._rsync_complete_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_synced", self._rsync_synced_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_unsynced", self._rsync_unsynced_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+
+    def refresh(self):
+        # Hide/Unhide rsync menu item based on whether the plugin is online
+        if self._syncNowItem and \
+           self.smfInst.get_service_state() == "online":
+            #self._setup_file_monitor()
+            self._setup_monitor()
+            # Kick start things by initially obtaining the
+            # backlog size and triggering a callback.
+            # Signal handlers will keep tooltip status up
+            # to date afterwards when the backup cron job
+            # executes.
+            propName = "%s:rsync" % (backup.propbasename)
+            queue = backup.list_pending_snapshots(propName)
+            self.queueSize = len(queue)
+            if self.queueSize == 0:
+                self._rsync_synced_handler()
+            else:
+                self._rsync_unsynced_handler(self.queueSize)
+            self._syncNowItem.show()
+        else:
+            self._syncNowItem.hide()
+
+    def _sync_now(self, menuItem):
+        """Runs the rsync-backup script manually
+           Assumes that user is root since it is only
+           called from the menu item which is invisible to
+           not authorised users
+        """
+        cmdPath = os.path.join(os.path.dirname(sys.argv[0]), \
+                               "time-slider/plugins/rsync/rsync-backup")
+        if os.geteuid() == 0:
+         cmd = [cmdPath, \
+                "%s:rsync" % (plugin.PLUGINBASEFMRI)]
+       else:
+         cmd = ['/usr/bin/gksu' ,cmdPath, \
+                "%s:rsync" % (plugin.PLUGINBASEFMRI)]
+
+       subprocess.Popen(cmd, close_fds=True, cwd="/")
+
+
+class CleanupNote(Note):
+
+    def __init__(self, icon, menu):
+        Note.__init__(self, icon, menu)
+        self._cleanupHead = None
+        self._cleanupBody = None
+        dbus.bus.NameOwnerWatch(bus,
+                                "org.opensolaris.TimeSlider",
+                                self._watch_handler)
+
+    def _show_cleanup_details(self, *args):
+        # We could keep a dialog around but this a rare
+        # enough event that's it not worth the effort.
+        dialog = gtk.MessageDialog(type=gtk.MESSAGE_WARNING,
+                                   buttons=gtk.BUTTONS_CLOSE)
+        dialog.set_title(_("Time Slider: Low Space Warning"))
+        dialog.set_markup("<b>%s</b>" % (self._cleanupHead))
+        dialog.format_secondary_markup(self._cleanupBody)
+        dialog.show()
+        dialog.present()
+        dialog.connect("response", self._dialog_response)
+
+    def _cleanup_handler(self, pool, severity, threshhold, sender=None, interface=None, path=None):
+        if severity == 4:
+            expiry = pynotify.EXPIRES_NEVER
+            urgency = pynotify.URGENCY_CRITICAL
+            self._cleanupHead = _("Emergency: \'%s\' is full!") % pool
+            notifyBody = _("The file system: \'%s\', is over %s%% full.") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("The file system: \'%s\', is over %s%% full.\n"
+                     "As an emergency measure, Time Slider has "
+                     "destroyed all of its backups.\nTo fix this problem, "
+                     "delete any unnecessary files on \'%s\', or add "
+                     "disk space (see ZFS documentation).") \
+                      % (pool, threshhold, pool)
+        elif severity == 3:
+            expiry = pynotify.EXPIRES_NEVER
+            urgency = pynotify.URGENCY_CRITICAL
+            self._cleanupHead = _("Emergency: \'%s\' is almost full!") % pool
+            notifyBody = _("The file system: \'%s\', exceeded %s%% "
+                           "of its total capacity") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("The file system: \'%s\', exceeded %s%% "
+                     "of its total capacity. As an emerency measure, "
+                     "Time Slider has has destroyed most or all of its "
+                     "backups to prevent the disk becoming full. "
+                     "To prevent this from happening again, delete "
+                     "any unnecessary files on \'%s\', or add disk "
+                     "space (see ZFS documentation).") \
+                      % (pool, threshhold, pool)
+        elif severity == 2:
+            expiry = pynotify.EXPIRES_NEVER
+            urgency = pynotify.URGENCY_CRITICAL
+            self._cleanupHead = _("Urgent: \'%s\' is almost full!") % pool
+            notifyBody = _("The file system: \'%s\', exceeded %s%% "
+                           "of its total capacity") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("The file system: \'%s\', exceeded %s%% "
+                     "of its total capacity. As a remedial measure, "
+                     "Time Slider has destroyed some backups, and will "
+                     "destroy more, eventually all, as capacity continues "
+                     "to diminish.\nTo prevent this from happening again, "
+                     "delete any unnecessary files on \'%s\', or add disk "
+                     "space (see ZFS documentation).") \
+                     % (pool, threshhold, pool)
+        elif severity == 1:
+            expiry = 20000 # 20 seconds
+            urgency = pynotify.URGENCY_NORMAL
+            self._cleanupHead = _("Warning: \'%s\' is getting full") % pool
+            notifyBody = _("The file system: \'%s\', exceeded %s%% "
+                           "of its total capacity") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("\'%s\' exceeded %s%% of its total "
+                     "capacity. To fix this, Time Slider has destroyed "
+                     "some recent backups, and will destroy more as "
+                     "capacity continues to diminish.\nTo prevent "
+                     "this from happening again, delete any "
+                     "unnecessary files on \'%s\', or add disk space "
+                     "(see ZFS documentation).\n") \
+                     % (pool, threshhold, pool)
+        else:
+            return # No other values currently supported
+
+        if (self._note != None):
+            self._note.close()
+        self._note = pynotify.Notification(self._cleanupHead,
+                                           notifyBody)
+        self._note.add_action("clicked",
+                              _("Details..."),
+                              self._show_cleanup_details)
+        self._note.connect("closed",
+                           self._notification_closed)
+        self._note.set_urgency(urgency)
+        self._note.set_timeout(expiry)
+        self._setup_icon_for_note()
+        self._icon.set_blinking(True)
+        gobject.idle_add(self._show_notification)
+
+    def _connect_to_object(self):
+        try:
+            remote_object = bus.get_object("org.opensolaris.TimeSlider",
+                                           "/org/opensolaris/TimeSlider/autosnap")
+        except dbus.DBusException:
+            sys.stderr.write("Failed to connect to remote D-Bus object: " + \
+                             "/org/opensolaris/TimeSlider/autosnap")
+
+        #Create an Interface wrapper for the remote object
+        iface = dbus.Interface(remote_object, "org.opensolaris.TimeSlider.autosnap")
+
+        iface.connect_to_signal("capacity_exceeded", self._cleanup_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+
+
+
+class SetupNote(Note):
+
+    def __init__(self, icon, menu, manager):
+        Note.__init__(self, icon, menu)
+        # We are passed a reference to out parent so we can
+        # provide it notification which it can then circulate
+        # to other notification objects such as Rsync and
+        # Cleanup
+        self._manager = manager
+        self._icon = icon
+        self._menu = menu
+        self._configSvcItem = gtk.MenuItem(_("Configure Time Slider..."))
+        self._configSvcItem.connect("activate",
+                                    self._run_config_app)
+        self._configSvcItem.set_sensitive(True)
+        self._menu.append(self._configSvcItem)
+        self._configSvcItem.show()
+        dbus.bus.NameOwnerWatch(bus,
+                                "org.opensolaris.TimeSlider.config",
+                                self._watch_handler)
+
+    def _connect_to_object(self):
+        try:
+            remote_object = bus.get_object("org.opensolaris.TimeSlider.config",
+                                           "/org/opensolaris/TimeSlider/config")
+        except dbus.DBusException:
+            sys.stderr.write("Failed to connect to remote D-Bus object: " + \
+                             "/org/opensolaris/TimeSlider/config")
+
+        #Create an Interface wrapper for the remote object
+        iface = dbus.Interface(remote_object, "org.opensolaris.TimeSlider.config")
+
+        iface.connect_to_signal("config_changed", self._config_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+
+    def _config_handler(self, sender=None, interface=None, path=None):
+        # Notify the manager.
+        # This will eventually propogate through to an invocation
+        # of our own refresh() method.
+        self._manager.refresh()
+
+    def _run_config_app(self, menuItem):
+        cmdPath = os.path.join(os.path.dirname(sys.argv[0]),
+                           os.path.pardir,
+                           "bin",
+                           "time-slider-setup")
+        cmd = os.path.abspath(cmdPath)
+        # The setup GUI deals with it's own security and 
+        # authorisation, so no need to pfexec it. Any
+        # changes made to configuration will come back to
+        # us by way of D-Bus notification.
+        subprocess.Popen(cmd, close_fds=True)
+
+class NoteManager():
+    def __init__(self):
+        # Notification objects need to share a common
+        # status icon and popup menu so these are created
+        # outside the object and passed to the constructor
+        self._menu = gtk.Menu()
+        self._icon = gtk.StatusIcon()
+        self._icon.set_from_icon_name("time-slider-setup")
+        self._setupNote = SetupNote(self._icon,
+                                    self._menu,
+                                    self)
+        self._cleanupNote = CleanupNote(self._icon,
+                                        self._menu)
+        self._rsyncNote = RsyncNote(self._icon,
+                                    self._menu)
+
+    def refresh(self):
+        self._rsyncNote.refresh()
+
+bus = dbus.SystemBus()
+
+def main(argv):
+    mainloop = gobject.MainLoop()
+    dbus.mainloop.glib.DBusGMainLoop(set_as_default = True)
+    gobject.threads_init()
+    pynotify.init(_("Time Slider"))
+
+    noteManager = NoteManager()
+
+    try:
+        mainloop.run()
+    except:
+        print "Exiting"
+
+if __name__ == '__main__':
+    main()
+
diff --git a/usr/share/time-slider/lib/time_slider/applet.py~ b/usr/share/time-slider/lib/time_slider/applet.py~
new file mode 100755 (executable)
index 0000000..7d722a6
--- /dev/null
@@ -0,0 +1,645 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import subprocess
+import threading
+import gobject
+import dbus
+import dbus.decorators
+import dbus.glib
+import dbus.mainloop
+import dbus.mainloop.glib
+import gio
+import gtk
+import pygtk
+import pynotify
+
+from time_slider import util, rbac
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import backup, rsyncsmf
+
+class Note:
+    _iconConnected = False
+
+    def __init__(self, icon, menu):
+        self._note = None
+        self._msgDialog = None
+        self._menu = menu
+        self._icon = icon
+        if Note._iconConnected == False:
+            self._icon.connect("popup-menu", self._popup_menu)
+            Note._iconConnected = True
+        self._icon.set_visible(True)
+
+    def _popup_menu(self, icon, button, time):
+        if button == 3:
+            # Don't popup an empty menu
+            if len(self._menu.get_children()) > 0:
+                self._menu.popup(None, None,
+                                 gtk.status_icon_position_menu,
+                                 button, time, icon)
+
+    def _dialog_response(self, dialog, response):
+        dialog.destroy()
+
+    def _notification_closed(self, notifcation):
+        self._note = None
+        self._icon.set_blinking(False)
+
+    def _show_notification(self):
+        if self._icon.is_embedded() == True:
+            self._note.attach_to_status_icon(self._icon)
+        self._note.show()
+        return False
+
+    def _connect_to_object(self):
+        pass
+
+    def refresh(self):
+        pass
+
+    def _watch_handler(self, new_owner = None):
+        if new_owner == None or len(new_owner) == 0:
+            pass
+        else:
+            self._connect_to_object()
+
+    def _setup_icon_for_note(self, themed=None):
+        if themed:
+            iconList = themed.get_names()
+        else:
+            iconList = ['gnome-dev-harddisk']
+
+        iconTheme = gtk.icon_theme_get_default()
+        iconInfo = iconTheme.choose_icon(iconList, 48, 0)
+        pixbuf = iconInfo.load_icon()
+
+        self._note.set_category("device")
+        self._note.set_icon_from_pixbuf(pixbuf)
+
+
+class RsyncNote(Note):
+
+    def __init__(self, icon, menu):
+        Note.__init__(self, icon, menu)
+        dbus.bus.NameOwnerWatch(bus,
+                                "org.opensolaris.TimeSlider.plugin.rsync",
+                                self._watch_handler)
+
+        self.smfInst = rsyncsmf.RsyncSMF("%s:rsync" \
+                                         % (plugin.PLUGINBASEFMRI))
+        self._lock = threading.Lock()
+        self._masterKey = None
+        sys,self._nodeName,rel,ver,arch = os.uname()
+        # References to gio.File and handler_id of a registered
+        # monitor callback on gio.File
+        self._fm = None
+        self._fmID = None
+        # References to gio.VolumeMonitor and handler_ids of
+        # registered mount-added and mount-removed callbacks.
+        self._vm = None
+        self._vmAdd = None
+        self._vmRem = None
+        # Every time the rsync backup script runs it will
+        # register with d-bus and trigger self._watch_handler().
+        # Use this variable to keep track of it's running status.
+        self._scriptRunning = False
+        self._targetDirAvail = False
+        self._syncNowItem = gtk.MenuItem(_("Update Backups Now"))
+        self._syncNowItem.set_sensitive(False)
+        self._syncNowItem.connect("activate",
+                                  self._sync_now)
+        self._menu.append(self._syncNowItem)
+
+        self.refresh()
+
+    def _validate_rsync_target(self, path):
+        """
+           Tests path to see if it is the pre-configured
+           rsync backup device path.
+           Returns True on success, otherwise False
+        """
+        if not os.path.exists(path):
+            return False
+        testDir = join(path,
+                       rsyncsmf.RSYNCDIRPREFIX,
+                       self._nodeName)
+        testKeyFile = join(path,
+                           rsyncsmf.RSYNCDIRPREFIX,
+                           rsyncsmf.RSYNCCONFIGFILE)
+        if os.path.exists(testDir) and \
+            os.path.exists(testKeyFile):
+            testKeyVal = None
+            f = open(testKeyFile, 'r')
+            for line in f.readlines():
+                key, val = line.strip().split('=')
+                if key.strip() == "target_key":
+                    targetKey = val.strip()
+                    break
+            f.close()
+            if targetKey == self._masterKey:
+                return True
+        return False
+
+    def _setup_monitor(self):
+        # Disconnect any previously registered signal
+        # handlers
+        if self._fm:
+            self._fm.disconnect(self._fmID)
+            self._fm = None
+
+        useVolMonitor = False        
+
+        # We always compare against masterKey to validate
+        # an rsync backup device.
+        self._masterKey = self.smfInst.get_target_key()
+        self._baseTargetDir = None
+        online = False
+
+        self._masterTargetDir = self.smfInst.get_target_dir()
+
+        if self._validate_rsync_target(self._masterTargetDir) == True:
+            self._baseTargetDir = self._masterTargetDir
+            online = True
+
+        if self._vm == None:
+            self._vm = gio.volume_monitor_get()
+
+        # If located, see if it's also managed by the volume monitor.
+        # Or just try to find it otherwise.
+        mounts = self._vm.get_mounts()
+        for mount in mounts:
+            root = mount.get_root()
+            path = root.get_path()
+            if self._baseTargetDir != None and \
+                path == self._baseTargetDir:
+                # Means the directory we found is gio monitored,
+                # so just monitor it using gio.VolumeMonitor.
+                useVolMonitor = True
+                break
+            elif self._validate_rsync_target(path) == True:
+                # Found it but not where we expected it to be so override
+                # the target path defined by SMF for now.
+                useVolMonitor = True
+                self._baseTargetDir = path
+                online = True
+                break
+
+        if self._baseTargetDir == None:
+            # Means we didn't find it, and we don't know where to expect
+            # it either - via a hotpluggable device or other nfs/zfs etc.
+            # We need to hedge our bets and monitor for both.
+            self._setup_file_monitor(self._masterTargetDir)
+            self._setup_volume_monitor()
+        else:
+            # Found it
+            if useVolMonitor == True:
+                # Looks like a removable device. Use gio.VolumeMonitor
+                # as the preferred monitoring mechanism.
+                self._setup_volume_monitor()
+            else:
+                # Found it on a static mount point like a zfs or nfs
+                # mount point.
+                # Can't use gio.VolumeMonitor so use a gio.File monitor
+                # instead.
+                self._setup_file_monitor(self._masterTargetDir)
+
+        # Finally, update the UI menu state
+        self._lock.acquire()
+        self._targetDirAvail = online
+        self._update_menu_state()
+        self._lock.release()
+            
+            
+    def _setup_file_monitor(self, expectedPath):
+        # Use gio.File monitor as a fallback in 
+        # case gio.VolumeMonitor can't track the device.
+        # This is the case for static/manual mount points
+        # such as NFS, ZFS and other non-hotpluggables.
+        gFile = gio.File(path=expectedPath)
+        self._fm = gFile.monitor_file(gio.FILE_MONITOR_WATCH_MOUNTS)
+        self._fmID = self._fm.connect("changed",
+                                      self._file_monitor_changed)
+
+    def _setup_volume_monitor(self):
+        # Check the handler_ids first to see if they have 
+        # already been connected. Avoids multiple callbacks
+        # for a single event
+        if self._vmAdd == None:
+            self._vmAdd = self._vm.connect("mount-added",
+                                           self._mount_added)
+        if self._vmRem == None:
+            self._vmRem = self._vm.connect("mount-removed",
+                                           self._mount_removed)
+            
+    def _mount_added(self, monitor, mount):
+        root = mount.get_root()
+        path = root.get_path()
+        if self._validate_rsync_target(path) == True:
+            # Since gio.VolumeMonitor found the rsync target, don't
+            # bother relying on gio.File to find it any more. Disconnect
+            # it's registered callbacks.
+            if self._fm:
+                self._fm.disconnect(self._fmID)
+                self._fm = None
+            self._lock.acquire()
+            self._baseTargetDir = path
+            self._targetDirAvail = True
+            self._update_menu_state()
+            self._lock.release()
+
+    def _mount_removed(self, monitor, mount):
+        root = mount.get_root()
+        path = root.get_path()
+        if path == self._baseTargetDir:
+            self._lock.acquire()
+            self._targetDirAvail = False
+            self._update_menu_state()
+            self._lock.release()
+
+    def _file_monitor_changed(self, filemonitor, file, other_file, event_type):
+        if file.get_path() == self._masterTargetDir:
+            self._lock.acquire()
+            if self._validate_rsync_target(self._masterTargetDir) == True:
+                self._targetDirAvail = True
+            else:
+                self._targetDirAvail = False
+            self._update_menu_state()
+            self._lock.release()            
+
+    def _update_menu_state(self):
+        if self._syncNowItem:
+            if self._targetDirAvail == True and \
+                self._scriptRunning == False:
+                self._syncNowItem.set_sensitive(True)
+            else:
+                self._syncNowItem.set_sensitive(False)
+
+    def _watch_handler(self, new_owner = None):
+        self._lock.acquire()
+        if new_owner == None or len(new_owner) == 0:
+            # Script not running or exited
+            self._scriptRunning = False
+        else:
+            self._scriptRunning = True
+            self._connect_to_object()
+        self._update_menu_state()
+        self._lock.release()
+
+    def _rsync_started_handler(self, target, sender=None, interface=None, path=None):
+        urgency = pynotify.URGENCY_NORMAL
+        if (self._note != None):
+            self._note.close()
+        # Try to pretty things up a bit by displaying volume name
+        # and hinted icon instead of the raw device path,
+        # and standard harddisk icon if possible.
+        icon = None
+        volume = util.path_to_volume(target)
+        if volume == None:
+            volName = target
+        else:
+            volName = volume.get_name()
+            icon = volume.get_icon()
+                      
+        self._note = pynotify.Notification(_("Backup Started"),
+                                           _("Backing up snapshots to:\n<b>%s</b>\n" \
+                                           "Do not disconnect the backup device.") \
+                                            % (volName))
+        self._note.connect("closed", \
+                           self._notification_closed)
+        self._note.set_urgency(urgency)
+        self._setup_icon_for_note(icon)
+        gobject.idle_add(self._show_notification)
+
+    def _rsync_current_handler(self, snapshot, remaining, sender=None, interface=None, path=None):
+        self._icon.set_tooltip_markup(_("Backing up: <b>\'%s\'\n%d</b> snapshots remaining.\n" \
+                                      "Do not disconnect the backup device.") \
+                                      % (snapshot, remaining))
+
+    def _rsync_complete_handler(self, target, sender=None, interface=None, path=None):
+        urgency = pynotify.URGENCY_NORMAL
+        if (self._note != None):
+            self._note.close()
+        # Try to pretty things up a bit by displaying volume name
+        # and hinted icon instead of the raw device path,
+        # and standard harddisk icon if possible.
+        icon = None
+        volume = util.path_to_volume(target)
+        if volume == None:
+            volName = target
+        else:
+            volName = volume.get_name()
+            icon = volume.get_icon()
+
+        self._note = pynotify.Notification(_("Backup Complete"),
+                                           _("Your snapshots have been backed up to:\n<b>%s</b>") \
+                                           % (volName))
+        self._note.connect("closed", \
+                           self._notification_closed)
+        self._note.set_urgency(urgency)
+        self._setup_icon_for_note(icon)
+        self._icon.set_has_tooltip(False)
+        self.queueSize = 0
+        gobject.idle_add(self._show_notification)
+
+    def _rsync_synced_handler(self, sender=None, interface=None, path=None):
+        self._icon.set_tooltip_markup(_("Your backups are up to date."))
+        self.queueSize = 0
+
+    def _rsync_unsynced_handler(self, queueSize, sender=None, interface=None, path=None):
+        self._icon.set_tooltip_markup(_("%d snapshots are queued for backup.") \
+                                      % (queueSize))
+        self.queueSize = queueSize
+
+    def _connect_to_object(self):
+        try:
+            remote_object = bus.get_object("org.opensolaris.TimeSlider.plugin.rsync",
+                                           "/org/opensolaris/TimeSlider/plugin/rsync")
+        except dbus.DBusException:
+            sys.stderr.write("Failed to connect to remote D-Bus object: " + \
+                             "/org/opensolaris/TimeSlider/plugin/rsync")
+            return
+
+        # Create an Interface wrapper for the remote object
+        iface = dbus.Interface(remote_object, "org.opensolaris.TimeSlider.plugin.rsync")
+
+        iface.connect_to_signal("rsync_started", self._rsync_started_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_current", self._rsync_current_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_complete", self._rsync_complete_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_synced", self._rsync_synced_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+        iface.connect_to_signal("rsync_unsynced", self._rsync_unsynced_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+
+    def refresh(self):
+        # Hide/Unhide rsync menu item based on whether the plugin is online
+        if self._syncNowItem and \
+           self.smfInst.get_service_state() == "online":
+            #self._setup_file_monitor()
+            self._setup_monitor()
+            # Kick start things by initially obtaining the
+            # backlog size and triggering a callback.
+            # Signal handlers will keep tooltip status up
+            # to date afterwards when the backup cron job
+            # executes.
+            propName = "%s:rsync" % (backup.propbasename)
+            queue = backup.list_pending_snapshots(propName)
+            self.queueSize = len(queue)
+            if self.queueSize == 0:
+                self._rsync_synced_handler()
+            else:
+                self._rsync_unsynced_handler(self.queueSize)
+            self._syncNowItem.show()
+        else:
+            self._syncNowItem.hide()
+
+    def _sync_now(self, menuItem):
+        """Runs the rsync-backup script manually
+           Assumes that user is root since it is only
+           called from the menu item which is invisible to
+           not authorised users
+        """
+        cmdPath = os.path.join(os.path.dirname(sys.argv[0]), \
+                               "time-slider/plugins/rsync/rsync-backup")
+        if os.geteuid() == 0:
+         cmd = [cmdPath, \
+                "%s:rsync" % (plugin.PLUGINBASEFMRI)]
+       else:
+         cmd = ['/usr/bin/gksu' ,cmdPath, \
+                "%s:rsync" % (plugin.PLUGINBASEFMRI)]
+
+       subprocess.Popen(cmd, close_fds=True, cwd="/")
+
+
+class CleanupNote(Note):
+
+    def __init__(self, icon, menu):
+        Note.__init__(self, icon, menu)
+        self._cleanupHead = None
+        self._cleanupBody = None
+        dbus.bus.NameOwnerWatch(bus,
+                                "org.opensolaris.TimeSlider",
+                                self._watch_handler)
+
+    def _show_cleanup_details(self, *args):
+        # We could keep a dialog around but this a rare
+        # enough event that's it not worth the effort.
+        dialog = gtk.MessageDialog(type=gtk.MESSAGE_WARNING,
+                                   buttons=gtk.BUTTONS_CLOSE)
+        dialog.set_title(_("Time Slider: Low Space Warning"))
+        dialog.set_markup("<b>%s</b>" % (self._cleanupHead))
+        dialog.format_secondary_markup(self._cleanupBody)
+        dialog.show()
+        dialog.present()
+        dialog.connect("response", self._dialog_response)
+
+    def _cleanup_handler(self, pool, severity, threshhold, sender=None, interface=None, path=None):
+        if severity == 4:
+            expiry = pynotify.EXPIRES_NEVER
+            urgency = pynotify.URGENCY_CRITICAL
+            self._cleanupHead = _("Emergency: \'%s\' is full!") % pool
+            notifyBody = _("The file system: \'%s\', is over %s%% full.") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("The file system: \'%s\', is over %s%% full.\n"
+                     "As an emergency measure, Time Slider has "
+                     "destroyed all of its backups.\nTo fix this problem, "
+                     "delete any unnecessary files on \'%s\', or add "
+                     "disk space (see ZFS documentation).") \
+                      % (pool, threshhold, pool)
+        elif severity == 3:
+            expiry = pynotify.EXPIRES_NEVER
+            urgency = pynotify.URGENCY_CRITICAL
+            self._cleanupHead = _("Emergency: \'%s\' is almost full!") % pool
+            notifyBody = _("The file system: \'%s\', exceeded %s%% "
+                           "of its total capacity") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("The file system: \'%s\', exceeded %s%% "
+                     "of its total capacity. As an emerency measure, "
+                     "Time Slider has has destroyed most or all of its "
+                     "backups to prevent the disk becoming full. "
+                     "To prevent this from happening again, delete "
+                     "any unnecessary files on \'%s\', or add disk "
+                     "space (see ZFS documentation).") \
+                      % (pool, threshhold, pool)
+        elif severity == 2:
+            expiry = pynotify.EXPIRES_NEVER
+            urgency = pynotify.URGENCY_CRITICAL
+            self._cleanupHead = _("Urgent: \'%s\' is almost full!") % pool
+            notifyBody = _("The file system: \'%s\', exceeded %s%% "
+                           "of its total capacity") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("The file system: \'%s\', exceeded %s%% "
+                     "of its total capacity. As a remedial measure, "
+                     "Time Slider has destroyed some backups, and will "
+                     "destroy more, eventually all, as capacity continues "
+                     "to diminish.\nTo prevent this from happening again, "
+                     "delete any unnecessary files on \'%s\', or add disk "
+                     "space (see ZFS documentation).") \
+                     % (pool, threshhold, pool)
+        elif severity == 1:
+            expiry = 20000 # 20 seconds
+            urgency = pynotify.URGENCY_NORMAL
+            self._cleanupHead = _("Warning: \'%s\' is getting full") % pool
+            notifyBody = _("The file system: \'%s\', exceeded %s%% "
+                           "of its total capacity") \
+                            % (pool, threshhold)
+            self._cleanupBody = _("\'%s\' exceeded %s%% of its total "
+                     "capacity. To fix this, Time Slider has destroyed "
+                     "some recent backups, and will destroy more as "
+                     "capacity continues to diminish.\nTo prevent "
+                     "this from happening again, delete any "
+                     "unnecessary files on \'%s\', or add disk space "
+                     "(see ZFS documentation).\n") \
+                     % (pool, threshhold, pool)
+        else:
+            return # No other values currently supported
+
+        if (self._note != None):
+            self._note.close()
+        self._note = pynotify.Notification(self._cleanupHead,
+                                           notifyBody)
+        self._note.add_action("clicked",
+                              _("Details..."),
+                              self._show_cleanup_details)
+        self._note.connect("closed",
+                           self._notification_closed)
+        self._note.set_urgency(urgency)
+        self._note.set_timeout(expiry)
+        self._setup_icon_for_note()
+        self._icon.set_blinking(True)
+        gobject.idle_add(self._show_notification)
+
+    def _connect_to_object(self):
+        try:
+            remote_object = bus.get_object("org.opensolaris.TimeSlider",
+                                           "/org/opensolaris/TimeSlider/autosnap")
+        except dbus.DBusException:
+            sys.stderr.write("Failed to connect to remote D-Bus object: " + \
+                             "/org/opensolaris/TimeSlider/autosnap")
+
+        #Create an Interface wrapper for the remote object
+        iface = dbus.Interface(remote_object, "org.opensolaris.TimeSlider.autosnap")
+
+        iface.connect_to_signal("capacity_exceeded", self._cleanup_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+
+
+
+class SetupNote(Note):
+
+    def __init__(self, icon, menu, manager):
+        Note.__init__(self, icon, menu)
+        # We are passed a reference to out parent so we can
+        # provide it notification which it can then circulate
+        # to other notification objects such as Rsync and
+        # Cleanup
+        self._manager = manager
+        self._icon = icon
+        self._menu = menu
+        self._configSvcItem = gtk.MenuItem(_("Configure Time Slider..."))
+        self._configSvcItem.connect("activate",
+                                    self._run_config_app)
+        self._configSvcItem.set_sensitive(True)
+        self._menu.append(self._configSvcItem)
+        self._configSvcItem.show()
+        dbus.bus.NameOwnerWatch(bus,
+                                "org.opensolaris.TimeSlider.config",
+                                self._watch_handler)
+
+    def _connect_to_object(self):
+        try:
+            remote_object = bus.get_object("org.opensolaris.TimeSlider.config",
+                                           "/org/opensolaris/TimeSlider/config")
+        except dbus.DBusException:
+            sys.stderr.write("Failed to connect to remote D-Bus object: " + \
+                             "/org/opensolaris/TimeSlider/config")
+
+        #Create an Interface wrapper for the remote object
+        iface = dbus.Interface(remote_object, "org.opensolaris.TimeSlider.config")
+
+        iface.connect_to_signal("config_changed", self._config_handler, sender_keyword='sender',
+                                interface_keyword='interface', path_keyword='path')
+
+    def _config_handler(self, sender=None, interface=None, path=None):
+        # Notify the manager.
+        # This will eventually propogate through to an invocation
+        # of our own refresh() method.
+        self._manager.refresh()
+
+    def _run_config_app(self, menuItem):
+        cmdPath = os.path.join(os.path.dirname(sys.argv[0]),
+                           os.path.pardir,
+                           "bin",
+                           "time-slider-setup")
+        cmd = os.path.abspath(cmdPath)
+        # The setup GUI deals with it's own security and 
+        # authorisation, so no need to pfexec it. Any
+        # changes made to configuration will come back to
+        # us by way of D-Bus notification.
+        subprocess.Popen(cmd, close_fds=True)
+
+class NoteManager():
+    def __init__(self):
+        # Notification objects need to share a common
+        # status icon and popup menu so these are created
+        # outside the object and passed to the constructor
+        self._menu = gtk.Menu()
+        self._icon = gtk.StatusIcon()
+        self._icon.set_from_icon_name("time-slider-setup")
+        self._setupNote = SetupNote(self._icon,
+                                    self._menu,
+                                    self)
+        self._cleanupNote = CleanupNote(self._icon,
+                                        self._menu)
+        self._rsyncNote = RsyncNote(self._icon,
+                                    self._menu)
+
+    def refresh(self):
+        self._rsyncNote.refresh()
+
+bus = dbus.SystemBus()
+
+def main(argv):
+    mainloop = gobject.MainLoop()
+    dbus.mainloop.glib.DBusGMainLoop(set_as_default = True)
+    gobject.threads_init()
+    pynotify.init(_("Time Slider"))
+
+    noteManager = NoteManager()
+
+    try:
+        mainloop.run()
+    except:
+        print "Exiting"
+
+if __name__ == '__main__':
+    main()
+
diff --git a/usr/share/time-slider/lib/time_slider/autosnapsmf.py b/usr/share/time-slider/lib/time_slider/autosnapsmf.py
new file mode 100755 (executable)
index 0000000..e659a28
--- /dev/null
@@ -0,0 +1,170 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import threading
+import smf
+import util
+
+factoryDefaultSchedules = ("monthly", "weekly", "daily", "hourly", "frequent")
+
+BASESVC= "svc:/system/filesystem/zfs/auto-snapshot"
+SNAPLABELPREFIX = "zfs-auto-snap"
+ZFSPROPGROUP = "zfs"
+
+
+# Bombarding the class with schedule queries causes the occasional
+# OSError exception due to interrupted system calls.
+# Serialising them helps prevent this unlikely event from occuring.
+_scheddetaillock = threading.RLock()
+
+class AutoSnap(smf.SMFInstance):
+
+    def __init__(self, schedule):
+        smf.SMFInstance.__init__(self, "%s:%s" % (BASESVC, schedule))
+        self.schedule = schedule
+
+    def get_schedule_details(self):
+        svc= "%s:%s" % (BASESVC, self.schedule)
+        _scheddetaillock.acquire()
+        try:
+            interval = self.get_prop(ZFSPROPGROUP, "interval")
+            period = int(self.get_prop(ZFSPROPGROUP, "period"))
+            keep =  int(self.get_prop(ZFSPROPGROUP, "keep"))
+
+        except OSError, message:
+            raise RuntimeError, "%s subprocess error:\n %s" % \
+                                (cmd, str(message))
+        finally:
+            _scheddetaillock.release()
+      
+        return [self.schedule, interval, period, keep]
+
+# FIXME - merge with enable_default_schedules()
+def disable_default_schedules():
+    """
+    Disables the default auto-snapshot SMF instances corresponding
+    to: "frequent", "hourly", "daily", "weekly" and "monthly"
+    schedules
+    Raises RuntimeError exception if unsuccessful
+    """
+
+    for s in factoryDefaultSchedules:
+        # Acquire the scheddetail lock since their status will
+        # likely be changed as a result of enabling the instances.
+        _scheddetaillock.acquire()
+        instanceName = "%s:%s" % (BASESVC,s)
+        svc = smf.SMFInstance(instanceName)
+        svc.disable_service()
+        _scheddetaillock.release()
+
+def enable_default_schedules():
+    """
+    Enables the default auto-snapshot SMF instances corresponding
+    to: "frequent", "hourly", "daily", "weekly" and "monthly"
+    schedules
+    Raises RuntimeError exception if unsuccessful
+    """
+    for s in factoryDefaultSchedules:
+        # Acquire the scheddetail lock since their status will
+        # likely be changed as a result of enabling the instances.
+        _scheddetaillock.acquire()
+        instanceName = "%s:%s" % (BASESVC,s)
+        svc = smf.SMFInstance(instanceName)
+        svc.enable_service()
+        _scheddetaillock.release()
+
+def get_default_schedules():
+    """
+    Finds the default schedules that are enabled (online, offline or degraded)
+    """
+    #This is not the fastest method but it is the safest, we need
+    #to ensure that default schedules are processed in the pre-defined
+    #order to ensure that the overlap between them is adhered to
+    #correctly. monthly->weekly->daily->hourly->frequent. They have
+    #to be processed first and they HAVE to be in the correct order.
+    _defaultSchedules = []
+    for s in factoryDefaultSchedules:
+        instanceName = "%s:%s" % (BASESVC,s)
+        cmd = [smf.SVCSCMD, "-H", "-o", "state", instanceName]
+        _scheddetaillock.acquire()
+        try:
+            outdata,errdata = util.run_command(cmd)
+        finally:
+            _scheddetaillock.release()
+        result = outdata.rstrip()
+        # Note that the schedules, being dependent on the time-slider service
+        # itself will typically be in an offline state when enabled. They will
+        # transition to an "online" state once time-slider itself comes
+        # "online" to satisfy it's dependency
+        if result == "online" or result == "offline" or result == "degraded":
+            instance = AutoSnap(s)
+            try:
+                _defaultSchedules.append(instance.get_schedule_details())
+            except RuntimeError, message:
+                raise RuntimeError, "Error getting schedule details for " + \
+                                    "default auto-snapshot SMF instance:" + \
+                                    "\n\t" + instanceName + "\nDetails:\n" + \
+                                    str(message)
+    return _defaultSchedules
+
+def get_custom_schedules():
+    """
+    Finds custom schedules ie. not the factory default
+    'monthly', 'weekly', 'hourly', 'daily' and 'frequent' schedules
+    """
+    _customSchedules = []
+    cmd = [smf.SVCSCMD, "-H", "-o", "state,FMRI", BASESVC]
+    _scheddetaillock.acquire()
+    try:
+        outdata,errdata = util.run_command(cmd)
+    finally:
+        _scheddetaillock.release()
+
+    for line in outdata.rstrip().split('\n'):
+        line = line.rstrip().split()
+        state = line[0]
+        fmri = line[1]
+        fmri = fmri.rsplit(":", 1)
+        label = fmri[1]
+        if label not in factoryDefaultSchedules:
+        # Note that the schedules, being dependent on the time-slider service
+        # itself will typically be in an offline state when enabled. They will
+        # transition to an "online" state once time-slider itself comes
+        # "online" to satisfy it's dependency
+            if state == "online" or state == "offline" or state == "degraded":
+                instance = AutoSnap(label)
+                try:
+                    _customSchedules.append(instance.get_schedule_details())
+                except RuntimeError, message:
+                    raise RuntimeError, "Error getting schedule details " + \
+                                        "for custom auto-snapshot SMF " + \
+                                        "instance:\n\t" + label + "\n" + \
+                                        "Details:\n" + str(message) 
+    return _customSchedules
+
+
+if __name__ == "__main__":
+    defaults = get_default_schedules()
+    for sched in defaults:
+        S = AutoSnap(sched[0])
+        print S.get_schedule_details()
+
diff --git a/usr/share/time-slider/lib/time_slider/dbussvc.py b/usr/share/time-slider/lib/time_slider/dbussvc.py
new file mode 100644 (file)
index 0000000..e9f80b0
--- /dev/null
@@ -0,0 +1,103 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+
+import dbus
+import dbus.service
+import dbus.mainloop
+import dbus.mainloop.glib
+
+
+class AutoSnap(dbus.service.Object):
+    """
+    D-Bus object for Time Slider's auto snapshot features.
+    """
+    def __init__(self, bus, path, snapshotmanager):
+        self.snapshotmanager = snapshotmanager
+        self._bus = bus
+        dbus.service.Object.__init__(self,
+                                     bus,
+                                     path)
+
+    # Remedial cleanup signal
+    @dbus.service.signal(dbus_interface="org.opensolaris.TimeSlider.autosnap",
+                         signature='suu')
+    def capacity_exceeded(self, pool, severity, threshhold):
+        pass
+
+class RsyncBackup(dbus.service.Object):
+    """
+    D-Bus object for Time Slider's rsync backup feature.
+    """
+    def __init__(self, bus, path):
+        self._bus = bus
+        dbus.service.Object.__init__(self, 
+                                     bus,  
+                                     path)
+
+    # Rsync operation rsync_started signal
+    @dbus.service.signal(dbus_interface="org.opensolaris.TimeSlider.plugin.rsync",
+                         signature='s')
+    def rsync_started(self, target):
+        pass
+
+    # Rsync operation rsync_current signal
+    @dbus.service.signal(dbus_interface="org.opensolaris.TimeSlider.plugin.rsync",
+                         signature='su')
+    def rsync_current(self, snapshot, remaining):
+        pass
+
+    # Rsync operation rsync_complete signal
+    @dbus.service.signal(dbus_interface="org.opensolaris.TimeSlider.plugin.rsync",
+                         signature='s')
+    def rsync_complete(self, target):
+        pass
+
+    # Rsync operation rsync_synced signal
+    @dbus.service.signal(dbus_interface="org.opensolaris.TimeSlider.plugin.rsync",
+                         signature='')
+    def rsync_synced(self):
+        pass
+
+    # Rsync operation rsync_unsynced signal
+    @dbus.service.signal(dbus_interface="org.opensolaris.TimeSlider.plugin.rsync",
+                         signature='u')
+    def rsync_unsynced(self, queueSize):
+        pass
+
+
+class Config(dbus.service.Object):
+    """
+    D-Bus object representing Time Slider service configuration changes.
+    """
+    def __init__(self, bus, path):
+        self._bus = bus
+        dbus.service.Object.__init__(self, 
+                                        bus,  
+                                        path)
+    # Service configuration change signal. Nothing fancy for now. 
+    # Listeners need to figure out what changed for themselves.
+    @dbus.service.signal(dbus_interface="org.opensolaris.TimeSlider.config",
+                         signature='')
+    def config_changed(self):
+        pass
+
diff --git a/usr/share/time-slider/lib/time_slider/deletegui.py b/usr/share/time-slider/lib/time_slider/deletegui.py
new file mode 100755 (executable)
index 0000000..8023d9a
--- /dev/null
@@ -0,0 +1,756 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import threading
+import sys
+import os
+import time
+import getopt
+import locale
+import shutil
+import fcntl
+from bisect import insort
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+try:
+    import glib
+    import gobject
+except:
+    sys.exit(1)
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import rsyncsmf
+
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from rbac import RBACprofile
+
+class RsyncBackup:
+
+    def __init__(self, mountpoint, rsync_dir = None,  fsname= None, snaplabel= None, creationtime= None):
+
+        if rsync_dir == None:
+            self.__init_from_mp (mountpoint)
+        else:
+            self.rsync_dir = rsync_dir
+            self.mountpoint = mountpoint
+            self.fsname = fsname
+            self.snaplabel = snaplabel
+
+            self.creationtime = creationtime
+            try:
+                tm = time.localtime(self.creationtime)
+                self.creationtime_str = unicode(time.strftime ("%c", tm),
+                           locale.getpreferredencoding()).encode('utf-8')
+            except:
+                self.creationtime_str = time.ctime(self.creationtime)
+        fs = zfs.Filesystem (self.fsname)
+        self.zfs_mountpoint = fs.get_mountpoint ()
+
+    def __init_from_mp (self, mountpoint):
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsync_dir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+        self.mountpoint = mountpoint
+
+        s1 = mountpoint.split ("%s/" % self.rsync_dir, 1)
+        s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+        s3 = s2[1].split ('/',2)
+        self.fsname = s2[0]
+        self.snaplabel =  s3[1]
+        self.creationtime = os.stat(mountpoint).st_mtime
+
+    def __str__(self):
+        ret = "self.rsync_dir = %s\n \
+               self.mountpoint = %s\n \
+               self.fsname = %s\n \
+               self.snaplabel = %s\n" % (self.rsync_dir,
+                                         self.mountpoint, self.fsname,
+                                         self.snaplabel)
+        return ret
+
+
+    def exists(self):
+        return os.path.exists(self.mountpoint)
+
+    def destroy(self):
+        lockFileDir = os.path.join(self.rsync_dir,
+                             self.fsname,
+                             rsyncsmf.RSYNCLOCKSUFFIX)
+
+        if not os.path.exists(lockFileDir):
+            os.makedirs(lockFileDir, 0755)
+
+        lockFile = os.path.join(lockFileDir, self.snaplabel + ".lock")
+        try:
+            lockFp = open(lockFile, 'w')
+            fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+        except IOError:
+            raise RuntimeError, \
+            "couldn't delete %s, already used by another process" % self.mountpoint
+            return
+
+        trashDir = os.path.join(self.rsync_dir,
+                          self.fsname,
+                          rsyncsmf.RSYNCTRASHSUFFIX)
+        if not os.path.exists(trashDir):
+            os.makedirs(trashDir, 0755)
+
+        backupTrashDir = os.path.join (self.rsync_dir,
+                                 self.fsname,
+                                 rsyncsmf.RSYNCTRASHSUFFIX,
+                                 self.snaplabel)
+
+        # move then delete
+        os.rename (self.mountpoint, backupTrashDir)
+        shutil.rmtree (backupTrashDir)
+
+        log = "%s/%s/%s/%s.log" % (self.rsync_dir,
+                                   self.fsname,
+                                   rsyncsmf.RSYNCLOGSUFFIX,
+                                   self.snaplabel)
+        if os.path.exists (log):
+            os.unlink (log)
+
+        lockFp.close()
+        os.unlink(lockFile)
+
+class DeleteSnapManager:
+
+    def __init__(self, snapshots = None):
+        self.xml = gtk.glade.XML("%s/../../glade/time-slider-delete.glade" \
+                                  % (os.path.dirname(__file__)))
+        self.backuptodelete = []
+        self.shortcircuit = []
+        maindialog = self.xml.get_widget("time-slider-delete")
+        self.pulsedialog = self.xml.get_widget("pulsedialog")
+        self.pulsedialog.set_transient_for(maindialog)
+        self.datasets = zfs.Datasets()
+        if snapshots:
+            maindialog.hide()
+            self.shortcircuit = snapshots
+        else:
+            glib.idle_add(self.__init_scan)
+
+        self.progressdialog = self.xml.get_widget("deletingdialog")
+        self.progressdialog.set_transient_for(maindialog)
+        self.progressbar = self.xml.get_widget("deletingprogress")
+        # signal dictionary
+        dic = {"on_closebutton_clicked" : gtk.main_quit,
+               "on_window_delete_event" : gtk.main_quit,
+               "on_snapshotmanager_delete_event" : gtk.main_quit,
+               "on_fsfilterentry_changed" : self.__on_filterentry_changed,
+               "on_schedfilterentry_changed" : self.__on_filterentry_changed,
+               "on_typefiltercombo_changed" : self.__on_filterentry_changed,
+               "on_selectbutton_clicked" : self.__on_selectbutton_clicked,
+               "on_deselectbutton_clicked" : self.__on_deselectbutton_clicked,
+               "on_deletebutton_clicked" : self.__on_deletebutton_clicked,
+               "on_confirmcancel_clicked" : self.__on_confirmcancel_clicked,
+               "on_confirmdelete_clicked" : self.__on_confirmdelete_clicked,
+               "on_errordialog_response" : self.__on_errordialog_response}
+        self.xml.signal_autoconnect(dic)
+
+    def initialise_view(self):
+        if len(self.shortcircuit) == 0:
+            # Set TreeViews
+            self.liststorefs = gtk.ListStore(str, str, str, str, str, long,
+                                             gobject.TYPE_PYOBJECT)
+            list_filter = self.liststorefs.filter_new()
+            list_sort = gtk.TreeModelSort(list_filter)
+            list_sort.set_sort_column_id(1, gtk.SORT_ASCENDING)
+
+            self.snaptreeview = self.xml.get_widget("snaplist")
+            self.snaptreeview.set_model(self.liststorefs)
+            self.snaptreeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+
+            cell0 = gtk.CellRendererText()
+            cell1 = gtk.CellRendererText()
+            cell2 = gtk.CellRendererText()
+            cell3 = gtk.CellRendererText()
+            cell4 = gtk.CellRendererText()
+            cell5 = gtk.CellRendererText()
+
+            typecol = gtk.TreeViewColumn(_("Type"),
+                                            cell0, text = 0)
+            typecol.set_sort_column_id(0)
+            typecol.set_resizable(True)
+            typecol.connect("clicked",
+                self.__on_treeviewcol_clicked, 0)
+            self.snaptreeview.append_column(typecol)
+
+            mountptcol = gtk.TreeViewColumn(_("Mount Point"),
+                                            cell1, text = 1)
+            mountptcol.set_sort_column_id(1)
+            mountptcol.set_resizable(True)
+            mountptcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 1)
+            self.snaptreeview.append_column(mountptcol)
+
+            fsnamecol = gtk.TreeViewColumn(_("File System Name"),
+                                           cell2, text = 2)
+            fsnamecol.set_sort_column_id(2)
+            fsnamecol.set_resizable(True)
+            fsnamecol.connect("clicked",
+                self.__on_treeviewcol_clicked, 2)
+            self.snaptreeview.append_column(fsnamecol)
+
+            snaplabelcol = gtk.TreeViewColumn(_("Snapshot Name"),
+                                              cell3, text = 3)
+            snaplabelcol.set_sort_column_id(3)
+            snaplabelcol.set_resizable(True)
+            snaplabelcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 3)
+            self.snaptreeview.append_column(snaplabelcol)
+
+            cell4.props.xalign = 1.0
+            creationcol = gtk.TreeViewColumn(_("Creation Time"),
+                                             cell4, text = 4)
+            creationcol.set_sort_column_id(5)
+            creationcol.set_resizable(True)
+            creationcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 5)
+            self.snaptreeview.append_column(creationcol)
+
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            typestore = gtk.ListStore(str, str)
+            typestore.append([_("All"), "All"])
+            typestore.append([_("Backups"), "Backup"])
+            typestore.append([_("Snapshots"), "Snapshot"])
+
+            self.typefiltercombo = self.xml.get_widget("typefiltercombo")
+            self.typefiltercombo.set_model(typestore)
+            typefiltercomboCell = gtk.CellRendererText()
+            self.typefiltercombo.pack_start(typefiltercomboCell, True)
+            self.typefiltercombo.add_attribute(typefiltercomboCell, 'text',0)
+
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            fsstore = gtk.ListStore(str, str)
+            fslist = self.datasets.list_filesystems()
+            fsstore.append([_("All"), None])
+            for fsname,fsmount in fslist:
+                fsstore.append([fsname, fsname])
+            self.fsfilterentry = self.xml.get_widget("fsfilterentry")
+            self.fsfilterentry.set_model(fsstore)
+            self.fsfilterentry.set_text_column(0)
+            fsfilterentryCell = gtk.CellRendererText()
+            self.fsfilterentry.pack_start(fsfilterentryCell)
+
+            schedstore = gtk.ListStore(str, str)
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            schedstore.append([_("All"), None])
+            schedstore.append([_("Monthly"), "monthly"])
+            schedstore.append([_("Weekly"), "weekly"])
+            schedstore.append([_("Daily"), "daily"])
+            schedstore.append([_("Hourly"), "hourly"])
+            schedstore.append([_("1/4 Hourly"), "frequent"])
+            self.schedfilterentry = self.xml.get_widget("schedfilterentry")
+            self.schedfilterentry.set_model(schedstore)
+            self.schedfilterentry.set_text_column(0)
+            schedentryCell = gtk.CellRendererText()
+            self.schedfilterentry.pack_start(schedentryCell)
+
+            self.schedfilterentry.set_active(0)
+            self.fsfilterentry.set_active(0)
+            self.typefiltercombo.set_active(0)
+        else:
+            cloned = self.datasets.list_cloned_snapshots()
+            num_snap = 0
+            num_rsync = 0
+            for snapname in self.shortcircuit:
+                # Filter out snapshots that are the root
+                # of cloned filesystems or volumes
+                try:
+                    cloned.index(snapname)
+                    dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Snapshot can not be deleted"))
+                    text = _("%s has one or more dependent clones "
+                             "and will not be deleted. To delete "
+                             "this snapshot, first delete all "
+                             "datasets and snapshots cloned from "
+                             "this snapshot.") \
+                             % snapname
+                    dialog.format_secondary_text(text)
+                    dialog.run()
+                    sys.exit(1)
+                except ValueError:
+                    path = os.path.abspath (snapname)
+                    if not os.path.exists (path):
+                        snapshot = zfs.Snapshot(snapname)
+                        self.backuptodelete.append(snapshot)
+                        num_snap += 1
+                    else:
+                        self.backuptodelete.append(RsyncBackup (snapname))
+                        num_rsync += 1
+
+            confirm = self.xml.get_widget("confirmdialog")
+            summary = self.xml.get_widget("summarylabel")
+            total = len(self.backuptodelete)
+
+            text = ""
+            if num_rsync != 0 :
+                if num_rsync == 1:
+                    text = _("1 external backup will be deleted.")
+                else:
+                    text = _("%d external backups will be deleted.") % num_rsync
+
+            if num_snap != 0 :
+                if len(text) != 0:
+                    text += "\n"
+                if num_snap == 1:
+                    text += _("1 snapshot will be deleted.")
+                else:
+                    text += _("%d snapshots will be deleted.") % num_snap
+
+            summary.set_text(text )
+            response = confirm.run()
+            if response != 2:
+                sys.exit(0)
+            else:
+                # Create the thread in an idle loop in order to
+                # avoid deadlock inside gtk.
+                glib.idle_add(self.__init_delete)
+        return False
+
+    def __on_treeviewcol_clicked(self, widget, searchcol):
+        self.snaptreeview.set_search_column(searchcol)
+
+    def __filter_snapshot_list(self, list, filesys = None, snap = None, btype = None):
+        if filesys == None and snap == None and btype == None:
+            return list
+        fssublist = []
+        if filesys != None:
+            for snapshot in list:
+                if snapshot.fsname.find(filesys) != -1:
+                    fssublist.append(snapshot)
+        else:
+            fssublist = list
+
+        snaplist = []
+        if snap != None:
+            for snapshot in fssublist:
+                if  snapshot.snaplabel.find(snap) != -1:
+                    snaplist.append(snapshot)
+        else:
+            snaplist = fssublist
+
+        typelist = []
+        if btype != None and btype != "All":
+            for item in snaplist:
+                if btype == "Backup":
+                    if isinstance(item, RsyncBackup):
+                        typelist.append (item)
+                else:
+                    if isinstance(item, zfs.Snapshot):
+                        typelist.append (item)
+        else:
+            typelist = snaplist
+
+        return typelist
+
+    def __on_filterentry_changed(self, widget):
+        # Get the filesystem filter value
+        iter = self.fsfilterentry.get_active_iter()
+        if iter == None:
+            filesys = self.fsfilterentry.get_active_text()
+        else:
+            model = self.fsfilterentry.get_model()
+            filesys = model.get(iter, 1)[0]
+        # Get the snapshot name filter value
+        iter = self.schedfilterentry.get_active_iter()
+        if iter == None:
+            snap = self.schedfilterentry.get_active_text()
+        else:
+            model = self.schedfilterentry.get_model()
+            snap = model.get(iter, 1)[0]
+
+        # Get the type filter value
+        iter = self.typefiltercombo.get_active_iter()
+        if iter == None:
+            type = "All"
+        else:
+            model = self.typefiltercombo.get_model()
+            type = model.get(iter, 1)[0]
+
+        self.liststorefs.clear()
+        newlist = self.__filter_snapshot_list(self.snapscanner.snapshots,
+                    filesys,
+                    snap, type)
+        for snapshot in newlist:
+            try:
+                tm = time.localtime(snapshot.get_creation_time())
+                t = unicode(time.strftime ("%c", tm),
+                    locale.getpreferredencoding()).encode('utf-8')
+            except:
+                t = time.ctime(snapshot.get_creation_time())
+            try:
+                mount_point = self.snapscanner.mounts[snapshot.fsname]
+                if (mount_point == "legacy"):
+                    mount_point = _("Legacy")
+
+                self.liststorefs.append([
+                       _("Snapshot"),
+                       mount_point,
+                       snapshot.fsname,
+                       snapshot.snaplabel,
+                       t,
+                       snapshot.get_creation_time(),
+                       snapshot])
+            except KeyError:
+                continue
+                # This will catch exceptions from things we ignore
+                # such as dump as swap volumes and skip over them.
+            # add rsync backups
+        newlist = self.__filter_snapshot_list(self.snapscanner.rsynced_backups,
+                                                filesys,
+                                                snap, type)
+        for backup in newlist:
+            self.liststorefs.append([_("Backup"),
+                                     backup.zfs_mountpoint,
+                                     backup.fsname,
+                                     backup.snaplabel,
+                                     backup.creationtime_str,
+                                     backup.creationtime,
+                                     backup])
+
+    def __on_selectbutton_clicked(self, widget):
+        selection = self.snaptreeview.get_selection()
+        selection.select_all()
+        return
+
+    def __on_deselectbutton_clicked(self, widget):
+        selection = self.snaptreeview.get_selection()
+        selection.unselect_all()
+        return
+
+    def __on_deletebutton_clicked(self, widget):
+        self.backuptodelete = []
+        selection = self.snaptreeview.get_selection()
+        selection.selected_foreach(self.__add_selection)
+        total = len(self.backuptodelete)
+        if total <= 0:
+            return
+
+        confirm = self.xml.get_widget("confirmdialog")
+        summary = self.xml.get_widget("summarylabel")
+
+        num_snap = 0
+        num_rsync = 0
+        for item in self.backuptodelete:
+            if isinstance (item, RsyncBackup):
+                num_rsync+=1
+            else:
+                num_snap+=1
+
+        str = ""
+        if num_rsync != 0 :
+            if num_rsync == 1:
+                str = _("1 external backup will be deleted.")
+            else:
+                str = _("%d external backups will be deleted.") % num_rsync
+
+        if num_snap != 0 :
+            if len(str) != 0:
+                str += "\n"
+            if num_snap == 1:
+                str += _("1 snapshot will be deleted.")
+            else:
+                str += _("%d snapshots will be deleted.") % num_snap
+
+        summary.set_text(str)
+        response = confirm.run()
+        if response != 2:
+            return
+        else:
+            glib.idle_add(self.__init_delete)
+        return
+
+    def __init_scan(self):
+        self.snapscanner = ScanSnapshots()
+        self.pulsedialog.show()
+        self.snapscanner.start()
+        glib.timeout_add(100, self.__monitor_scan)
+        return False
+
+    def __init_delete(self):
+        self.snapdeleter = DeleteSnapshots(self.backuptodelete)
+        # If there's more than a few snapshots, pop up
+        # a progress bar.
+        if len(self.backuptodelete) > 3:
+            self.progressbar.set_fraction(0.0)
+            self.progressdialog.show()
+        self.snapdeleter.start()
+        glib.timeout_add(300, self.__monitor_deletion)
+        return False
+
+    def __monitor_scan(self):
+        if self.snapscanner.isAlive() == True:
+            self.xml.get_widget("pulsebar").pulse()
+            return True
+        else:
+            self.pulsedialog.hide()
+            if self.snapscanner.errors:
+                details = ""
+                dialog = gtk.MessageDialog(None,
+                            0,
+                            gtk.MESSAGE_ERROR,
+                            gtk.BUTTONS_CLOSE,
+                            _("Some snapshots could not be read"))
+                dialog.connect("response",
+                            self.__on_errordialog_response)
+                for error in self.snapscanner.errors:
+                    details = details + error
+                dialog.format_secondary_text(details)
+                dialog.show()
+            self.__on_filterentry_changed(None)
+            return False
+
+    def __monitor_deletion(self):
+        if self.snapdeleter.isAlive() == True:
+            self.progressbar.set_fraction(self.snapdeleter.progress)
+            return True
+        else:
+            self.progressdialog.hide()
+            self.progressbar.set_fraction(1.0)
+            self.progressdialog.hide()
+            if self.snapdeleter.errors:
+                details = ""
+                dialog = gtk.MessageDialog(None,
+                            0,
+                            gtk.MESSAGE_ERROR,
+                            gtk.BUTTONS_CLOSE,
+                            _("Some snapshots could not be deleted"))
+                dialog.connect("response",
+                            self.__on_errordialog_response)
+                for error in self.snapdeleter.errors:
+                    details = details + error
+                dialog.format_secondary_text(details)
+                dialog.show()
+            # If we didn't shortcircut straight to the delete confirmation
+            # dialog then the main dialog is visible so we rebuild the list
+            # view.
+            if len(self.shortcircuit) ==  0:
+                self.__refresh_view()
+            else:
+                gtk.main_quit()
+            return False
+
+    def __refresh_view(self):
+        self.liststorefs.clear()
+        glib.idle_add(self.__init_scan)
+        self.backuptodelete = []
+
+    def __add_selection(self, treemodel, path, iter):
+        snapshot = treemodel.get(iter, 6)[0]
+        self.backuptodelete.append(snapshot)
+
+    def __on_confirmcancel_clicked(self, widget):
+        widget.get_toplevel().hide()
+        widget.get_toplevel().response(1)
+
+    def __on_confirmdelete_clicked(self, widget):
+        widget.get_toplevel().hide()
+        widget.get_toplevel().response(2)
+
+    def __on_errordialog_response(self, widget, responseid):
+        widget.hide()
+
+class ScanSnapshots(threading.Thread):
+
+    def __init__(self):
+        threading.Thread.__init__(self)
+        self.errors = []
+        self.datasets = zfs.Datasets()
+        self.snapshots = []
+        self.rsynced_fs = []
+        self.rsynced_backups = []
+
+    def run(self):
+        self.mounts = self.__get_fs_mountpoints()
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        self.__get_rsync_backups ()
+        self.rescan()
+
+    def __get_rsync_backups (self):
+        # get rsync backup dir
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsyncDir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+        if not os.path.exists(self.rsyncDir):
+            return
+
+        rootBackupDirs = []
+
+        for root, dirs, files in os.walk(self.rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove('.time-slider')
+                backupDir = os.path.join(root, rsyncsmf.RSYNCDIRSUFFIX)
+                if os.path.exists(backupDir):
+                    insort(rootBackupDirs, os.path.abspath(backupDir))
+
+        for dirName in rootBackupDirs:
+            os.chdir(dirName)
+            for d in os.listdir(dirName):
+                if os.path.isdir(d) and not os.path.islink(d):
+                    s1 = dirName.split ("%s/" % self.rsyncDir, 1)
+                    s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+                    fs = s2[0]
+
+                    rb = RsyncBackup ("%s/%s" %(dirName, d),
+                                      self.rsyncDir,
+                                      fs,
+                                      d,
+                                      os.stat(d).st_mtime)
+                    self.rsynced_backups.append (rb)
+
+    def __get_fs_mountpoints(self):
+        """Returns a dictionary mapping:
+           {filesystem : mountpoint}"""
+        result = {}
+        for filesys,mountpoint in self.datasets.list_filesystems():
+            result[filesys] = mountpoint
+        return result
+
+    def rescan(self):
+        cloned = self.datasets.list_cloned_snapshots()
+        self.snapshots = []
+        snaplist = self.datasets.list_snapshots()
+        for snapname,snaptime in snaplist:
+            # Filter out snapshots that are the root
+            # of cloned filesystems or volumes
+            try:
+                cloned.index(snapname)
+            except ValueError:
+                snapshot = zfs.Snapshot(snapname, snaptime)
+                self.snapshots.append(snapshot)
+
+class DeleteSnapshots(threading.Thread):
+
+    def __init__(self, snapshots):
+        threading.Thread.__init__(self)
+        self.backuptodelete = snapshots
+        self.started = False
+        self.completed = False
+        self.progress = 0.0
+        self.errors = []
+
+    def run(self):
+        deleted = 0
+        self.started = True
+        total = len(self.backuptodelete)
+        for backup in self.backuptodelete:
+            # The backup could have expired and been automatically
+            # destroyed since the user selected it. Check that it
+            # still exists before attempting to delete it. If it
+            # doesn't exist just silently ignore it.
+            if backup.exists():
+                try:
+                    backup.destroy ()
+                except RuntimeError, inst:
+                    self.errors.append(str(inst))
+            deleted += 1
+            self.progress = deleted / (total * 1.0)
+        self.completed = True
+
+def main(argv):
+    try:
+        opts,args = getopt.getopt(sys.argv[1:], "", [])
+    except getopt.GetoptError:
+        sys.exit(2)
+    rbacp = RBACprofile()
+    if os.geteuid() == 0:
+        if len(args) > 0:
+            manager = DeleteSnapManager(args)
+        else:
+            manager = DeleteSnapManager()
+        gtk.gdk.threads_enter()
+        glib.idle_add(manager.initialise_view)
+        gtk.main()
+        gtk.gdk.threads_leave()
+    elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
+        # Run via gksu, which will prompt for the root password
+        newargs = ["gksu", argv]
+        for arg in args:
+            newargs.append(arg)
+        os.execv("/usr/bin/gksu", newargs);
+        # Shouldn't reach this point
+        sys.exit(1)
+    else:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Insufficient Priviliges"))
+        dialog.format_secondary_text(_("Snapshot deletion requires "
+                                       "administrative privileges to run. "
+                                       "You have not been assigned the necessary"
+                                       "administrative priviliges."
+                                       "\n\nConsult your system administrator "))
+        dialog.run()
+        print argv + "is not a valid executable path"
+        sys.exit(1)
diff --git a/usr/share/time-slider/lib/time_slider/deletegui.py.bak b/usr/share/time-slider/lib/time_slider/deletegui.py.bak
new file mode 100644 (file)
index 0000000..dd157f5
--- /dev/null
@@ -0,0 +1,766 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import threading
+import sys
+import os
+import time
+import getopt
+import locale
+import shutil
+import fcntl
+from bisect import insort
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+try:
+    import glib
+    import gobject
+except:
+    sys.exit(1)
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import rsyncsmf
+
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from rbac import RBACprofile
+
+class RsyncBackup:
+
+    def __init__(self, mountpoint, rsync_dir = None,  fsname= None, snaplabel= None, creationtime= None):
+
+        if rsync_dir == None:
+            self.__init_from_mp (mountpoint)
+        else:
+            self.rsync_dir = rsync_dir
+            self.mountpoint = mountpoint
+            self.fsname = fsname
+            self.snaplabel = snaplabel
+
+            self.creationtime = creationtime
+            try:
+                tm = time.localtime(self.creationtime)
+                self.creationtime_str = unicode(time.strftime ("%c", tm),
+                           locale.getpreferredencoding()).encode('utf-8')
+            except:
+                self.creationtime_str = time.ctime(self.creationtime)
+       fs = zfs.Filesystem (self.fsname)       
+       self.zfs_mountpoint = fs.get_mountpoint ()
+
+    def __init_from_mp (self, mountpoint):
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsync_dir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+        self.mountpoint = mountpoint
+
+        s1 = mountpoint.split ("%s/" % self.rsync_dir, 1)
+        s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+        s3 = s2[1].split ('/',2)
+        self.fsname = s2[0]
+        self.snaplabel =  s3[1]
+        self.creationtime = os.stat(mountpoint).st_mtime
+
+    def __str__(self):
+        ret = "self.rsync_dir = %s\n \
+               self.mountpoint = %s\n \
+               self.fsname = %s\n \
+               self.snaplabel = %s\n" % (self.rsync_dir,
+                                         self.mountpoint, self.fsname,
+                                         self.snaplabel)
+        return ret
+
+
+    def exists(self):
+        return os.path.exists(self.mountpoint)
+
+    def destroy(self):
+        lockFileDir = os.path.join(self.rsync_dir,
+                             self.fsname,
+                             rsyncsmf.RSYNCLOCKSUFFIX)
+
+        if not os.path.exists(lockFileDir):
+            os.makedirs(lockFileDir, 0755)
+
+        lockFile = os.path.join(lockFileDir, self.snaplabel + ".lock")
+        try:
+            lockFp = open(lockFile, 'w')
+            fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+        except IOError:
+            raise RuntimeError, \
+            "couldn't delete %s, already used by another process" % self.mountpoint
+            return
+
+        trashDir = os.path.join(self.rsync_dir,
+                          self.fsname,
+                          rsyncsmf.RSYNCTRASHSUFFIX)
+        if not os.path.exists(trashDir):
+            os.makedirs(trashDir, 0755)
+
+        backupTrashDir = os.path.join (self.rsync_dir,
+                                 self.fsname,
+                                 rsyncsmf.RSYNCTRASHSUFFIX,
+                                 self.snaplabel)
+
+        # move then delete
+        os.rename (self.mountpoint, backupTrashDir)
+        shutil.rmtree (backupTrashDir)
+
+        log = "%s/%s/%s/%s.log" % (self.rsync_dir,
+                                   self.fsname,
+                                   rsyncsmf.RSYNCLOGSUFFIX,
+                                   self.snaplabel)
+        if os.path.exists (log):
+            os.unlink (log)
+
+        lockFp.close()
+        os.unlink(lockFile)
+
+class DeleteSnapManager:
+
+    def __init__(self, snapshots = None):
+        self.xml = gtk.glade.XML("%s/../../glade/time-slider-delete.glade" \
+                                  % (os.path.dirname(__file__)))
+        self.backuptodelete = []
+        self.shortcircuit = []
+        maindialog = self.xml.get_widget("time-slider-delete")
+        self.pulsedialog = self.xml.get_widget("pulsedialog")
+        self.pulsedialog.set_transient_for(maindialog)
+        self.datasets = zfs.Datasets()
+        if snapshots:
+            maindialog.hide()
+            self.shortcircuit = snapshots
+        else:
+            glib.idle_add(self.__init_scan)
+
+        self.progressdialog = self.xml.get_widget("deletingdialog")
+        self.progressdialog.set_transient_for(maindialog)
+        self.progressbar = self.xml.get_widget("deletingprogress")
+        # signal dictionary
+        dic = {"on_closebutton_clicked" : gtk.main_quit,
+               "on_window_delete_event" : gtk.main_quit,
+               "on_snapshotmanager_delete_event" : gtk.main_quit,
+               "on_fsfilterentry_changed" : self.__on_filterentry_changed,
+               "on_schedfilterentry_changed" : self.__on_filterentry_changed,
+               "on_typefiltercombo_changed" : self.__on_filterentry_changed,
+               "on_selectbutton_clicked" : self.__on_selectbutton_clicked,
+               "on_deselectbutton_clicked" : self.__on_deselectbutton_clicked,
+               "on_deletebutton_clicked" : self.__on_deletebutton_clicked,
+               "on_confirmcancel_clicked" : self.__on_confirmcancel_clicked,
+               "on_confirmdelete_clicked" : self.__on_confirmdelete_clicked,
+               "on_errordialog_response" : self.__on_errordialog_response}
+        self.xml.signal_autoconnect(dic)
+
+    def initialise_view(self):
+        if len(self.shortcircuit) == 0:
+            # Set TreeViews
+            self.liststorefs = gtk.ListStore(str, str, str, str, str, long,
+                                             gobject.TYPE_PYOBJECT)
+            list_filter = self.liststorefs.filter_new()
+            list_sort = gtk.TreeModelSort(list_filter)
+            list_sort.set_sort_column_id(1, gtk.SORT_ASCENDING)
+
+            self.snaptreeview = self.xml.get_widget("snaplist")
+            self.snaptreeview.set_model(self.liststorefs)
+            self.snaptreeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+
+            cell0 = gtk.CellRendererText()
+            cell1 = gtk.CellRendererText()
+            cell2 = gtk.CellRendererText()
+            cell3 = gtk.CellRendererText()
+            cell4 = gtk.CellRendererText()
+            cell5 = gtk.CellRendererText()
+
+            typecol = gtk.TreeViewColumn(_("Type"),
+                                            cell0, text = 0)
+            typecol.set_sort_column_id(0)
+            typecol.set_resizable(True)
+            typecol.connect("clicked",
+                self.__on_treeviewcol_clicked, 0)
+            self.snaptreeview.append_column(typecol)
+
+            mountptcol = gtk.TreeViewColumn(_("Mount Point"),
+                                            cell1, text = 1)
+            mountptcol.set_sort_column_id(1)
+            mountptcol.set_resizable(True)
+            mountptcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 1)
+            self.snaptreeview.append_column(mountptcol)
+
+            fsnamecol = gtk.TreeViewColumn(_("File System Name"),
+                                           cell2, text = 2)
+            fsnamecol.set_sort_column_id(2)
+            fsnamecol.set_resizable(True)
+            fsnamecol.connect("clicked",
+                self.__on_treeviewcol_clicked, 2)
+            self.snaptreeview.append_column(fsnamecol)
+
+            snaplabelcol = gtk.TreeViewColumn(_("Snapshot Name"),
+                                              cell3, text = 3)
+            snaplabelcol.set_sort_column_id(3)
+            snaplabelcol.set_resizable(True)
+            snaplabelcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 3)
+            self.snaptreeview.append_column(snaplabelcol)
+
+            cell4.props.xalign = 1.0
+            creationcol = gtk.TreeViewColumn(_("Creation Time"),
+                                             cell4, text = 4)
+            creationcol.set_sort_column_id(5)
+            creationcol.set_resizable(True)
+            creationcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 5)
+            self.snaptreeview.append_column(creationcol)
+
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            typestore = gtk.ListStore(str, str)
+            typestore.append([_("All"), "All"])
+            typestore.append([_("Backups"), "Backup"])
+            typestore.append([_("Snapshots"), "Snapshot"])
+
+            self.typefiltercombo = self.xml.get_widget("typefiltercombo")
+            self.typefiltercombo.set_model(typestore)
+            typefiltercomboCell = gtk.CellRendererText()
+            self.typefiltercombo.pack_start(typefiltercomboCell, True)
+            self.typefiltercombo.add_attribute(typefiltercomboCell, 'text',0)
+
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            fsstore = gtk.ListStore(str, str)
+            fslist = self.datasets.list_filesystems()
+            fsstore.append([_("All"), None])
+            for fsname,fsmount in fslist:
+                fsstore.append([fsname, fsname])
+            self.fsfilterentry = self.xml.get_widget("fsfilterentry")
+            self.fsfilterentry.set_model(fsstore)
+            self.fsfilterentry.set_text_column(0)
+            fsfilterentryCell = gtk.CellRendererText()
+            self.fsfilterentry.pack_start(fsfilterentryCell)
+
+            schedstore = gtk.ListStore(str, str)
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            schedstore.append([_("All"), None])
+            schedstore.append([_("Monthly"), "monthly"])
+            schedstore.append([_("Weekly"), "weekly"])
+            schedstore.append([_("Daily"), "daily"])
+            schedstore.append([_("Hourly"), "hourly"])
+            schedstore.append([_("1/4 Hourly"), "frequent"])
+            self.schedfilterentry = self.xml.get_widget("schedfilterentry")
+            self.schedfilterentry.set_model(schedstore)
+            self.schedfilterentry.set_text_column(0)
+            schedentryCell = gtk.CellRendererText()
+            self.schedfilterentry.pack_start(schedentryCell)
+
+            self.schedfilterentry.set_active(0)
+            self.fsfilterentry.set_active(0)
+            self.typefiltercombo.set_active(0)
+        else:
+            cloned = self.datasets.list_cloned_snapshots()
+            num_snap = 0
+            num_rsync = 0
+            for snapname in self.shortcircuit:
+                # Filter out snapshots that are the root
+                # of cloned filesystems or volumes
+                try:
+                    cloned.index(snapname)
+                    dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Snapshot can not be deleted"))
+                    text = _("%s has one or more dependent clones "
+                             "and will not be deleted. To delete "
+                             "this snapshot, first delete all "
+                             "datasets and snapshots cloned from "
+                             "this snapshot.") \
+                             % snapname
+                    dialog.format_secondary_text(text)
+                    dialog.run()
+                    sys.exit(1)
+                except ValueError:
+                   path = os.path.abspath (snapname)
+                    if not os.path.exists (path):
+                        snapshot = zfs.Snapshot(snapname)
+                        self.backuptodelete.append(snapshot)
+                        num_snap += 1
+                    else:
+                        self.backuptodelete.append(RsyncBackup (snapname))
+                        num_rsync += 1
+
+            confirm = self.xml.get_widget("confirmdialog")
+            summary = self.xml.get_widget("summarylabel")
+            total = len(self.backuptodelete)
+
+            text = ""
+            if num_rsync != 0 :
+                if num_rsync == 1:
+                    text = _("1 external backup will be deleted.")
+                else:
+                    text = _("%d external backups will be deleted.") % num_rsync
+
+            if num_snap != 0 :
+                if len(text) != 0:
+                    text += "\n"
+                if num_snap == 1:
+                    text += _("1 snapshot will be deleted.")
+                else:
+                    text += _("%d snapshots will be deleted.") % num_snap
+
+            summary.set_text(text )
+            response = confirm.run()
+            if response != 2:
+                sys.exit(0)
+            else:
+                # Create the thread in an idle loop in order to
+                # avoid deadlock inside gtk.
+                glib.idle_add(self.__init_delete)
+        return False
+
+    def __on_treeviewcol_clicked(self, widget, searchcol):
+        self.snaptreeview.set_search_column(searchcol)
+
+    def __filter_snapshot_list(self, list, filesys = None, snap = None, btype = None):
+        if filesys == None and snap == None and btype == None:
+            return list
+        fssublist = []
+        if filesys != None:
+            for snapshot in list:
+                if snapshot.fsname.find(filesys) != -1:
+                    fssublist.append(snapshot)
+        else:
+            fssublist = list
+
+        snaplist = []
+        if snap != None:
+            for snapshot in fssublist:
+                if  snapshot.snaplabel.find(snap) != -1:
+                    snaplist.append(snapshot)
+        else:
+            snaplist = fssublist
+
+        typelist = []
+        if btype != None and btype != "All":
+            for item in snaplist:
+                if btype == "Backup":
+                    if isinstance(item, RsyncBackup):
+                        typelist.append (item)
+                else:
+                    if isinstance(item, zfs.Snapshot):
+                        typelist.append (item)
+        else:
+            typelist = snaplist
+
+        return typelist
+
+    def __on_filterentry_changed(self, widget):
+        # Get the filesystem filter value
+        iter = self.fsfilterentry.get_active_iter()
+        if iter == None:
+            filesys = self.fsfilterentry.get_active_text()
+        else:
+            model = self.fsfilterentry.get_model()
+            filesys = model.get(iter, 1)[0]
+        # Get the snapshot name filter value
+        iter = self.schedfilterentry.get_active_iter()
+        if iter == None:
+            snap = self.schedfilterentry.get_active_text()
+        else:
+            model = self.schedfilterentry.get_model()
+            snap = model.get(iter, 1)[0]
+
+        # Get the type filter value
+        iter = self.typefiltercombo.get_active_iter()
+        if iter == None:
+            type = "All"
+        else:
+            model = self.typefiltercombo.get_model()
+            type = model.get(iter, 1)[0]
+
+        self.liststorefs.clear()
+        newlist = self.__filter_snapshot_list(self.snapscanner.snapshots,
+                    filesys,
+                    snap, type)
+        for snapshot in newlist:
+            try:
+                tm = time.localtime(snapshot.get_creation_time())
+                t = unicode(time.strftime ("%c", tm),
+                    locale.getpreferredencoding()).encode('utf-8')
+            except:
+                t = time.ctime(snapshot.get_creation_time())
+            try:
+                mount_point = self.snapscanner.mounts[snapshot.fsname]
+                if (mount_point == "legacy"):
+                    mount_point = _("Legacy")
+
+                self.liststorefs.append([
+                       _("Snapshot"),
+                       mount_point,
+                       snapshot.fsname,
+                       snapshot.snaplabel,
+                       t,
+                       snapshot.get_creation_time(),
+                       snapshot])
+            except KeyError:
+                continue
+                # This will catch exceptions from things we ignore
+                # such as dump as swap volumes and skip over them.
+            # add rsync backups
+        newlist = self.__filter_snapshot_list(self.snapscanner.rsynced_backups,
+                                                filesys,
+                                                snap, type)
+        for backup in newlist:
+            self.liststorefs.append([_("Backup"),
+                                     backup.zfs_mountpoint,
+                                     backup.fsname,
+                                     backup.snaplabel,
+                                     backup.creationtime_str,
+                                     backup.creationtime,
+                                     backup])
+
+    def __on_selectbutton_clicked(self, widget):
+        selection = self.snaptreeview.get_selection()
+        selection.select_all()
+        return
+
+    def __on_deselectbutton_clicked(self, widget):
+        selection = self.snaptreeview.get_selection()
+        selection.unselect_all()
+        return
+
+    def __on_deletebutton_clicked(self, widget):
+        self.backuptodelete = []
+        selection = self.snaptreeview.get_selection()
+        selection.selected_foreach(self.__add_selection)
+        total = len(self.backuptodelete)
+        if total <= 0:
+            return
+
+        confirm = self.xml.get_widget("confirmdialog")
+        summary = self.xml.get_widget("summarylabel")
+
+        num_snap = 0
+        num_rsync = 0
+        for item in self.backuptodelete:
+            if isinstance (item, RsyncBackup):
+                num_rsync+=1
+            else:
+                num_snap+=1
+
+        str = ""
+        if num_rsync != 0 :
+            if num_rsync == 1:
+                str = _("1 external backup will be deleted.")
+            else:
+                str = _("%d external backups will be deleted.") % num_rsync
+
+        if num_snap != 0 :
+            if len(str) != 0:
+                str += "\n"
+            if num_snap == 1:
+                str += _("1 snapshot will be deleted.")
+            else:
+                str += _("%d snapshots will be deleted.") % num_snap
+
+        summary.set_text(str)
+        response = confirm.run()
+        if response != 2:
+            return
+        else:
+            glib.idle_add(self.__init_delete)
+        return
+
+    def __init_scan(self):
+        self.snapscanner = ScanSnapshots()
+        self.pulsedialog.show()
+        self.snapscanner.start()
+        glib.timeout_add(100, self.__monitor_scan)
+        return False
+
+    def __init_delete(self):
+        self.snapdeleter = DeleteSnapshots(self.backuptodelete)
+        # If there's more than a few snapshots, pop up
+        # a progress bar.
+        if len(self.backuptodelete) > 3:
+            self.progressbar.set_fraction(0.0)
+            self.progressdialog.show()
+        self.snapdeleter.start()
+        glib.timeout_add(300, self.__monitor_deletion)
+        return False
+
+    def __monitor_scan(self):
+        if self.snapscanner.isAlive() == True:
+            self.xml.get_widget("pulsebar").pulse()
+            return True
+        else:
+            self.pulsedialog.hide()
+            if self.snapscanner.errors:
+                details = ""
+                dialog = gtk.MessageDialog(None,
+                            0,
+                            gtk.MESSAGE_ERROR,
+                            gtk.BUTTONS_CLOSE,
+                            _("Some snapshots could not be read"))
+                dialog.connect("response",
+                            self.__on_errordialog_response)
+                for error in self.snapscanner.errors:
+                    details = details + error
+                dialog.format_secondary_text(details)
+                dialog.show()
+            self.__on_filterentry_changed(None)
+            return False
+
+    def __monitor_deletion(self):
+        if self.snapdeleter.isAlive() == True:
+            self.progressbar.set_fraction(self.snapdeleter.progress)
+            return True
+        else:
+            self.progressdialog.hide()
+            self.progressbar.set_fraction(1.0)
+            self.progressdialog.hide()
+            if self.snapdeleter.errors:
+                details = ""
+                dialog = gtk.MessageDialog(None,
+                            0,
+                            gtk.MESSAGE_ERROR,
+                            gtk.BUTTONS_CLOSE,
+                            _("Some snapshots could not be deleted"))
+                dialog.connect("response",
+                            self.__on_errordialog_response)
+                for error in self.snapdeleter.errors:
+                    details = details + error
+                dialog.format_secondary_text(details)
+                dialog.show()
+            # If we didn't shortcircut straight to the delete confirmation
+            # dialog then the main dialog is visible so we rebuild the list
+            # view.
+            if len(self.shortcircuit) ==  0:
+                self.__refresh_view()
+            else:
+                gtk.main_quit()
+            return False
+
+    def __refresh_view(self):
+        self.liststorefs.clear()
+        glib.idle_add(self.__init_scan)
+        self.backuptodelete = []
+
+    def __add_selection(self, treemodel, path, iter):
+        snapshot = treemodel.get(iter, 8)[0]
+        self.backuptodelete.append(snapshot)
+
+    def __on_confirmcancel_clicked(self, widget):
+        widget.get_toplevel().hide()
+        widget.get_toplevel().response(1)
+
+    def __on_confirmdelete_clicked(self, widget):
+        widget.get_toplevel().hide()
+        widget.get_toplevel().response(2)
+
+    def __on_errordialog_response(self, widget, responseid):
+        widget.hide()
+
+class ScanSnapshots(threading.Thread):
+
+    def __init__(self):
+        threading.Thread.__init__(self)
+        self.errors = []
+        self.datasets = zfs.Datasets()
+        self.snapshots = []
+        self.rsynced_fs = []
+        self.rsynced_backups = []
+
+    def run(self):
+        self.mounts = self.__get_fs_mountpoints()
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        self.__get_rsync_backups ()
+        self.rescan()
+
+    def __get_rsync_backups (self):
+        # get rsync backup dir
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsyncDir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+        if not os.path.exists(self.rsyncDir):
+            return
+
+        rootBackupDirs = []
+
+       for root, dirs, files in os.walk(self.rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove('.time-slider')
+                backupDir = os.path.join(root, rsyncsmf.RSYNCDIRSUFFIX)
+                if os.path.exists(backupDir):
+                    insort(rootBackupDirs, os.path.abspath(backupDir))
+
+        for dirName in rootBackupDirs:
+            os.chdir(dirName)
+            for d in os.listdir(dirName):
+                if os.path.isdir(d) and not os.path.islink(d):
+                    s1 = dirName.split ("%s/" % self.rsyncDir, 1)
+                    s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+                    fs = s2[0]
+
+                    rb = RsyncBackup ("%s/%s" %(dirName, d),
+                                      self.rsyncDir,
+                                      fs,
+                                      d,
+                                      os.stat(d).st_mtime)
+                    self.rsynced_backups.append (rb)
+
+    def __get_fs_mountpoints(self):
+        """Returns a dictionary mapping:
+           {filesystem : mountpoint}"""
+        result = {}
+        for filesys,mountpoint in self.datasets.list_filesystems():
+            result[filesys] = mountpoint
+        return result
+
+    def rescan(self):
+        cloned = self.datasets.list_cloned_snapshots()
+        self.snapshots = []
+        snaplist = self.datasets.list_snapshots()
+        for snapname,snaptime in snaplist:
+            # Filter out snapshots that are the root
+            # of cloned filesystems or volumes
+            try:
+                cloned.index(snapname)
+            except ValueError:
+                snapshot = zfs.Snapshot(snapname, snaptime)
+                self.snapshots.append(snapshot)
+
+class DeleteSnapshots(threading.Thread):
+
+    def __init__(self, snapshots):
+        threading.Thread.__init__(self)
+        self.backuptodelete = snapshots
+        self.started = False
+        self.completed = False
+        self.progress = 0.0
+        self.errors = []
+
+    def run(self):
+        deleted = 0
+        self.started = True
+        total = len(self.backuptodelete)
+        for backup in self.backuptodelete:
+            # The backup could have expired and been automatically
+            # destroyed since the user selected it. Check that it
+            # still exists before attempting to delete it. If it
+            # doesn't exist just silently ignore it.
+            if backup.exists():
+                try:
+                    backup.destroy ()
+                except RuntimeError, inst:
+                    self.errors.append(str(inst))
+            deleted += 1
+            self.progress = deleted / (total * 1.0)
+        self.completed = True
+
+def main(argv):
+    try:
+        opts,args = getopt.getopt(sys.argv[1:], "", [])
+    except getopt.GetoptError:
+        sys.exit(2)
+    rbacp = RBACprofile()
+    if os.geteuid() == 0:
+        if len(args) > 0:
+            manager = DeleteSnapManager(args)
+        else:
+            manager = DeleteSnapManager()
+        gtk.gdk.threads_enter()
+        glib.idle_add(manager.initialise_view)
+        gtk.main()
+        gtk.gdk.threads_leave()
+    elif rbacp.has_profile("Primary Administrator") or \
+            rbacp.has_profile("ZFS File System Management"):
+        # Run via pfexec, which will launch the GUI as superuser
+        arguments = []
+        arguments.append ("pfexec")
+        arguments.append (argv)
+        arguments += args
+        os.execv("/usr/bin/pfexec", arguments)
+        # Shouldn't reach this point
+        sys.exit(1)
+    elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
+        # Run via gksu, which will prompt for the root password
+        newargs = ["gksu", argv]
+        for arg in args:
+            newargs.append(arg)
+        os.execv("/usr/bin/gksu", newargs);
+        # Shouldn't reach this point
+        sys.exit(1)
+    else:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Insufficient Priviliges"))
+        dialog.format_secondary_text(_("Snapshot deletion requires "
+                                       "administrative privileges to run. "
+                                       "You have not been assigned the necessary"
+                                       "administrative priviliges."
+                                       "\n\nConsult your system administrator "))
+        dialog.run()
+        print argv + "is not a valid executable path"
+        sys.exit(1)
diff --git a/usr/share/time-slider/lib/time_slider/deletegui.py~ b/usr/share/time-slider/lib/time_slider/deletegui.py~
new file mode 100755 (executable)
index 0000000..8023d9a
--- /dev/null
@@ -0,0 +1,756 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import threading
+import sys
+import os
+import time
+import getopt
+import locale
+import shutil
+import fcntl
+from bisect import insort
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+try:
+    import glib
+    import gobject
+except:
+    sys.exit(1)
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import rsyncsmf
+
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from rbac import RBACprofile
+
+class RsyncBackup:
+
+    def __init__(self, mountpoint, rsync_dir = None,  fsname= None, snaplabel= None, creationtime= None):
+
+        if rsync_dir == None:
+            self.__init_from_mp (mountpoint)
+        else:
+            self.rsync_dir = rsync_dir
+            self.mountpoint = mountpoint
+            self.fsname = fsname
+            self.snaplabel = snaplabel
+
+            self.creationtime = creationtime
+            try:
+                tm = time.localtime(self.creationtime)
+                self.creationtime_str = unicode(time.strftime ("%c", tm),
+                           locale.getpreferredencoding()).encode('utf-8')
+            except:
+                self.creationtime_str = time.ctime(self.creationtime)
+        fs = zfs.Filesystem (self.fsname)
+        self.zfs_mountpoint = fs.get_mountpoint ()
+
+    def __init_from_mp (self, mountpoint):
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsync_dir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+        self.mountpoint = mountpoint
+
+        s1 = mountpoint.split ("%s/" % self.rsync_dir, 1)
+        s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+        s3 = s2[1].split ('/',2)
+        self.fsname = s2[0]
+        self.snaplabel =  s3[1]
+        self.creationtime = os.stat(mountpoint).st_mtime
+
+    def __str__(self):
+        ret = "self.rsync_dir = %s\n \
+               self.mountpoint = %s\n \
+               self.fsname = %s\n \
+               self.snaplabel = %s\n" % (self.rsync_dir,
+                                         self.mountpoint, self.fsname,
+                                         self.snaplabel)
+        return ret
+
+
+    def exists(self):
+        return os.path.exists(self.mountpoint)
+
+    def destroy(self):
+        lockFileDir = os.path.join(self.rsync_dir,
+                             self.fsname,
+                             rsyncsmf.RSYNCLOCKSUFFIX)
+
+        if not os.path.exists(lockFileDir):
+            os.makedirs(lockFileDir, 0755)
+
+        lockFile = os.path.join(lockFileDir, self.snaplabel + ".lock")
+        try:
+            lockFp = open(lockFile, 'w')
+            fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+        except IOError:
+            raise RuntimeError, \
+            "couldn't delete %s, already used by another process" % self.mountpoint
+            return
+
+        trashDir = os.path.join(self.rsync_dir,
+                          self.fsname,
+                          rsyncsmf.RSYNCTRASHSUFFIX)
+        if not os.path.exists(trashDir):
+            os.makedirs(trashDir, 0755)
+
+        backupTrashDir = os.path.join (self.rsync_dir,
+                                 self.fsname,
+                                 rsyncsmf.RSYNCTRASHSUFFIX,
+                                 self.snaplabel)
+
+        # move then delete
+        os.rename (self.mountpoint, backupTrashDir)
+        shutil.rmtree (backupTrashDir)
+
+        log = "%s/%s/%s/%s.log" % (self.rsync_dir,
+                                   self.fsname,
+                                   rsyncsmf.RSYNCLOGSUFFIX,
+                                   self.snaplabel)
+        if os.path.exists (log):
+            os.unlink (log)
+
+        lockFp.close()
+        os.unlink(lockFile)
+
+class DeleteSnapManager:
+
+    def __init__(self, snapshots = None):
+        self.xml = gtk.glade.XML("%s/../../glade/time-slider-delete.glade" \
+                                  % (os.path.dirname(__file__)))
+        self.backuptodelete = []
+        self.shortcircuit = []
+        maindialog = self.xml.get_widget("time-slider-delete")
+        self.pulsedialog = self.xml.get_widget("pulsedialog")
+        self.pulsedialog.set_transient_for(maindialog)
+        self.datasets = zfs.Datasets()
+        if snapshots:
+            maindialog.hide()
+            self.shortcircuit = snapshots
+        else:
+            glib.idle_add(self.__init_scan)
+
+        self.progressdialog = self.xml.get_widget("deletingdialog")
+        self.progressdialog.set_transient_for(maindialog)
+        self.progressbar = self.xml.get_widget("deletingprogress")
+        # signal dictionary
+        dic = {"on_closebutton_clicked" : gtk.main_quit,
+               "on_window_delete_event" : gtk.main_quit,
+               "on_snapshotmanager_delete_event" : gtk.main_quit,
+               "on_fsfilterentry_changed" : self.__on_filterentry_changed,
+               "on_schedfilterentry_changed" : self.__on_filterentry_changed,
+               "on_typefiltercombo_changed" : self.__on_filterentry_changed,
+               "on_selectbutton_clicked" : self.__on_selectbutton_clicked,
+               "on_deselectbutton_clicked" : self.__on_deselectbutton_clicked,
+               "on_deletebutton_clicked" : self.__on_deletebutton_clicked,
+               "on_confirmcancel_clicked" : self.__on_confirmcancel_clicked,
+               "on_confirmdelete_clicked" : self.__on_confirmdelete_clicked,
+               "on_errordialog_response" : self.__on_errordialog_response}
+        self.xml.signal_autoconnect(dic)
+
+    def initialise_view(self):
+        if len(self.shortcircuit) == 0:
+            # Set TreeViews
+            self.liststorefs = gtk.ListStore(str, str, str, str, str, long,
+                                             gobject.TYPE_PYOBJECT)
+            list_filter = self.liststorefs.filter_new()
+            list_sort = gtk.TreeModelSort(list_filter)
+            list_sort.set_sort_column_id(1, gtk.SORT_ASCENDING)
+
+            self.snaptreeview = self.xml.get_widget("snaplist")
+            self.snaptreeview.set_model(self.liststorefs)
+            self.snaptreeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+
+            cell0 = gtk.CellRendererText()
+            cell1 = gtk.CellRendererText()
+            cell2 = gtk.CellRendererText()
+            cell3 = gtk.CellRendererText()
+            cell4 = gtk.CellRendererText()
+            cell5 = gtk.CellRendererText()
+
+            typecol = gtk.TreeViewColumn(_("Type"),
+                                            cell0, text = 0)
+            typecol.set_sort_column_id(0)
+            typecol.set_resizable(True)
+            typecol.connect("clicked",
+                self.__on_treeviewcol_clicked, 0)
+            self.snaptreeview.append_column(typecol)
+
+            mountptcol = gtk.TreeViewColumn(_("Mount Point"),
+                                            cell1, text = 1)
+            mountptcol.set_sort_column_id(1)
+            mountptcol.set_resizable(True)
+            mountptcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 1)
+            self.snaptreeview.append_column(mountptcol)
+
+            fsnamecol = gtk.TreeViewColumn(_("File System Name"),
+                                           cell2, text = 2)
+            fsnamecol.set_sort_column_id(2)
+            fsnamecol.set_resizable(True)
+            fsnamecol.connect("clicked",
+                self.__on_treeviewcol_clicked, 2)
+            self.snaptreeview.append_column(fsnamecol)
+
+            snaplabelcol = gtk.TreeViewColumn(_("Snapshot Name"),
+                                              cell3, text = 3)
+            snaplabelcol.set_sort_column_id(3)
+            snaplabelcol.set_resizable(True)
+            snaplabelcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 3)
+            self.snaptreeview.append_column(snaplabelcol)
+
+            cell4.props.xalign = 1.0
+            creationcol = gtk.TreeViewColumn(_("Creation Time"),
+                                             cell4, text = 4)
+            creationcol.set_sort_column_id(5)
+            creationcol.set_resizable(True)
+            creationcol.connect("clicked",
+                self.__on_treeviewcol_clicked, 5)
+            self.snaptreeview.append_column(creationcol)
+
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            typestore = gtk.ListStore(str, str)
+            typestore.append([_("All"), "All"])
+            typestore.append([_("Backups"), "Backup"])
+            typestore.append([_("Snapshots"), "Snapshot"])
+
+            self.typefiltercombo = self.xml.get_widget("typefiltercombo")
+            self.typefiltercombo.set_model(typestore)
+            typefiltercomboCell = gtk.CellRendererText()
+            self.typefiltercombo.pack_start(typefiltercomboCell, True)
+            self.typefiltercombo.add_attribute(typefiltercomboCell, 'text',0)
+
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            fsstore = gtk.ListStore(str, str)
+            fslist = self.datasets.list_filesystems()
+            fsstore.append([_("All"), None])
+            for fsname,fsmount in fslist:
+                fsstore.append([fsname, fsname])
+            self.fsfilterentry = self.xml.get_widget("fsfilterentry")
+            self.fsfilterentry.set_model(fsstore)
+            self.fsfilterentry.set_text_column(0)
+            fsfilterentryCell = gtk.CellRendererText()
+            self.fsfilterentry.pack_start(fsfilterentryCell)
+
+            schedstore = gtk.ListStore(str, str)
+            # Note to developers.
+            # The second element is for internal matching and should not
+            # be i18ned under any circumstances.
+            schedstore.append([_("All"), None])
+            schedstore.append([_("Monthly"), "monthly"])
+            schedstore.append([_("Weekly"), "weekly"])
+            schedstore.append([_("Daily"), "daily"])
+            schedstore.append([_("Hourly"), "hourly"])
+            schedstore.append([_("1/4 Hourly"), "frequent"])
+            self.schedfilterentry = self.xml.get_widget("schedfilterentry")
+            self.schedfilterentry.set_model(schedstore)
+            self.schedfilterentry.set_text_column(0)
+            schedentryCell = gtk.CellRendererText()
+            self.schedfilterentry.pack_start(schedentryCell)
+
+            self.schedfilterentry.set_active(0)
+            self.fsfilterentry.set_active(0)
+            self.typefiltercombo.set_active(0)
+        else:
+            cloned = self.datasets.list_cloned_snapshots()
+            num_snap = 0
+            num_rsync = 0
+            for snapname in self.shortcircuit:
+                # Filter out snapshots that are the root
+                # of cloned filesystems or volumes
+                try:
+                    cloned.index(snapname)
+                    dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Snapshot can not be deleted"))
+                    text = _("%s has one or more dependent clones "
+                             "and will not be deleted. To delete "
+                             "this snapshot, first delete all "
+                             "datasets and snapshots cloned from "
+                             "this snapshot.") \
+                             % snapname
+                    dialog.format_secondary_text(text)
+                    dialog.run()
+                    sys.exit(1)
+                except ValueError:
+                    path = os.path.abspath (snapname)
+                    if not os.path.exists (path):
+                        snapshot = zfs.Snapshot(snapname)
+                        self.backuptodelete.append(snapshot)
+                        num_snap += 1
+                    else:
+                        self.backuptodelete.append(RsyncBackup (snapname))
+                        num_rsync += 1
+
+            confirm = self.xml.get_widget("confirmdialog")
+            summary = self.xml.get_widget("summarylabel")
+            total = len(self.backuptodelete)
+
+            text = ""
+            if num_rsync != 0 :
+                if num_rsync == 1:
+                    text = _("1 external backup will be deleted.")
+                else:
+                    text = _("%d external backups will be deleted.") % num_rsync
+
+            if num_snap != 0 :
+                if len(text) != 0:
+                    text += "\n"
+                if num_snap == 1:
+                    text += _("1 snapshot will be deleted.")
+                else:
+                    text += _("%d snapshots will be deleted.") % num_snap
+
+            summary.set_text(text )
+            response = confirm.run()
+            if response != 2:
+                sys.exit(0)
+            else:
+                # Create the thread in an idle loop in order to
+                # avoid deadlock inside gtk.
+                glib.idle_add(self.__init_delete)
+        return False
+
+    def __on_treeviewcol_clicked(self, widget, searchcol):
+        self.snaptreeview.set_search_column(searchcol)
+
+    def __filter_snapshot_list(self, list, filesys = None, snap = None, btype = None):
+        if filesys == None and snap == None and btype == None:
+            return list
+        fssublist = []
+        if filesys != None:
+            for snapshot in list:
+                if snapshot.fsname.find(filesys) != -1:
+                    fssublist.append(snapshot)
+        else:
+            fssublist = list
+
+        snaplist = []
+        if snap != None:
+            for snapshot in fssublist:
+                if  snapshot.snaplabel.find(snap) != -1:
+                    snaplist.append(snapshot)
+        else:
+            snaplist = fssublist
+
+        typelist = []
+        if btype != None and btype != "All":
+            for item in snaplist:
+                if btype == "Backup":
+                    if isinstance(item, RsyncBackup):
+                        typelist.append (item)
+                else:
+                    if isinstance(item, zfs.Snapshot):
+                        typelist.append (item)
+        else:
+            typelist = snaplist
+
+        return typelist
+
+    def __on_filterentry_changed(self, widget):
+        # Get the filesystem filter value
+        iter = self.fsfilterentry.get_active_iter()
+        if iter == None:
+            filesys = self.fsfilterentry.get_active_text()
+        else:
+            model = self.fsfilterentry.get_model()
+            filesys = model.get(iter, 1)[0]
+        # Get the snapshot name filter value
+        iter = self.schedfilterentry.get_active_iter()
+        if iter == None:
+            snap = self.schedfilterentry.get_active_text()
+        else:
+            model = self.schedfilterentry.get_model()
+            snap = model.get(iter, 1)[0]
+
+        # Get the type filter value
+        iter = self.typefiltercombo.get_active_iter()
+        if iter == None:
+            type = "All"
+        else:
+            model = self.typefiltercombo.get_model()
+            type = model.get(iter, 1)[0]
+
+        self.liststorefs.clear()
+        newlist = self.__filter_snapshot_list(self.snapscanner.snapshots,
+                    filesys,
+                    snap, type)
+        for snapshot in newlist:
+            try:
+                tm = time.localtime(snapshot.get_creation_time())
+                t = unicode(time.strftime ("%c", tm),
+                    locale.getpreferredencoding()).encode('utf-8')
+            except:
+                t = time.ctime(snapshot.get_creation_time())
+            try:
+                mount_point = self.snapscanner.mounts[snapshot.fsname]
+                if (mount_point == "legacy"):
+                    mount_point = _("Legacy")
+
+                self.liststorefs.append([
+                       _("Snapshot"),
+                       mount_point,
+                       snapshot.fsname,
+                       snapshot.snaplabel,
+                       t,
+                       snapshot.get_creation_time(),
+                       snapshot])
+            except KeyError:
+                continue
+                # This will catch exceptions from things we ignore
+                # such as dump as swap volumes and skip over them.
+            # add rsync backups
+        newlist = self.__filter_snapshot_list(self.snapscanner.rsynced_backups,
+                                                filesys,
+                                                snap, type)
+        for backup in newlist:
+            self.liststorefs.append([_("Backup"),
+                                     backup.zfs_mountpoint,
+                                     backup.fsname,
+                                     backup.snaplabel,
+                                     backup.creationtime_str,
+                                     backup.creationtime,
+                                     backup])
+
+    def __on_selectbutton_clicked(self, widget):
+        selection = self.snaptreeview.get_selection()
+        selection.select_all()
+        return
+
+    def __on_deselectbutton_clicked(self, widget):
+        selection = self.snaptreeview.get_selection()
+        selection.unselect_all()
+        return
+
+    def __on_deletebutton_clicked(self, widget):
+        self.backuptodelete = []
+        selection = self.snaptreeview.get_selection()
+        selection.selected_foreach(self.__add_selection)
+        total = len(self.backuptodelete)
+        if total <= 0:
+            return
+
+        confirm = self.xml.get_widget("confirmdialog")
+        summary = self.xml.get_widget("summarylabel")
+
+        num_snap = 0
+        num_rsync = 0
+        for item in self.backuptodelete:
+            if isinstance (item, RsyncBackup):
+                num_rsync+=1
+            else:
+                num_snap+=1
+
+        str = ""
+        if num_rsync != 0 :
+            if num_rsync == 1:
+                str = _("1 external backup will be deleted.")
+            else:
+                str = _("%d external backups will be deleted.") % num_rsync
+
+        if num_snap != 0 :
+            if len(str) != 0:
+                str += "\n"
+            if num_snap == 1:
+                str += _("1 snapshot will be deleted.")
+            else:
+                str += _("%d snapshots will be deleted.") % num_snap
+
+        summary.set_text(str)
+        response = confirm.run()
+        if response != 2:
+            return
+        else:
+            glib.idle_add(self.__init_delete)
+        return
+
+    def __init_scan(self):
+        self.snapscanner = ScanSnapshots()
+        self.pulsedialog.show()
+        self.snapscanner.start()
+        glib.timeout_add(100, self.__monitor_scan)
+        return False
+
+    def __init_delete(self):
+        self.snapdeleter = DeleteSnapshots(self.backuptodelete)
+        # If there's more than a few snapshots, pop up
+        # a progress bar.
+        if len(self.backuptodelete) > 3:
+            self.progressbar.set_fraction(0.0)
+            self.progressdialog.show()
+        self.snapdeleter.start()
+        glib.timeout_add(300, self.__monitor_deletion)
+        return False
+
+    def __monitor_scan(self):
+        if self.snapscanner.isAlive() == True:
+            self.xml.get_widget("pulsebar").pulse()
+            return True
+        else:
+            self.pulsedialog.hide()
+            if self.snapscanner.errors:
+                details = ""
+                dialog = gtk.MessageDialog(None,
+                            0,
+                            gtk.MESSAGE_ERROR,
+                            gtk.BUTTONS_CLOSE,
+                            _("Some snapshots could not be read"))
+                dialog.connect("response",
+                            self.__on_errordialog_response)
+                for error in self.snapscanner.errors:
+                    details = details + error
+                dialog.format_secondary_text(details)
+                dialog.show()
+            self.__on_filterentry_changed(None)
+            return False
+
+    def __monitor_deletion(self):
+        if self.snapdeleter.isAlive() == True:
+            self.progressbar.set_fraction(self.snapdeleter.progress)
+            return True
+        else:
+            self.progressdialog.hide()
+            self.progressbar.set_fraction(1.0)
+            self.progressdialog.hide()
+            if self.snapdeleter.errors:
+                details = ""
+                dialog = gtk.MessageDialog(None,
+                            0,
+                            gtk.MESSAGE_ERROR,
+                            gtk.BUTTONS_CLOSE,
+                            _("Some snapshots could not be deleted"))
+                dialog.connect("response",
+                            self.__on_errordialog_response)
+                for error in self.snapdeleter.errors:
+                    details = details + error
+                dialog.format_secondary_text(details)
+                dialog.show()
+            # If we didn't shortcircut straight to the delete confirmation
+            # dialog then the main dialog is visible so we rebuild the list
+            # view.
+            if len(self.shortcircuit) ==  0:
+                self.__refresh_view()
+            else:
+                gtk.main_quit()
+            return False
+
+    def __refresh_view(self):
+        self.liststorefs.clear()
+        glib.idle_add(self.__init_scan)
+        self.backuptodelete = []
+
+    def __add_selection(self, treemodel, path, iter):
+        snapshot = treemodel.get(iter, 6)[0]
+        self.backuptodelete.append(snapshot)
+
+    def __on_confirmcancel_clicked(self, widget):
+        widget.get_toplevel().hide()
+        widget.get_toplevel().response(1)
+
+    def __on_confirmdelete_clicked(self, widget):
+        widget.get_toplevel().hide()
+        widget.get_toplevel().response(2)
+
+    def __on_errordialog_response(self, widget, responseid):
+        widget.hide()
+
+class ScanSnapshots(threading.Thread):
+
+    def __init__(self):
+        threading.Thread.__init__(self)
+        self.errors = []
+        self.datasets = zfs.Datasets()
+        self.snapshots = []
+        self.rsynced_fs = []
+        self.rsynced_backups = []
+
+    def run(self):
+        self.mounts = self.__get_fs_mountpoints()
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        self.__get_rsync_backups ()
+        self.rescan()
+
+    def __get_rsync_backups (self):
+        # get rsync backup dir
+        self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsyncDir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+        if not os.path.exists(self.rsyncDir):
+            return
+
+        rootBackupDirs = []
+
+        for root, dirs, files in os.walk(self.rsyncDir):
+            if '.time-slider' in dirs:
+                dirs.remove('.time-slider')
+                backupDir = os.path.join(root, rsyncsmf.RSYNCDIRSUFFIX)
+                if os.path.exists(backupDir):
+                    insort(rootBackupDirs, os.path.abspath(backupDir))
+
+        for dirName in rootBackupDirs:
+            os.chdir(dirName)
+            for d in os.listdir(dirName):
+                if os.path.isdir(d) and not os.path.islink(d):
+                    s1 = dirName.split ("%s/" % self.rsyncDir, 1)
+                    s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+                    fs = s2[0]
+
+                    rb = RsyncBackup ("%s/%s" %(dirName, d),
+                                      self.rsyncDir,
+                                      fs,
+                                      d,
+                                      os.stat(d).st_mtime)
+                    self.rsynced_backups.append (rb)
+
+    def __get_fs_mountpoints(self):
+        """Returns a dictionary mapping:
+           {filesystem : mountpoint}"""
+        result = {}
+        for filesys,mountpoint in self.datasets.list_filesystems():
+            result[filesys] = mountpoint
+        return result
+
+    def rescan(self):
+        cloned = self.datasets.list_cloned_snapshots()
+        self.snapshots = []
+        snaplist = self.datasets.list_snapshots()
+        for snapname,snaptime in snaplist:
+            # Filter out snapshots that are the root
+            # of cloned filesystems or volumes
+            try:
+                cloned.index(snapname)
+            except ValueError:
+                snapshot = zfs.Snapshot(snapname, snaptime)
+                self.snapshots.append(snapshot)
+
+class DeleteSnapshots(threading.Thread):
+
+    def __init__(self, snapshots):
+        threading.Thread.__init__(self)
+        self.backuptodelete = snapshots
+        self.started = False
+        self.completed = False
+        self.progress = 0.0
+        self.errors = []
+
+    def run(self):
+        deleted = 0
+        self.started = True
+        total = len(self.backuptodelete)
+        for backup in self.backuptodelete:
+            # The backup could have expired and been automatically
+            # destroyed since the user selected it. Check that it
+            # still exists before attempting to delete it. If it
+            # doesn't exist just silently ignore it.
+            if backup.exists():
+                try:
+                    backup.destroy ()
+                except RuntimeError, inst:
+                    self.errors.append(str(inst))
+            deleted += 1
+            self.progress = deleted / (total * 1.0)
+        self.completed = True
+
+def main(argv):
+    try:
+        opts,args = getopt.getopt(sys.argv[1:], "", [])
+    except getopt.GetoptError:
+        sys.exit(2)
+    rbacp = RBACprofile()
+    if os.geteuid() == 0:
+        if len(args) > 0:
+            manager = DeleteSnapManager(args)
+        else:
+            manager = DeleteSnapManager()
+        gtk.gdk.threads_enter()
+        glib.idle_add(manager.initialise_view)
+        gtk.main()
+        gtk.gdk.threads_leave()
+    elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
+        # Run via gksu, which will prompt for the root password
+        newargs = ["gksu", argv]
+        for arg in args:
+            newargs.append(arg)
+        os.execv("/usr/bin/gksu", newargs);
+        # Shouldn't reach this point
+        sys.exit(1)
+    else:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Insufficient Priviliges"))
+        dialog.format_secondary_text(_("Snapshot deletion requires "
+                                       "administrative privileges to run. "
+                                       "You have not been assigned the necessary"
+                                       "administrative priviliges."
+                                       "\n\nConsult your system administrator "))
+        dialog.run()
+        print argv + "is not a valid executable path"
+        sys.exit(1)
diff --git a/usr/share/time-slider/lib/time_slider/fileversion.py b/usr/share/time-slider/lib/time_slider/fileversion.py
new file mode 100755 (executable)
index 0000000..86a2584
--- /dev/null
@@ -0,0 +1,328 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import time
+import getopt
+import os
+import gio
+import sys
+import threading
+import subprocess
+import string
+import gnomevfs
+import gnome.ui
+#import traceback
+
+try:
+       import pygtk
+       pygtk.require("2.4")
+except:
+       pass
+try:
+       import gtk
+       import gtk.glade
+       gtk.gdk.threads_init()
+except:
+       sys.exit(1)
+try:
+       import gobject
+except:
+       sys.exit(1)
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+       os.path.pardir,
+       os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+KILOBYTES = 1024.0
+MEGABYTES = KILOBYTES*1024
+GIGABYTES = MEGABYTES*1024
+TERABYTES = GIGABYTES*1024
+
+class File:
+       displayTemplates = [
+               (TERABYTES, '%0.1f TB'), 
+               (GIGABYTES, '%0.1f GB'),
+               (MEGABYTES, '%0.1f MB'),
+               (KILOBYTES, '%0.1f KB'),
+               (0, '%0.1f B'),]
+
+       def __init__(self, path):
+               self.path = path
+               self.file = gio.File (path)
+               try:
+                       self.info = self.file.query_info ("*")
+                       self.exist = True
+               except gio.Error:
+                       self.exist = False
+
+       def  get_icon (self):
+               #try thumnailer first
+               icon_factory = gnome.ui.ThumbnailFactory(gnome.ui.THUMBNAIL_SIZE_NORMAL)
+               mtime = os.path.getmtime(self.path)
+               uri = gnomevfs.make_uri_from_input(self.path)
+               thumb =  icon_factory.lookup (uri, mtime)
+               if thumb:
+                 return gtk.gdk.pixbuf_new_from_file (thumb)
+               thumb = icon_factory.generate_thumbnail (uri, self.info.get_content_type())
+               if thumb:
+                 icon_factory.save_thumbnail (thumb, uri, mtime)
+                 return thumb
+                #fallback get the themed icon
+               return gtk.icon_theme_get_default().choose_icon (self.info.get_icon().get_property ("names"), 48,  gtk.ICON_LOOKUP_USE_BUILTIN).load_icon ()
+
+       def  get_size (self):
+               amount = self.info.get_size ()
+               for treshold, template in self.displayTemplates:
+                       if amount > treshold:
+                               if treshold:
+                                       amount = amount /treshold
+                               return "%s (%d bytes)" % (template % amount, self.info.get_size ())
+               return "%d byte" % amount
+
+       def add_if_unique (self, versions):
+               found = False
+               for file in versions:
+                       if int (file.info.get_modification_time ()) == int (self.info.get_modification_time ()):
+                               found = True
+               if not found:
+                       versions.append (self)
+                       return True
+               return False
+
+       def get_mime_type (self):
+               return gnomevfs.get_mime_type(gnomevfs.make_uri_from_input(self.path))
+
+
+( COLUMN_ICON,
+  COLUMN_NAME,
+  COLUMN_STRING_DATE,
+  COLUMN_DATE,
+  COLUMN_SIZE
+) = range (5)
+
+
+
+class FileVersionWindow:
+       meld_hint_displayed = False
+
+       def __init__(self, snap_path, file):
+               self.snap_path = snap_path
+               self.filename = file
+               self.xml = gtk.glade.XML("%s/../../glade/time-slider-version.glade" \
+                       % (os.path.dirname(__file__)))
+               self.window = self.xml.get_widget("toplevel")
+               self.progress = self.xml.get_widget("progress")
+               self.version_label = self.xml.get_widget("num_versions_label")
+               # signal dictionary
+               dic = {"on_toplevel_delete_event": self.exit3 ,
+                       "on_close_clicked": self.exit ,
+                       "on_compare_button_clicked": self.on_compare_button_clicked,
+                       "on_current_file_button_clicked": self.on_current_file_button_clicked,
+                       "on_treeview_row_activated": self.on_treeview_row_activated,
+                       "on_treeview_cursor_changed": self.on_treeview_cursor_changed}
+               self.xml.signal_autoconnect(dic)
+                       
+               self.filename_label = self.xml.get_widget("filename_label")
+               self.size_label = self.xml.get_widget("size_label")
+               self.date_label = self.xml.get_widget("date_label")
+               self.older_versions_label = self.xml.get_widget("older_versions_label")
+               self.compare_button = self.xml.get_widget("compare_button")
+               self.button_init = False
+
+               self.window.show ()
+
+               self.file = File (file)
+               self.filename_label.set_text (self.file.info.get_name ())
+               self.size_label.set_text (self.file.get_size ())
+               self.date_label.set_text (time.strftime ("%d/%m/%y %Hh%Ms%S", time.localtime(self.file.info.get_modification_time ())))
+               self.xml.get_widget("icon_image").set_from_pixbuf (self.file.get_icon ())
+
+               self.treeview = self.xml.get_widget("treeview")
+               self.model = gtk.ListStore(gtk.gdk.Pixbuf,
+                                          gobject.TYPE_STRING,
+                                          gobject.TYPE_STRING,
+                                          gobject.TYPE_STRING,
+                                          gobject.TYPE_STRING)
+
+               self.treeview.set_model (self.model)
+               self.__add_columns (self.treeview)
+
+               self.scanner = VersionScanner (self)
+               self.scanner.start()
+
+       def __add_columns(self, treeview):
+               model = treeview.get_model()
+
+               renderer = gtk.CellRendererPixbuf()
+               column = gtk.TreeViewColumn('Icon', renderer, pixbuf=COLUMN_ICON)
+               treeview.append_column(column)
+
+               self.date_column = gtk.TreeViewColumn('Last Modified Date', gtk.CellRendererText(),
+                       text=COLUMN_STRING_DATE)
+               self.date_column.set_sort_column_id(COLUMN_DATE)
+               treeview.append_column(self.date_column)
+
+               # column for description
+               column = gtk.TreeViewColumn('Size', gtk.CellRendererText(),
+                       text=COLUMN_SIZE)
+               column.set_sort_column_id(COLUMN_SIZE)
+               treeview.append_column(column)
+
+       def add_file (self, file):
+               iter = self.model.append ()
+               self.model.set (iter, 
+               COLUMN_ICON, file.get_icon (),
+               COLUMN_NAME, file.path,
+               COLUMN_STRING_DATE, time.strftime ("%d/%m/%y %Hh%Ms%S", time.localtime(file.info.get_modification_time ())),
+               COLUMN_DATE, file.info.get_modification_time (),
+               COLUMN_SIZE, file.get_size ())
+
+       def exit3 (self, blah, blih):
+               self.exit (self)
+
+       def exit (self, blah):
+               self.scanner.join ()
+               gtk.main_quit ()
+               
+       def on_current_file_button_clicked (self, widget):
+               application = gnomevfs.mime_get_default_application (gnomevfs.get_mime_type(gnomevfs.make_uri_from_input(self.filename)))
+               if application:
+                       subprocess.Popen (str.split (application[2]) + [self.filename])
+
+       def on_treeview_row_activated (self, treeview, path, column):
+               (model, iter) = treeview.get_selection ().get_selected ()
+               filename = model.get (iter, 1)[0]
+               application = gnomevfs.mime_get_default_application (gnomevfs.get_mime_type(gnomevfs.make_uri_from_input(filename)))
+               if application:
+                       subprocess.Popen (str.split (application[2]) + [filename])
+
+       def on_treeview_cursor_changed (self, treeview):
+               if not self.button_init:
+                       self.button_init = True
+                       if self.file.get_mime_type ().find ("text") != -1 :
+                               self.compare_button.set_sensitive (True)
+
+       def on_compare_button_clicked (self, widget):
+               (model, iter) = self.treeview.get_selection ().get_selected ()
+               filename = model.get (iter, 1)[0]
+               if os.path.exists ("/usr/bin/meld"):
+                 subprocess.Popen (["/usr/bin/meld",self.filename, filename])
+               else:
+                 if not self.meld_hint_displayed:
+                   dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, _("Hint"))
+                   dialog.set_title (_("Hint"))
+                   dialog.format_secondary_text(_("Installing the optional meld package will enhance the file comparison visualization"))
+                   dialog.run ()
+                   dialog.destroy ()
+                   self.meld_hint_displayed = True
+                 p1 = subprocess.Popen(["/usr/bin/diff", "-u", self.filename, filename], stdout=subprocess.PIPE)
+                 p2 = subprocess.Popen(str.split ("/usr/bin/zenity --text-info --editable"), stdin=p1.stdout, stdout=subprocess.PIPE)
+
+
+class VersionScanner(threading.Thread):
+
+       def __init__(self, window):
+               self.w = window
+               self._stopevent = threading.Event()
+               threading.Thread.__init__(self)
+
+       def run(self):
+               l = self.w.snap_path.split (".zfs")
+               path_before_snap = l[0]
+               l = self.w.filename.split (path_before_snap)
+               path_after_snap = l[1]
+               snap_path = "%s.zfs/snapshot/" % path_before_snap;
+               dirs = os.listdir(snap_path)
+
+               num_dirs = len(dirs)
+               current_dir = 1
+
+               gobject.idle_add (self.w.progress.set_pulse_step,  (1.0 / num_dirs))
+               gobject.idle_add (self.w.progress.set_text,  ("Scanning for older versions (%d/%d)" % (current_dir, num_dirs)))
+
+               versions = [File (self.w.filename)]
+
+               for dir in dirs:
+                       if not self._stopevent.isSet ():
+                               file = File ("%s%s/%s" % (snap_path, dir, path_after_snap))
+                               if file.exist :
+                                       if file.add_if_unique(versions):
+                                               gobject.idle_add (self.w.add_file, file)
+                               fraction = self.w.progress.get_fraction ()
+                               fraction += self.w.progress.get_pulse_step ()
+                               if fraction > 1:
+                                       fraction = 1
+
+                               gobject.idle_add (self.w.progress.set_fraction, fraction)
+                               current_dir += 1
+                               gobject.idle_add (self.w.progress.set_text, "Scanning for older versions (%d/%d)" % (current_dir, num_dirs))
+                       else:
+                               return None
+
+               gobject.idle_add(self.w.progress.hide)
+               gobject.idle_add(self.w.older_versions_label.set_markup , "<b>Older Versions</b> (%d) " % (len(versions) - 1))
+               # sort by date
+               gobject.idle_add(self.w.date_column.emit, "clicked")
+               gobject.idle_add(self.w.date_column.emit, "clicked")
+       
+       def join(self, timeout=None):
+               self._stopevent.set ()
+               threading.Thread.join(self, timeout)
+
+def main(argv):
+       try:
+               opts, args = getopt.getopt(sys.argv[1:], "", [])
+       except getopt.GetoptError:
+               sys.exit(2)
+       if len(args) != 2:
+               dialog = gtk.MessageDialog(None,
+                       0,
+                       gtk.MESSAGE_ERROR,
+                       gtk.BUTTONS_CLOSE,
+                       _("Invalid arguments count."))
+               dialog.set_title ("Error")
+               dialog.format_secondary_text(_("Version explorer requires"
+                       " 2 arguments :\n- The path of the "
+                       "root snapshot directory.\n"
+                       "- The filename to explore."))
+               dialog.run()
+               sys.exit (2)
+
+       window = FileVersionWindow(args[0], args[1])
+       gtk.gdk.threads_enter()
+       gtk.main()
+       gtk.gdk.threads_leave()
diff --git a/usr/share/time-slider/lib/time_slider/rbac.py b/usr/share/time-slider/lib/time_slider/rbac.py
new file mode 100755 (executable)
index 0000000..1995205
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import pwd
+
+import util
+
+class RBACprofile:
+
+    def __init__(self, name = None):
+        # Filtering through the pwd module is beneficial because
+        # it will raise a KeyError exception for an invalid
+        # name argument 
+        if name == None:
+            euid = os.geteuid()
+            pwnam = pwd.getpwuid(euid)
+            self.uid = euid
+            self.name = pwnam[0]
+        else:
+            pwnam = pwd.getpwnam(name)
+            self.name = pwnam[0]
+            self.uid = pwnam[2]
+
+        self.profiles = self.get_profiles()
+        self.auths = self.get_auths()
+
+    def get_profiles(self):
+        cmd = ["/usr/bin/profiles", self.name]
+        profiles = []
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.split('\n'):
+            if line.isspace():
+                continue
+            else:
+                try:
+                    line.index(self.name + " :")
+                except ValueError:
+                    profiles.append(line.strip())
+        # Remove "All" because it's (seemingly) meaningless
+        try:
+            profiles.remove("All")
+        except ValueError:
+            return profiles
+        return profiles
+
+    def get_auths(self):
+        cmd = ["/usr/bin/auths", self.name]
+        auths = []
+        outdata,errdata  = util.run_command(cmd)
+        auths = outdata.rstrip().split(",")
+        return auths
+
+    def has_profile(self, profile):
+        # root is all powerful
+        if self.uid == 0:
+            return True
+        try:
+            self.profiles.index(profile)
+        except ValueError:
+            return False
+        return True
+
+    def has_auth(self, auth):
+        """ Checks the user's authorisations to see if "auth" is
+            assigned to the user. Recursively searches higher up
+            for glob matching eg. solaris.network.hosts.read ->
+            solaris.network.hosts.* -> solaris.network.* ->
+            solaris.*, until a valid authorisation is found.
+            Returns True if user has the "auth" authorisation,
+            False otherwise"""
+        try:
+            self.auths.index(auth)
+            return True
+        except ValueError:
+            subpattern = auth.rsplit(".", 1)
+            # If there are still more "."s in the string
+            if subpattern[0] != auth:
+                # Try using the glob pattern if auth is not
+                # already a glob pattern eg. solaris.device.*
+                if subpattern[1] != "*":
+                    try:
+                        self.auths.index("%s.*" % subpattern[0])
+                        return True
+                    except ValueError:
+                        pass
+                # Strip another "." off the auth and carry on searching 
+                subsearch = subpattern[0].rsplit(".", 1)
+                if subsearch[0] != subpattern[0]:
+                    return self.has_auth("%s.*" % subsearch[0])
+            return False
+
+if __name__ == "__main__":
+  rbac = RBACprofile()
+  print rbac.name
+  print rbac.uid
+  print rbac.profiles
+  print rbac.auths
+
diff --git a/usr/share/time-slider/lib/time_slider/setupgui.py b/usr/share/time-slider/lib/time_slider/setupgui.py
new file mode 100755 (executable)
index 0000000..b3a37b6
--- /dev/null
@@ -0,0 +1,1322 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import subprocess
+import threading
+import util
+import smf
+from autosnapsmf import enable_default_schedules, disable_default_schedules
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import rsyncsmf
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+
+import glib
+import gobject
+import gio
+import dbus
+import dbus.service
+import dbus.mainloop
+import dbus.mainloop.glib
+import dbussvc
+
+
+# This is the rough guess ratio used for rsync backup device size
+# vs. the total size of the pools it's expected to backup.
+RSYNCTARGETRATIO = 2
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from timeslidersmf import TimeSliderSMF
+from rbac import RBACprofile
+
+
+class FilesystemIntention:
+
+    def __init__(self, name, selected, inherited):
+        self.name = name
+        self.selected = selected
+        self.inherited = inherited
+
+    def __str__(self):
+        return_string = "Filesystem name: " + self.name + \
+                "\n\tSelected: " + str(self.selected) + \
+                "\n\tInherited: " + str(self.inherited)
+        return return_string
+
+    def __eq__(self, other):
+        if self.name != other.name:
+            return False
+        if self.inherited and other.inherited:
+            return True
+        elif not self.inherited and other.inherited:
+            return False
+        if (self.selected == other.selected) and \
+           (self.inherited == other.inherited):
+            return True
+        else:
+            return False
+
+class SetupManager:
+
+    def __init__(self, execpath):
+        self._execPath = execpath
+        self._datasets = zfs.Datasets()
+        self._xml = gtk.glade.XML("%s/../../glade/time-slider-setup.glade" \
+                                  % (os.path.dirname(__file__)))
+
+        # Tell dbus to use the gobject mainloop for async ops
+        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+        dbus.mainloop.glib.threads_init()
+
+        # Register a bus name with the system dbus daemon
+        systemBus = dbus.SystemBus()
+        busName = dbus.service.BusName("org.opensolaris.TimeSlider.config",
+                                       systemBus)
+        self._dbus = dbussvc.Config(systemBus,
+                                    '/org/opensolaris/TimeSlider/config')
+        # Used later to trigger a D-Bus notification of select configuration 
+        # changes made
+        self._configNotify = False
+
+        # These variables record the initial UI state which are used
+        # later to compare against the UI state when the OK or Cancel
+        # button is clicked and apply the minimum set of necessary 
+        # configuration changes. Prevents minor changes taking ages
+        # to be applied by the GUI.
+        self._initialEnabledState = None
+        self._initialRsyncState = None
+        self._initialRsyncTargetDir = None
+        self._initialCleanupLevel = None
+        self._initialCustomSelection = False
+        self._initialSnapStateDic = {}
+        self._initialRsyncStateDic = {}
+        self._initialFsIntentDic = {}
+        self._initialRsyncIntentDic = {}
+
+        # Currently selected rsync backup device via the GUI.
+        self._newRsyncTargetDir = None
+        # Used to store GUI filesystem selection state and the
+        # set of intended properties to apply to zfs filesystems.
+        self._snapStateDic = {}
+        self._rsyncStateDic = {}
+        self._fsIntentDic = {}
+        self._rsyncIntentDic = {}
+        # Dictionary that maps device ID numbers to zfs filesystem objects
+        self._fsDevices = {}
+
+        topLevel = self._xml.get_widget("toplevel")
+        self._pulseDialog = self._xml.get_widget("pulsedialog")
+        self._pulseDialog.set_transient_for(topLevel)
+        
+        # gio.VolumeMonitor reference
+        self._vm = gio.volume_monitor_get()
+        self._vm.connect("mount-added", self._mount_added)
+        self._vm.connect("mount-removed" , self._mount_removed)
+
+        self._fsListStore = gtk.ListStore(bool,
+                                         bool,
+                                         str,
+                                         str,
+                                         gobject.TYPE_PYOBJECT)
+        filesystems = self._datasets.list_filesystems()
+        for fsname,fsmountpoint in filesystems:
+            if (fsmountpoint == "legacy"):
+                mountpoint = _("Legacy")
+            else:
+                mountpoint = fsmountpoint
+            fs = zfs.Filesystem(fsname, fsmountpoint)
+            # Note that we don't deal with legacy mountpoints.
+            if fsmountpoint != "legacy" and fs.is_mounted():
+                self._fsDevices[os.stat(fsmountpoint).st_dev] = fs
+            snap = fs.get_auto_snap()
+            rsyncstr = fs.get_user_property(rsyncsmf.RSYNCFSTAG)
+            if rsyncstr == "true":
+                rsync = True
+            else:
+                rsync = False
+            # Rsync is only performed on snapshotted filesystems.
+            # So treat as False if rsync is set to true independently
+            self._fsListStore.append([snap, snap & rsync,
+                                     mountpoint, fs.name, fs])
+            self._initialSnapStateDic[fs.name] = snap
+            self._initialRsyncStateDic[fs.name] = snap & rsync
+        del filesystems
+
+        for fsname in self._initialSnapStateDic:
+                self._refine_filesys_actions(fsname,
+                                              self._initialSnapStateDic,
+                                              self._initialFsIntentDic)
+                self._refine_filesys_actions(fsname,
+                                              self._initialRsyncStateDic,
+                                              self._initialRsyncIntentDic)
+   
+        self._fsTreeView = self._xml.get_widget("fstreeview")
+        self._fsTreeView.set_sensitive(False)
+        self._fsTreeView.set_size_request(10, 200)
+
+        self._fsTreeView.set_model(self._fsListStore)
+
+        cell0 = gtk.CellRendererToggle()
+        cell1 = gtk.CellRendererToggle()
+        cell2 = gtk.CellRendererText()
+        cell3 = gtk.CellRendererText()
+        radioColumn = gtk.TreeViewColumn(_("Select"),
+                                             cell0, active=0)
+        self._fsTreeView.insert_column(radioColumn, 0)
+
+        self._rsyncRadioColumn = gtk.TreeViewColumn(_("Replicate"),
+                                                    cell1, active=1)
+        nameColumn = gtk.TreeViewColumn(_("Mount Point"),
+                                        cell2, text=2)
+        self._fsTreeView.insert_column(nameColumn, 2)
+        mountPointColumn = gtk.TreeViewColumn(_("File System Name"),
+                                              cell3, text=3)
+        self._fsTreeView.insert_column(mountPointColumn, 3)
+        cell0.connect('toggled', self._row_toggled)
+        cell1.connect('toggled', self._rsync_cell_toggled)
+        advancedBox = self._xml.get_widget("advancedbox")
+        advancedBox.connect('unmap', self._advancedbox_unmap)  
+
+        self._rsyncSMF = rsyncsmf.RsyncSMF("%s:rsync" \
+                                          %(plugin.PLUGINBASEFMRI))
+        state = self._rsyncSMF.get_service_state()
+        self._initialRsyncTargetDir = self._rsyncSMF.get_target_dir()
+        # Check for the default, unset value of "" from SMF.
+        if self._initialRsyncTargetDir == '""':
+            self._initialRsyncTargetDir = ''
+        self._newRsyncTargetDir = self._initialRsyncTargetDir
+        self._smfTargetKey = self._rsyncSMF.get_target_key()
+        self._newRsyncTargetSelected = False
+        sys,self._nodeName,rel,ver,arch = os.uname()
+
+        # Model columns:
+        # 0 Themed icon list (python list)
+        # 1 device root
+        # 2 volume name
+        # 3 Is gio.Mount device
+        # 4 Is separator (for comboBox separator rendering)
+        self._rsyncStore = gtk.ListStore(gobject.TYPE_PYOBJECT,
+                                         gobject.TYPE_STRING,
+                                         gobject.TYPE_STRING,
+                                         gobject.TYPE_BOOLEAN,
+                                         gobject.TYPE_BOOLEAN)
+        self._rsyncCombo = self._xml.get_widget("rsyncdevcombo")
+        mounts = self._vm.get_mounts()
+        for mount in mounts:
+            self._mount_added(self._vm, mount)
+        if len(mounts) > 0:
+            # Add a separator
+            self._rsyncStore.append((None, None, None, None, True))
+        del mounts
+
+        if len(self._newRsyncTargetDir) == 0:
+            self._rsyncStore.append((['folder'],
+                                    _("(None)"),
+                                    '',
+                                    False,
+                                    False))
+            # Add a separator
+            self._rsyncStore.append((None, None, None, None, True))
+        self._rsyncStore.append((None, _("Other..."), "Other", False, False))
+        self._iconCell = gtk.CellRendererPixbuf()
+        self._nameCell = gtk.CellRendererText()
+        self._rsyncCombo.clear()
+        self._rsyncCombo.pack_start(self._iconCell, False)
+        self._rsyncCombo.set_cell_data_func(self._iconCell,
+                                            self._icon_cell_render)
+        self._rsyncCombo.pack_end(self._nameCell)
+        self._rsyncCombo.set_attributes(self._nameCell, text=1)
+        self._rsyncCombo.set_row_separator_func(self._row_separator)
+        self._rsyncCombo.set_model(self._rsyncStore)
+        self._rsyncCombo.connect("changed", self._rsync_combo_changed)
+        # Force selection of currently configured device
+        self._rsync_dev_selected(self._newRsyncTargetDir)
+
+        # signal dictionary    
+        dic = {"on_ok_clicked" : self._on_ok_clicked,
+               "on_cancel_clicked" : gtk.main_quit,
+               "on_snapshotmanager_delete_event" : gtk.main_quit,
+               "on_enablebutton_toggled" : self._on_enablebutton_toggled,
+               "on_rsyncbutton_toggled" : self._on_rsyncbutton_toggled,
+               "on_defaultfsradio_toggled" : self._on_defaultfsradio_toggled,
+               "on_selectfsradio_toggled" : self._on_selectfsradio_toggled,
+               "on_deletesnapshots_clicked" : self._on_deletesnapshots_clicked}
+        self._xml.signal_autoconnect(dic)
+
+        if state != "disabled":
+            self._rsyncEnabled = True
+            self._xml.get_widget("rsyncbutton").set_active(True)
+            self._initialRsyncState = True
+        else:
+            self._rsyncEnabled = False
+            self._rsyncCombo.set_sensitive(False)
+            self._initialRsyncState = False
+
+        # Initialise SMF service instance state.
+        try:
+            self._sliderSMF = TimeSliderSMF()
+        except RuntimeError,message:
+            self._xml.get_widget("toplevel").set_sensitive(False)
+            dialog = gtk.MessageDialog(self._xml.get_widget("toplevel"),
+                                       0,
+                                       gtk.MESSAGE_ERROR,
+                                       gtk.BUTTONS_CLOSE,
+                                       _("Snapshot manager service error"))
+            dialog.format_secondary_text(_("The snapshot manager service does "
+                                         "not appear to be installed on this "
+                                         "system."
+                                         "\n\nSee the svcs(1) man page for more "
+                                         "information."
+                                         "\n\nDetails:\n%s")%(message))
+            dialog.set_icon_name("time-slider-setup")
+            dialog.run()
+            sys.exit(1)
+
+        if self._sliderSMF.svcstate == "disabled":
+            self._xml.get_widget("enablebutton").set_active(False)
+            self._initialEnabledState = False
+        elif self._sliderSMF.svcstate == "offline":
+            self._xml.get_widget("toplevel").set_sensitive(False)
+            errors = ''.join("%s\n" % (error) for error in \
+                self._sliderSMF.find_dependency_errors())
+            dialog = gtk.MessageDialog(self._xml.get_widget("toplevel"),
+                                        0,
+                                        gtk.MESSAGE_ERROR,
+                                        gtk.BUTTONS_CLOSE,
+                                        _("Snapshot manager service dependency error"))
+            dialog.format_secondary_text(_("The snapshot manager service has "
+                                            "been placed offline due to a dependency "
+                                            "problem. The following dependency problems "
+                                            "were found:\n\n%s\n\nRun \"svcs -xv\" from "
+                                            "a command prompt for more information about "
+                                            "these dependency problems.") % errors)
+            dialog.set_icon_name("time-slider-setup")
+            dialog.run()
+            sys.exit(1)
+        elif self._sliderSMF.svcstate == "maintenance":
+            self._xml.get_widget("toplevel").set_sensitive(False)
+            dialog = gtk.MessageDialog(self._xml.get_widget("toplevel"),
+                                        0,
+                                        gtk.MESSAGE_ERROR,
+                                        gtk.BUTTONS_CLOSE,
+                                        _("Snapshot manager service error"))
+            dialog.format_secondary_text(_("The snapshot manager service has "
+                                            "encountered a problem and has been "
+                                            "disabled until the problem is fixed."
+                                            "\n\nSee the svcs(1) man page for more "
+                                            "information."))
+            dialog.set_icon_name("time-slider-setup")
+            dialog.run()
+            sys.exit(1)
+        else:
+            # FIXME: Check transitional states 
+            self._xml.get_widget("enablebutton").set_active(True)
+            self._initialEnabledState = True
+
+
+        # Emit a toggled signal so that the initial GUI state is consistent
+        self._xml.get_widget("enablebutton").emit("toggled")
+        # Check the snapshotting policy (UserData (default), or Custom)
+        self._initialCustomSelection = self._sliderSMF.is_custom_selection()
+        if self._initialCustomSelection == True:
+            self._xml.get_widget("selectfsradio").set_active(True)
+            # Show the advanced controls so the user can see the
+            # customised configuration.
+            if self._sliderSMF.svcstate != "disabled":
+                self._xml.get_widget("expander").set_expanded(True)
+        else: # "false" or any other non "true" value
+            self._xml.get_widget("defaultfsradio").set_active(True)
+
+        # Set the cleanup threshhold value
+        spinButton = self._xml.get_widget("capspinbutton")
+        critLevel = self._sliderSMF.get_cleanup_level("critical")
+        warnLevel = self._sliderSMF.get_cleanup_level("warning")
+
+        # Force the warning level to something practical
+        # on the lower end, and make it no greater than the
+        # critical level specified in the SVC instance.
+        spinButton.set_range(70, critLevel)
+        self._initialCleanupLevel = warnLevel
+        if warnLevel > 70:
+            spinButton.set_value(warnLevel)
+        else:
+            spinButton.set_value(70)
+
+    def _icon_cell_render(self, celllayout, cell, model, iter):
+        iconList = self._rsyncStore.get_value(iter, 0)
+        if iconList != None:
+            gicon = gio.ThemedIcon(iconList)
+            cell.set_property("gicon", gicon)
+        else:
+            root = self._rsyncStore.get_value(iter, 2)
+            if root == "Other":
+                cell.set_property("gicon", None)
+
+    def _row_separator(self, model, iter):
+        return model.get_value(iter, 4)
+
+    def _mount_added(self, volume_monitor, mount):
+        icon = mount.get_icon()
+        iconList = icon.get_names()
+        if iconList == None:
+            iconList = ['drive-harddisk', 'drive']
+        root = mount.get_root()
+        path = root.get_path()
+        mountName = mount.get_name()
+        volume = mount.get_volume()
+        if volume == None:
+            volName = mount.get_name()
+            if volName == None:
+                volName = os.path.split(path)[1]
+        else:
+            volName = volume.get_name()
+
+        # Check to see if there is at least one gio.Mount device already
+        # in the ListStore. If not, then we also need to add a separator
+        # row.
+        iter = self._rsyncStore.get_iter_first()
+        if iter and self._rsyncStore.get_value(iter, 3) == False:
+            self._rsyncStore.insert(0, (None, None, None, None, True))
+        
+        self._rsyncStore.insert(0, (iconList, volName, path, True, False))
+        # If this happens to be the already configured backup device
+        # and the user hasn't tried to change device yet, auto select
+        # it.
+        if self._initialRsyncTargetDir == self._newRsyncTargetDir:
+            if self._validate_rsync_target(path) == True:
+                self._rsyncCombo.set_active(0)
+
+    def _mount_removed(self, volume_monitor, mount):
+        root = mount.get_root()
+        path = root.get_path()
+        iter = self._rsyncStore.get_iter_first()
+        mountIter = None
+        numMounts = 0
+        # Search gio.Mount devices
+        while iter != None and \
+            self._rsyncStore.get_value(iter, 3) == True:
+            numMounts += 1
+            compPath = self._rsyncStore.get_value(iter, 2)
+            if compPath == path:
+                mountIter = iter
+                break
+            else:
+                iter = self._rsyncStore.iter_next(iter)
+        if mountIter != None:
+            if numMounts == 1:
+                # Need to remove the separator also since
+                # there will be no more gio.Mount devices
+                # shown in the combo box
+                sepIter = self._rsyncStore.iter_next(mountIter)
+                if self._rsyncStore.get_value(sepIter, 4) == True:
+                    self._rsyncStore.remove(sepIter)                  
+            self._rsyncStore.remove(mountIter)
+            iter = self._rsyncStore.get_iter_first()
+            # Insert a custom folder if none exists already
+            if self._rsyncStore.get_value(iter, 2) == "Other":
+                path = self._initialRsyncTargetDir
+                length = len(path)
+                if length > 1:
+                    name = os.path.split(path)[1]
+                elif length == 1:
+                    name = path
+                else: # Indicates path is unset: ''
+                    name = _("(None)")
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (None,
+                                                       None,
+                                                       None,
+                                                       None,
+                                                       True))
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (['folder'],
+                                                       name,
+                                                       path,
+                                                       False,
+                                                       False))
+            self._rsyncCombo.set_active_iter(iter)
+
+    def _monitor_setup(self, pulseBar):
+        if self._enabler.isAlive() == True:
+            pulseBar.pulse()
+            return True
+        else:
+            gtk.main_quit()   
+
+    def _row_toggled(self, renderer, path):
+        model = self._fsTreeView.get_model()
+        iter = model.get_iter(path)
+        state = renderer.get_active()
+        if state == False:
+            self._fsListStore.set_value(iter, 0, True)
+        else:
+            self._fsListStore.set_value(iter, 0, False)
+            self._fsListStore.set_value(iter, 1, False)
+
+    def _rsync_cell_toggled(self, renderer, path):
+        model = self._fsTreeView.get_model()
+        iter = model.get_iter(path)
+        state = renderer.get_active()
+        rowstate = self._fsListStore.get_value(iter, 0)
+        if rowstate == True:
+            if state == False:
+                self._fsListStore.set_value(iter, 1, True)
+            else:
+                self._fsListStore.set_value(iter, 1, False)
+
+    def _rsync_config_error(self, msg):
+        topLevel = self._xml.get_widget("toplevel")
+        dialog = gtk.MessageDialog(topLevel,
+                                    0,
+                                    gtk.MESSAGE_ERROR,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Unsuitable Backup Location"))
+        dialog.format_secondary_text(msg)
+        dialog.set_icon_name("time-slider-setup")
+        dialog.run()
+        dialog.hide()
+        return
+
+    def _rsync_dev_selected(self, path):
+        iter = self._rsyncStore.get_iter_first()
+        while iter != None:
+            # Break out when we hit a non gio.Mount device
+            if self._rsyncStore.get_value(iter, 3) == False:
+                break
+            compPath = self._rsyncStore.get_value(iter, 2)
+            if compPath == path:
+                self._rsyncCombo.set_active_iter(iter)
+                self._newRsyncTargetDir = path
+                return
+            else:
+                iter = self._rsyncStore.iter_next(iter)
+
+        # Not one of the shortcut RMM devices, so it's
+        # some other path on the filesystem.
+        # iter may be pointing at a separator. Increment
+        # to next row iter if so.
+        if self._rsyncStore.get_value(iter, 4) == True:
+            iter = self._rsyncStore.iter_next(iter)
+
+        if iter != None:
+            if len(path) > 1:
+                name = os.path.split(path)[1]
+            elif len(path) == 1:
+                name = path
+            else: # Indicates path is unset: ''
+                name = _("(None)")
+            # Could be either the custom folder selection
+            # row or the  "Other" row if the custom row
+            # was not created. If "Other" then create the
+            # custom row and separator now at this position
+            if self._rsyncStore.get_value(iter, 2) == "Other":
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (None,
+                                                       None,
+                                                       None,
+                                                       None,
+                                                       True))
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (['folder'],
+                                                       name,
+                                                       path,
+                                                       False,
+                                                       False))
+            else:
+                self._rsyncStore.set(iter,
+                                     1, name,
+                                     2, path)
+            self._rsyncCombo.set_active_iter(iter)
+            self._newRsyncTargetDir = path
+
+    def _rsync_combo_changed(self, combobox):
+        newIter = combobox.get_active_iter()
+        if newIter != None:
+            root = self._rsyncStore.get_value(newIter, 2)
+            if root != "Other":
+                self._newRsyncTargetDir = root
+            else:
+                msg = _("Select A Back Up Device")
+                fileDialog = \
+                    gtk.FileChooserDialog(
+                        msg,
+                        self._xml.get_widget("toplevel"),
+                        gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
+                        (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,
+                        gtk.STOCK_OK,gtk.RESPONSE_OK),
+                        None)
+                self._rsyncCombo.set_sensitive(False)
+                response = fileDialog.run()
+                fileDialog.hide()
+                if response == gtk.RESPONSE_OK:
+                    gFile = fileDialog.get_file()
+                    self._rsync_dev_selected(gFile.get_path())
+                else:
+                    self._rsync_dev_selected(self._newRsyncTargetDir)
+                self._rsyncCombo.set_sensitive(True)
+
+    def _rsync_size_warning(self, zpools, zpoolSize,
+                             rsyncTarget, targetSize):
+        # Using decimal "GB" instead of binary "GiB"
+        KB = 1000
+        MB = 1000 * KB
+        GB = 1000 * MB
+        TB = 1000 * GB
+
+        suggestedSize = RSYNCTARGETRATIO * zpoolSize
+        if suggestedSize > TB:
+            sizeStr = "%.1f TB" % round(suggestedSize / float(TB), 1)
+        elif suggestedSize > GB:
+            sizeStr = "%.1f GB" % round(suggestedSize / float(GB), 1)
+        else:
+            sizeStr = "%.1f MB" % round(suggestedSize / float(MB), 1)
+
+        if targetSize > TB:
+            targetStr = "%.1f TB" % round(targetSize / float(TB), 1)
+        elif targetSize > GB:
+            targetStr = "%.1f GB" % round(targetSize / float(GB), 1)
+        else:
+            targetStr = "%.1f MB" % round(targetSize / float(MB), 1)
+
+
+        msg = _("Time Slider suggests a device with a capacity of at "
+                "least <b>%s</b>.\n"
+                "The device: \'<b>%s</b>\'\nonly has <b>%s</b>\n"
+                "Do you want to use it anyway?") \
+                % (sizeStr, rsyncTarget, targetStr)
+
+        topLevel = self._xml.get_widget("toplevel")
+        dialog = gtk.MessageDialog(topLevel,
+                                   0,
+                                   gtk.MESSAGE_QUESTION,
+                                   gtk.BUTTONS_YES_NO,
+                                   _("Time Slider"))
+        dialog.set_default_response(gtk.RESPONSE_NO)
+        dialog.set_transient_for(topLevel)
+        dialog.set_markup(msg)
+        dialog.set_icon_name("time-slider-setup")
+
+        response = dialog.run()
+        dialog.hide()
+        if response == gtk.RESPONSE_YES:
+            return True
+        else:
+            return False
+
+    def _check_rsync_config(self):
+        """
+           Checks rsync configuration including, filesystem selection,
+           target directory validation and capacity checks.
+           Returns True if everything is OK, otherwise False.
+           Pops up blocking error dialogs to notify users of error
+           conditions before returning.
+        """
+        def _get_mount_point(path):
+            if os.path.ismount(path):
+                return path
+            else:
+                return _get_mount_point(abspath(join(path, pardir)))
+
+        if self._rsyncEnabled != True:
+            return True
+
+        if len(self._newRsyncTargetDir) == 0:
+            msg = _("No backup device was selected.\n"
+                    "Please select an empty device.")
+            self._rsync_config_error(msg)
+            return False
+        # There's little that can be done if the device is from a
+        # previous configuration and currently offline. So just 
+        # treat it as being OK based on the assumption that it was
+        # previously deemed to be OK.
+        if self._initialRsyncTargetDir == self._newRsyncTargetDir and \
+           not os.path.exists(self._newRsyncTargetDir):
+            return True
+        # Perform the required validation checks on the
+        # target directory.
+        newTargetDir = self._newRsyncTargetDir
+
+        # We require the whole device. So find the enclosing
+        # mount point and inspect from there.
+        targetMountPoint = abspath(_get_mount_point(newTargetDir))
+
+        # Check that it's writable.
+        f = None
+        testFile = os.path.join(targetMountPoint, ".ts-test")
+        try:
+            f = open(testFile, 'w')
+        except (OSError, IOError):
+            msg = _("\'%s\'\n"
+                    "is not writable. The backup device must "
+                    "be writable by the system administrator." 
+                    "\n\nPlease use a different device.") \
+                    % (targetMountPoint)
+            self._rsync_config_error(msg)
+            return False
+        f.close()
+
+        # Try to create a symlink. Rsync requires this to
+        # do incremental backups and to ensure it's posix like
+        # enough to correctly set file ownerships and perms.
+        os.chdir(targetMountPoint)
+        try:
+            os.link(testFile, ".ts-test-link")
+        except OSError:
+            msg = _("\'%s\'\n"
+                    "contains an incompatible file system. " 
+                    "The selected device must have a Unix "
+                    "style file system that supports file "
+                    "linking, such as UFS"
+                    "\n\nPlease use a different device.") \
+                    % (targetMountPoint)
+            self._rsync_config_error(msg)
+            return False
+        finally:
+            os.unlink(testFile)
+        os.unlink(".ts-test-link")
+
+        # Check that selected directory is either empty
+        # or already preconfigured as a backup target
+        sys,nodeName,rel,ver,arch = os.uname()
+        basePath = os.path.join(targetMountPoint,
+                                rsyncsmf.RSYNCDIRPREFIX)
+        nodePath = os.path.join(basePath,
+                                nodeName)
+        configPath = os.path.join(basePath,
+                                    rsyncsmf.RSYNCCONFIGFILE)
+        self._newRsyncTargetSelected = True
+        targetDirKey = None
+
+        contents = os.listdir(targetMountPoint)
+        os.chdir(targetMountPoint)
+
+        # The only other exception to an empty directory is
+        # "lost+found".
+        for item in contents:
+            if (item != rsyncsmf.RSYNCDIRPREFIX and \
+                item != "lost+found") or \
+               not os.path.isdir(item) or \
+               os.path.islink(item):
+                msg = _("\'%s\'\n is not an empty device.\n\n"
+                        "Please select an empty device.") \
+                        % (newTargetDir)
+                self._rsync_config_error(msg)
+                return False
+
+        # Validate existing directory structure
+        if os.path.exists(basePath):
+            # We only accept a pre-existing directory if
+            # 1. It has a config key that matches that stored by
+            #    the rsync plugin's SMF configuration
+            # 2. It has a single subfolder that matches the nodename
+            #    of this system,
+
+            # Check for previous config key
+            if os.path.exists(configPath):
+                f = open(configPath, 'r')
+                for line in f.readlines():
+                    key, val = line.strip().split('=')
+                    if key.strip() == "target_key":
+                        targetDirKey = val.strip()
+                        break
+
+            # Examine anything else in the directory
+            self._targetSelectionError = None
+            dirList = [d for d in os.listdir(basePath) if
+                        d != '.rsync-config']
+            os.chdir(basePath)
+            if len(dirList) > 0:
+                msg = _("\'%s\'\n is not an empty device.\n\n"
+                        "Please select an empty device.") \
+                        % (newTargetDir)
+                # No config key or > 1 directory:
+                # User specified a non empty directory.
+                if targetDirKey == None or len(dirList) > 1:
+                    self._rsync_config_error(msg)
+                    return False
+                # Make sure the single item is not a file or symlink.
+                elif os.path.islink(dirList[0]) or \
+                        os.path.isfile(dirList[0]):
+                    self._rsync_config_error(msg)
+                    return False
+                else:
+                    # Has 1 other item and a config key. Other
+                    # item must be a directory and must match the
+                    # system nodename and SMF's key value respectively
+                    # respectively
+                    if dirList[0] != nodeName and \
+                        targetDirKey != self._smfTargetKey:
+                        msg = _("\'%s\'\n"
+                                "is a Time Slider external backup device "
+                                "that is already in use by another system. "
+                                "Backup devices may not be shared between "
+                                "systems." 
+                                "\n\nPlease use a different device.") \
+                                % (newTargetDir)
+                        self._rsync_config_error(msg)                                
+                        return False
+                    else:
+                        if dirList[0] == nodeName and \
+                           targetDirKey != self._smfTargetKey:
+                            # Looks like a device that we previously used,
+                            # but discontinued using in favour of some other
+                            # device.
+                            msg = _("\'<b>%s</b>\' appears to be a a device "
+                                    "previously configured for use by this "
+                                    "system.\n\nDo you want resume use of "
+                                    "this device for backups?") \
+                                    % (newTargetDir)
+
+                            topLevel = self._xml.get_widget("toplevel")
+                            dialog = gtk.MessageDialog(topLevel,
+                                                       0,
+                                                       gtk.MESSAGE_QUESTION,
+                                                       gtk.BUTTONS_YES_NO,
+                                                       _("Time Slider"))
+                            dialog.set_default_response(gtk.RESPONSE_NO)
+                            dialog.set_transient_for(topLevel)
+                            dialog.set_markup(msg)
+                            dialog.set_icon_name("time-slider-setup")
+
+                            response = dialog.run()
+                            dialog.hide()
+                            if response == gtk.RESPONSE_NO:
+                                return False
+                        else:
+                            # Appears to be our own pre-configured directory.
+                            self._newRsyncTargetSelected = False
+
+        # Compare device ID against selected ZFS filesystems
+        # and their enclosing Zpools. The aim is to avoid
+        # a vicous circle caused by backing up snapshots onto
+        # the same pool the snapshots originate from
+        targetDev = os.stat(newTargetDir).st_dev
+        try:
+            fs = self._fsDevices[targetDev]
+            
+            # See if the filesystem itself is selected
+            # and/or any other fileystem on the pool is 
+            # selected.
+            fsEnabled = self._snapStateDic[fs.name]
+            if fsEnabled == True:
+                # Definitely can't use this since it's a
+                # snapshotted filesystem.
+                msg = _("\'%s\'\n"
+                        "belongs to the ZFS filesystem \'%s\' "
+                        "which is already selected for "
+                        "regular ZFS snaphots." 
+                        "\n\nPlease select a drive "
+                        "not already in use by "
+                        "Time Slider") \
+                        % (newTargetDir, fs.name)
+                self._rsync_config_error(msg)
+                return False
+            else:
+                # See if there is anything else on the pool being
+                # snapshotted
+                poolName = fs.name.split("/", 1)[0]
+                for name,mount in self._datasets.list_filesystems():
+                    if name.find(poolName) == 0:
+                        try:
+                            otherEnabled = self._snapStateDic[name]
+                            radioBtn = self._xml.get_widget("defaultfsradio")
+                            snapAll = radioBtn.get_active()
+                            if snapAll or otherEnabled:
+                                msg = _("\'%s\'\n"
+                                        "belongs to the ZFS pool \'%s\' "
+                                        "which is already being used "
+                                        "to store ZFS snaphots." 
+                                        "\n\nPlease select a drive "
+                                        "not already in use by "
+                                        "Time Slider") \
+                                        % (newTargetDir, poolName)
+                                self._rsync_config_error(msg)
+                                return False
+                        except KeyError:
+                            pass               
+        except KeyError:
+            # No match found - good.
+            pass
+
+
+        # Figure out if there's a reasonable amount of free space to
+        # store backups. This is a vague guess at best.
+        allPools = zfs.list_zpools()
+        snapPools = []
+        # FIXME -  this is for custom selection. There is a short
+        # circuit case for default (All) configuration. Don't forget
+        # to implement this short circuit.
+        for poolName in allPools:
+            try:
+                snapPools.index(poolName)
+            except ValueError:
+                pool = zfs.ZPool(poolName)
+                # FIXME - we should include volumes here but they
+                # can only be set from the command line, not via
+                # the GUI, so not crucial.
+                for fsName,mount in pool.list_filesystems():
+                    # Don't try to catch exception. The filesystems
+                    # are already populated in self._snapStateDic
+                    enabled = self._snapStateDic[fsName]
+                    if enabled == True:
+                        snapPools.append(poolName)
+                        break
+
+        sumPoolSize = 0
+        for poolName in snapPools:
+            pool = zfs.ZPool(poolName)
+            # Rough calcualation, but precise enough for
+            # estimation purposes
+            sumPoolSize += pool.get_used_size()
+            sumPoolSize += pool.get_available_size()
+
+
+        # Compare with available space on rsync target dir
+        targetAvail = util.get_available_size(targetMountPoint)
+        targetUsed = util.get_used_size(targetMountPoint)
+        targetSum = targetAvail + targetUsed
+
+        # Recommended Minimum:
+        # At least double the combined size of all pools with
+        # fileystems selected for backup. Variables include,
+        # frequency of data changes, how much efficiency rsync
+        # sacrifices compared to ZFS' block level diff tracking,
+        # whether compression and/or deduplication are enabled 
+        # on the source pool/fileystem.
+        # We don't try to make calculations based on individual
+        # filesystem selection as there are too many unpredictable
+        # variables to make an estimation of any practical use.
+        # Let the user figure that out for themselves.
+
+        # The most consistent measurement is to use the sum of
+        # available and used size on the target fileystem. We
+        # assume based on previous checks that the target device
+        # is only being used for rsync backups and therefore the
+        # used value consists of existing backups and is. Available
+        # space can be reduced for various reasons including the used
+        # value increasing or for nfs mounted zfs fileystems, other
+        # zfs filesystems on the containing pool using up more space.
+        
+
+        targetPoolRatio = targetSum/float(sumPoolSize)
+        if (targetPoolRatio < RSYNCTARGETRATIO):
+            response = self._rsync_size_warning(snapPools,
+                                                 sumPoolSize,
+                                                 targetMountPoint,
+                                                 targetSum)
+            if response == False:
+                return False
+
+        self._newRsyncTargetDir = targetMountPoint
+        return True
+
+    def _on_ok_clicked(self, widget):
+        # Make sure the dictionaries are empty.
+        self._fsIntentDic = {}
+        self._snapStateDic = {}
+        self._rsyncStateDic = {}
+        enabled = self._xml.get_widget("enablebutton").get_active()
+        self._rsyncEnabled = self._xml.get_widget("rsyncbutton").get_active()
+        if enabled == False:
+            if self._rsyncEnabled == False and \
+               self._initialRsyncState == True:
+                self._rsyncSMF.disable_service()
+            if self._initialEnabledState == True:
+                self._sliderSMF.disable_service()
+            # Ignore other changes to the snapshot/rsync configuration
+            # of filesystems. Just broadcast the change and exit.
+            self._configNotify = True
+            self.broadcast_changes()
+            gtk.main_quit()
+        else:
+            model = self._fsTreeView.get_model()
+            snapalldata = self._xml.get_widget("defaultfsradio").get_active()
+                
+            if snapalldata == True:
+                model.foreach(self._set_fs_selection_state, True)
+                if self._rsyncEnabled == True:
+                    model.foreach(self._set_rsync_selection_state, True)
+            else:
+                model.foreach(self._get_fs_selection_state)
+                model.foreach(self._get_rsync_selection_state)
+            for fsname in self._snapStateDic:
+                self._refine_filesys_actions(fsname,
+                                              self._snapStateDic,
+                                              self._fsIntentDic)
+                if self._rsyncEnabled == True:
+                    self._refine_filesys_actions(fsname,
+                                                  self._rsyncStateDic,
+                                                  self._rsyncIntentDic)
+            if self._rsyncEnabled and \
+               not self._check_rsync_config():
+                    return
+
+            self._pulseDialog.show()
+            self._enabler = EnableService(self)
+            self._enabler.start()
+            glib.timeout_add(100,
+                             self._monitor_setup,
+                             self._xml.get_widget("pulsebar"))
+
+    def _on_enablebutton_toggled(self, widget):
+        expander = self._xml.get_widget("expander")
+        enabled = widget.get_active()
+        self._xml.get_widget("filesysframe").set_sensitive(enabled)
+        expander.set_sensitive(enabled)
+        if (enabled == False):
+            expander.set_expanded(False)
+
+    def _on_rsyncbutton_toggled(self, widget):
+        self._rsyncEnabled = widget.get_active()
+        if self._rsyncEnabled == True:
+            self._fsTreeView.insert_column(self._rsyncRadioColumn, 1)
+            self._rsyncCombo.set_sensitive(True)
+        else:
+            self._fsTreeView.remove_column(self._rsyncRadioColumn)
+            self._rsyncCombo.set_sensitive(False)
+
+    def _on_defaultfsradio_toggled(self, widget):
+        if widget.get_active() == True:
+            self._xml.get_widget("fstreeview").set_sensitive(False)
+
+    def _on_selectfsradio_toggled(self, widget):
+       if widget.get_active() == True:
+            self._xml.get_widget("fstreeview").set_sensitive(True)
+
+    def _advancedbox_unmap(self, widget):
+        # Auto shrink the window by subtracting the frame's height
+        # requistion from the window's height requisition
+        myrequest = widget.size_request()
+        toplevel = self._xml.get_widget("toplevel")
+        toprequest = toplevel.size_request()
+        toplevel.resize(toprequest[0], toprequest[1] - myrequest[1])
+
+    def _get_fs_selection_state(self, model, path, iter):
+        fsname = self._fsListStore.get_value(iter, 3)    
+        enabled = self._fsListStore.get_value(iter, 0)
+        self._snapStateDic[fsname] = enabled
+
+    def _get_rsync_selection_state(self, model, path, iter):
+        fsname = self._fsListStore.get_value(iter, 3)
+        enabled = self._fsListStore.get_value(iter, 1)
+        self._rsyncStateDic[fsname] = enabled
+
+    def _set_fs_selection_state(self, model, path, iter, selected):
+        fsname = self._fsListStore.get_value(iter, 3)
+        self._snapStateDic[fsname] = selected
+
+    def _set_rsync_selection_state(self, model, path, iter, selected):
+        fsname = self._fsListStore.get_value(iter, 3)
+        self._rsyncStateDic[fsname] = selected
+
+    def _refine_filesys_actions(self, fsname, inputdic, actions):
+        selected = inputdic[fsname]
+        try:
+            fstag = actions[fsname]
+            # Found so we can skip over.
+        except KeyError:
+            # Need to check parent value to see if
+            # we should set explicitly or just inherit.
+            path = fsname.rsplit("/", 1)
+            parentName = path[0]
+            if parentName == fsname:
+                # Means this filesystem is the root of the pool
+                # so we need to set it explicitly.
+                actions[fsname] = \
+                    FilesystemIntention(fsname, selected, False)
+            else:
+                parentIntent = None
+                inherit = False
+                # Check if parent is already set and if so whether to
+                # inherit or override with a locally set property value.
+                try:
+                    # Parent has already been registered
+                    parentIntent = actions[parentName]
+                except:
+                    # Parent not yet set, so do that recursively to figure
+                    # out if we need to inherit or set a local property on
+                    # this child filesystem.
+                    self._refine_filesys_actions(parentName,
+                                                  inputdic,
+                                                  actions)
+                    parentIntent = actions[parentName]
+                if parentIntent.selected == selected:
+                    inherit = True
+                actions[fsname] = \
+                    FilesystemIntention(fsname, selected, inherit)
+
+    def _validate_rsync_target(self, path):
+        """
+            Tests path to see if it is the pre-configured
+            rsync backup device path.
+            Returns True on success, otherwise False
+        """
+        # FIXME - this is duplicate in applet.py and rsync-backup.py
+        # It should be moved into a shared module
+        if not os.path.exists(path):
+            return False
+        testDir = os.path.join(path,
+                                rsyncsmf.RSYNCDIRPREFIX,
+                                self._nodeName)
+        testKeyFile = os.path.join(path,
+                                    rsyncsmf.RSYNCDIRPREFIX,
+                                    rsyncsmf.RSYNCCONFIGFILE)
+        if os.path.exists(testDir) and \
+            os.path.exists(testKeyFile):
+            testKeyVal = None
+            f = open(testKeyFile, 'r')
+            for line in f.readlines():
+                key, val = line.strip().split('=')
+                if key.strip() == "target_key":
+                    targetKey = val.strip()
+                    break
+            f.close()
+            if targetKey == self._smfTargetKey:
+                return True
+        return False
+
+
+    def commit_filesystem_selection(self):
+        """
+        Commits the intended filesystem selection actions based on the
+        user's UI configuration to disk. Compares with initial startup
+        configuration and applies the minimum set of necessary changes.
+        """
+        for fsname,fsmountpoint in self._datasets.list_filesystems():
+            fs = zfs.Filesystem(fsname, fsmountpoint)
+            try:
+                initialIntent = self._initialFsIntentDic[fsname]
+                intent = self._fsIntentDic[fsname]
+                if intent == initialIntent:
+                    continue
+                fs.set_auto_snap(intent.selected, intent.inherited)
+
+            except KeyError:
+                pass
+
+    def commit_rsync_selection(self):
+        """
+        Commits the intended filesystem selection actions based on the
+        user's UI configuration to disk. Compares with initial startup
+        configuration and applies the minimum set of necessary changes.
+        """
+        for fsname,fsmountpoint in self._datasets.list_filesystems():
+            fs = zfs.Filesystem(fsname, fsmountpoint)
+            try:
+                initialIntent = self._initialRsyncIntentDic[fsname]
+                intent = self._rsyncIntentDic[fsname]
+                if intent == initialIntent:
+                    continue
+                if intent.inherited == True and \
+                    initialIntent.inherited == False:
+                    fs.unset_user_property(rsyncsmf.RSYNCFSTAG)
+                else:
+                    if intent.selected == True:
+                        value = "true"
+                    else:
+                        value = "false"
+                    fs.set_user_property(rsyncsmf.RSYNCFSTAG,
+                                         value)
+            except KeyError:
+                pass
+
+    def setup_rsync_config(self):
+        if self._rsyncEnabled == True:
+            if self._newRsyncTargetSelected == True:
+                sys,nodeName,rel,ver,arch = os.uname()
+                basePath = os.path.join(self._newRsyncTargetDir,
+                                        rsyncsmf.RSYNCDIRPREFIX,)
+                nodePath = os.path.join(basePath,
+                                        nodeName)
+                configPath = os.path.join(basePath,
+                                          rsyncsmf.RSYNCCONFIGFILE)
+                newKey = generate_random_key()
+                try:
+                    origmask = os.umask(0222)
+                    if not os.path.exists(nodePath):
+                        os.makedirs(nodePath, 0755)
+                    f = open(configPath, 'w')
+                    f.write("target_key=%s\n" % (newKey))
+                    f.close()
+                    os.umask(origmask)
+                except OSError as e:
+                    self._pulseDialog.hide()
+                    sys.stderr.write("Error configuring external " \
+                                     "backup device:\n" \
+                                     "%s\n\nReason:\n %s") \
+                                     % (self._newRsyncTargetDir, str(e))
+                    sys.exit(-1)
+                self._rsyncSMF.set_target_dir(self._newRsyncTargetDir)
+                self._rsyncSMF.set_target_key(newKey)
+                # Applet monitors rsyncTargetDir so make sure to notify it.
+                self._configNotify = True
+        return
+
+    def setup_services(self):
+        # Take care of the rsync plugin service first since time-slider
+        # will query it.
+        # Changes to rsync or time-slider SMF service State should be
+        # broadcast to let notification applet refresh.
+        if self._rsyncEnabled == True and \
+            self._initialRsyncState == False:
+            self._rsyncSMF.enable_service()
+            self._configNotify = True
+        elif self._rsyncEnabled == False and \
+            self._initialRsyncState == True:
+            self._rsyncSMF.disable_service()
+            self._configNotify = True
+        customSelection = self._xml.get_widget("selectfsradio").get_active()
+        if customSelection != self._initialCustomSelection:
+            self._sliderSMF.set_custom_selection(customSelection)
+        if self._initialEnabledState == False:
+            enable_default_schedules()
+            self._sliderSMF.enable_service()
+            self._configNotify = True
+
+    def set_cleanup_level(self):
+        """
+        Wrapper function to set the warning level cleanup threshold
+        value as a percentage of pool capacity.
+        """
+        level = self._xml.get_widget("capspinbutton").get_value_as_int()
+        if level != self._initialCleanupLevel:
+            self._sliderSMF.set_cleanup_level("warning", level)
+
+    def broadcast_changes(self):
+        """
+        Blunt instrument to notify D-Bus listeners such as notification
+        applet to rescan service configuration
+        """
+        if self._configNotify == False:
+            return
+        self._dbus.config_changed()
+
+    def _on_deletesnapshots_clicked(self, widget):
+        cmdpath = os.path.join(os.path.dirname(self._execPath), \
+                               "../lib/time-slider-delete")
+        p = subprocess.Popen(cmdpath, close_fds=True)
+
+
+class EnableService(threading.Thread):
+
+    def __init__(self, setupManager):
+        threading.Thread.__init__(self)
+        self._setupManager = setupManager
+
+    def run(self):
+        try:
+            # Set the service state last so that the ZFS filesystems
+            # are correctly tagged before the snapshot scripts check them
+            self._setupManager.commit_filesystem_selection()
+            self._setupManager.commit_rsync_selection()
+            self._setupManager.set_cleanup_level()
+            self._setupManager.setup_rsync_config()
+            self._setupManager.setup_services()
+            self._setupManager.broadcast_changes()
+        except RuntimeError, message:
+            sys.stderr.write(str(message))
+
+def generate_random_key(length=32):
+    """
+    Returns a 'length' byte character composed of random letters and
+    unsigned single digit integers. Used to create a random
+    signature key to identify pre-configured backup directories
+    for the rsync plugin
+    """
+    from string import letters, digits
+    from random import choice
+    return ''.join([choice(letters + digits) \
+              for i in range(length)])
+
+def main(argv):
+    rbacp = RBACprofile()
+    # The setup GUI needs to be run as root in order to ensure
+    # that the rsync backup target directory is accessible by
+    # root and to perform validation checks on it.
+    # This GUI can be launched with an euid of root in one of
+    # the following 3 ways;
+    # 0. Run by the superuser (root)
+    # 1. Run via gksu to allow a non priviliged user to authenticate
+    #    as the superuser (root)
+
+    if os.geteuid() == 0:
+        manager = SetupManager(argv)
+        gtk.gdk.threads_enter()
+        gtk.main()
+        gtk.gdk.threads_leave()
+    elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
+        # Run via gksu, which will prompt for the root password
+        os.unsetenv("DBUS_SESSION_BUS_ADDRESS")
+        os.execl("/usr/bin/gksu", "gksu", argv)
+        # Shouldn't reach this point
+        sys.exit(1)
+    else:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Insufficient Priviliges"))
+        dialog.format_secondary_text(_("The snapshot manager service requires "
+                                       "administrative privileges to run. "
+                                       "You have not been assigned the necessary"
+                                       "administrative priviliges."
+                                       "\n\nConsult your system administrator "))
+        dialog.set_icon_name("time-slider-setup")
+        dialog.run()
+        sys.exit(1)
+
diff --git a/usr/share/time-slider/lib/time_slider/setupgui.py~ b/usr/share/time-slider/lib/time_slider/setupgui.py~
new file mode 100755 (executable)
index 0000000..b3a37b6
--- /dev/null
@@ -0,0 +1,1322 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import subprocess
+import threading
+import util
+import smf
+from autosnapsmf import enable_default_schedules, disable_default_schedules
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import rsyncsmf
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+
+import glib
+import gobject
+import gio
+import dbus
+import dbus.service
+import dbus.mainloop
+import dbus.mainloop.glib
+import dbussvc
+
+
+# This is the rough guess ratio used for rsync backup device size
+# vs. the total size of the pools it's expected to backup.
+RSYNCTARGETRATIO = 2
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from timeslidersmf import TimeSliderSMF
+from rbac import RBACprofile
+
+
+class FilesystemIntention:
+
+    def __init__(self, name, selected, inherited):
+        self.name = name
+        self.selected = selected
+        self.inherited = inherited
+
+    def __str__(self):
+        return_string = "Filesystem name: " + self.name + \
+                "\n\tSelected: " + str(self.selected) + \
+                "\n\tInherited: " + str(self.inherited)
+        return return_string
+
+    def __eq__(self, other):
+        if self.name != other.name:
+            return False
+        if self.inherited and other.inherited:
+            return True
+        elif not self.inherited and other.inherited:
+            return False
+        if (self.selected == other.selected) and \
+           (self.inherited == other.inherited):
+            return True
+        else:
+            return False
+
+class SetupManager:
+
+    def __init__(self, execpath):
+        self._execPath = execpath
+        self._datasets = zfs.Datasets()
+        self._xml = gtk.glade.XML("%s/../../glade/time-slider-setup.glade" \
+                                  % (os.path.dirname(__file__)))
+
+        # Tell dbus to use the gobject mainloop for async ops
+        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+        dbus.mainloop.glib.threads_init()
+
+        # Register a bus name with the system dbus daemon
+        systemBus = dbus.SystemBus()
+        busName = dbus.service.BusName("org.opensolaris.TimeSlider.config",
+                                       systemBus)
+        self._dbus = dbussvc.Config(systemBus,
+                                    '/org/opensolaris/TimeSlider/config')
+        # Used later to trigger a D-Bus notification of select configuration 
+        # changes made
+        self._configNotify = False
+
+        # These variables record the initial UI state which are used
+        # later to compare against the UI state when the OK or Cancel
+        # button is clicked and apply the minimum set of necessary 
+        # configuration changes. Prevents minor changes taking ages
+        # to be applied by the GUI.
+        self._initialEnabledState = None
+        self._initialRsyncState = None
+        self._initialRsyncTargetDir = None
+        self._initialCleanupLevel = None
+        self._initialCustomSelection = False
+        self._initialSnapStateDic = {}
+        self._initialRsyncStateDic = {}
+        self._initialFsIntentDic = {}
+        self._initialRsyncIntentDic = {}
+
+        # Currently selected rsync backup device via the GUI.
+        self._newRsyncTargetDir = None
+        # Used to store GUI filesystem selection state and the
+        # set of intended properties to apply to zfs filesystems.
+        self._snapStateDic = {}
+        self._rsyncStateDic = {}
+        self._fsIntentDic = {}
+        self._rsyncIntentDic = {}
+        # Dictionary that maps device ID numbers to zfs filesystem objects
+        self._fsDevices = {}
+
+        topLevel = self._xml.get_widget("toplevel")
+        self._pulseDialog = self._xml.get_widget("pulsedialog")
+        self._pulseDialog.set_transient_for(topLevel)
+        
+        # gio.VolumeMonitor reference
+        self._vm = gio.volume_monitor_get()
+        self._vm.connect("mount-added", self._mount_added)
+        self._vm.connect("mount-removed" , self._mount_removed)
+
+        self._fsListStore = gtk.ListStore(bool,
+                                         bool,
+                                         str,
+                                         str,
+                                         gobject.TYPE_PYOBJECT)
+        filesystems = self._datasets.list_filesystems()
+        for fsname,fsmountpoint in filesystems:
+            if (fsmountpoint == "legacy"):
+                mountpoint = _("Legacy")
+            else:
+                mountpoint = fsmountpoint
+            fs = zfs.Filesystem(fsname, fsmountpoint)
+            # Note that we don't deal with legacy mountpoints.
+            if fsmountpoint != "legacy" and fs.is_mounted():
+                self._fsDevices[os.stat(fsmountpoint).st_dev] = fs
+            snap = fs.get_auto_snap()
+            rsyncstr = fs.get_user_property(rsyncsmf.RSYNCFSTAG)
+            if rsyncstr == "true":
+                rsync = True
+            else:
+                rsync = False
+            # Rsync is only performed on snapshotted filesystems.
+            # So treat as False if rsync is set to true independently
+            self._fsListStore.append([snap, snap & rsync,
+                                     mountpoint, fs.name, fs])
+            self._initialSnapStateDic[fs.name] = snap
+            self._initialRsyncStateDic[fs.name] = snap & rsync
+        del filesystems
+
+        for fsname in self._initialSnapStateDic:
+                self._refine_filesys_actions(fsname,
+                                              self._initialSnapStateDic,
+                                              self._initialFsIntentDic)
+                self._refine_filesys_actions(fsname,
+                                              self._initialRsyncStateDic,
+                                              self._initialRsyncIntentDic)
+   
+        self._fsTreeView = self._xml.get_widget("fstreeview")
+        self._fsTreeView.set_sensitive(False)
+        self._fsTreeView.set_size_request(10, 200)
+
+        self._fsTreeView.set_model(self._fsListStore)
+
+        cell0 = gtk.CellRendererToggle()
+        cell1 = gtk.CellRendererToggle()
+        cell2 = gtk.CellRendererText()
+        cell3 = gtk.CellRendererText()
+        radioColumn = gtk.TreeViewColumn(_("Select"),
+                                             cell0, active=0)
+        self._fsTreeView.insert_column(radioColumn, 0)
+
+        self._rsyncRadioColumn = gtk.TreeViewColumn(_("Replicate"),
+                                                    cell1, active=1)
+        nameColumn = gtk.TreeViewColumn(_("Mount Point"),
+                                        cell2, text=2)
+        self._fsTreeView.insert_column(nameColumn, 2)
+        mountPointColumn = gtk.TreeViewColumn(_("File System Name"),
+                                              cell3, text=3)
+        self._fsTreeView.insert_column(mountPointColumn, 3)
+        cell0.connect('toggled', self._row_toggled)
+        cell1.connect('toggled', self._rsync_cell_toggled)
+        advancedBox = self._xml.get_widget("advancedbox")
+        advancedBox.connect('unmap', self._advancedbox_unmap)  
+
+        self._rsyncSMF = rsyncsmf.RsyncSMF("%s:rsync" \
+                                          %(plugin.PLUGINBASEFMRI))
+        state = self._rsyncSMF.get_service_state()
+        self._initialRsyncTargetDir = self._rsyncSMF.get_target_dir()
+        # Check for the default, unset value of "" from SMF.
+        if self._initialRsyncTargetDir == '""':
+            self._initialRsyncTargetDir = ''
+        self._newRsyncTargetDir = self._initialRsyncTargetDir
+        self._smfTargetKey = self._rsyncSMF.get_target_key()
+        self._newRsyncTargetSelected = False
+        sys,self._nodeName,rel,ver,arch = os.uname()
+
+        # Model columns:
+        # 0 Themed icon list (python list)
+        # 1 device root
+        # 2 volume name
+        # 3 Is gio.Mount device
+        # 4 Is separator (for comboBox separator rendering)
+        self._rsyncStore = gtk.ListStore(gobject.TYPE_PYOBJECT,
+                                         gobject.TYPE_STRING,
+                                         gobject.TYPE_STRING,
+                                         gobject.TYPE_BOOLEAN,
+                                         gobject.TYPE_BOOLEAN)
+        self._rsyncCombo = self._xml.get_widget("rsyncdevcombo")
+        mounts = self._vm.get_mounts()
+        for mount in mounts:
+            self._mount_added(self._vm, mount)
+        if len(mounts) > 0:
+            # Add a separator
+            self._rsyncStore.append((None, None, None, None, True))
+        del mounts
+
+        if len(self._newRsyncTargetDir) == 0:
+            self._rsyncStore.append((['folder'],
+                                    _("(None)"),
+                                    '',
+                                    False,
+                                    False))
+            # Add a separator
+            self._rsyncStore.append((None, None, None, None, True))
+        self._rsyncStore.append((None, _("Other..."), "Other", False, False))
+        self._iconCell = gtk.CellRendererPixbuf()
+        self._nameCell = gtk.CellRendererText()
+        self._rsyncCombo.clear()
+        self._rsyncCombo.pack_start(self._iconCell, False)
+        self._rsyncCombo.set_cell_data_func(self._iconCell,
+                                            self._icon_cell_render)
+        self._rsyncCombo.pack_end(self._nameCell)
+        self._rsyncCombo.set_attributes(self._nameCell, text=1)
+        self._rsyncCombo.set_row_separator_func(self._row_separator)
+        self._rsyncCombo.set_model(self._rsyncStore)
+        self._rsyncCombo.connect("changed", self._rsync_combo_changed)
+        # Force selection of currently configured device
+        self._rsync_dev_selected(self._newRsyncTargetDir)
+
+        # signal dictionary    
+        dic = {"on_ok_clicked" : self._on_ok_clicked,
+               "on_cancel_clicked" : gtk.main_quit,
+               "on_snapshotmanager_delete_event" : gtk.main_quit,
+               "on_enablebutton_toggled" : self._on_enablebutton_toggled,
+               "on_rsyncbutton_toggled" : self._on_rsyncbutton_toggled,
+               "on_defaultfsradio_toggled" : self._on_defaultfsradio_toggled,
+               "on_selectfsradio_toggled" : self._on_selectfsradio_toggled,
+               "on_deletesnapshots_clicked" : self._on_deletesnapshots_clicked}
+        self._xml.signal_autoconnect(dic)
+
+        if state != "disabled":
+            self._rsyncEnabled = True
+            self._xml.get_widget("rsyncbutton").set_active(True)
+            self._initialRsyncState = True
+        else:
+            self._rsyncEnabled = False
+            self._rsyncCombo.set_sensitive(False)
+            self._initialRsyncState = False
+
+        # Initialise SMF service instance state.
+        try:
+            self._sliderSMF = TimeSliderSMF()
+        except RuntimeError,message:
+            self._xml.get_widget("toplevel").set_sensitive(False)
+            dialog = gtk.MessageDialog(self._xml.get_widget("toplevel"),
+                                       0,
+                                       gtk.MESSAGE_ERROR,
+                                       gtk.BUTTONS_CLOSE,
+                                       _("Snapshot manager service error"))
+            dialog.format_secondary_text(_("The snapshot manager service does "
+                                         "not appear to be installed on this "
+                                         "system."
+                                         "\n\nSee the svcs(1) man page for more "
+                                         "information."
+                                         "\n\nDetails:\n%s")%(message))
+            dialog.set_icon_name("time-slider-setup")
+            dialog.run()
+            sys.exit(1)
+
+        if self._sliderSMF.svcstate == "disabled":
+            self._xml.get_widget("enablebutton").set_active(False)
+            self._initialEnabledState = False
+        elif self._sliderSMF.svcstate == "offline":
+            self._xml.get_widget("toplevel").set_sensitive(False)
+            errors = ''.join("%s\n" % (error) for error in \
+                self._sliderSMF.find_dependency_errors())
+            dialog = gtk.MessageDialog(self._xml.get_widget("toplevel"),
+                                        0,
+                                        gtk.MESSAGE_ERROR,
+                                        gtk.BUTTONS_CLOSE,
+                                        _("Snapshot manager service dependency error"))
+            dialog.format_secondary_text(_("The snapshot manager service has "
+                                            "been placed offline due to a dependency "
+                                            "problem. The following dependency problems "
+                                            "were found:\n\n%s\n\nRun \"svcs -xv\" from "
+                                            "a command prompt for more information about "
+                                            "these dependency problems.") % errors)
+            dialog.set_icon_name("time-slider-setup")
+            dialog.run()
+            sys.exit(1)
+        elif self._sliderSMF.svcstate == "maintenance":
+            self._xml.get_widget("toplevel").set_sensitive(False)
+            dialog = gtk.MessageDialog(self._xml.get_widget("toplevel"),
+                                        0,
+                                        gtk.MESSAGE_ERROR,
+                                        gtk.BUTTONS_CLOSE,
+                                        _("Snapshot manager service error"))
+            dialog.format_secondary_text(_("The snapshot manager service has "
+                                            "encountered a problem and has been "
+                                            "disabled until the problem is fixed."
+                                            "\n\nSee the svcs(1) man page for more "
+                                            "information."))
+            dialog.set_icon_name("time-slider-setup")
+            dialog.run()
+            sys.exit(1)
+        else:
+            # FIXME: Check transitional states 
+            self._xml.get_widget("enablebutton").set_active(True)
+            self._initialEnabledState = True
+
+
+        # Emit a toggled signal so that the initial GUI state is consistent
+        self._xml.get_widget("enablebutton").emit("toggled")
+        # Check the snapshotting policy (UserData (default), or Custom)
+        self._initialCustomSelection = self._sliderSMF.is_custom_selection()
+        if self._initialCustomSelection == True:
+            self._xml.get_widget("selectfsradio").set_active(True)
+            # Show the advanced controls so the user can see the
+            # customised configuration.
+            if self._sliderSMF.svcstate != "disabled":
+                self._xml.get_widget("expander").set_expanded(True)
+        else: # "false" or any other non "true" value
+            self._xml.get_widget("defaultfsradio").set_active(True)
+
+        # Set the cleanup threshhold value
+        spinButton = self._xml.get_widget("capspinbutton")
+        critLevel = self._sliderSMF.get_cleanup_level("critical")
+        warnLevel = self._sliderSMF.get_cleanup_level("warning")
+
+        # Force the warning level to something practical
+        # on the lower end, and make it no greater than the
+        # critical level specified in the SVC instance.
+        spinButton.set_range(70, critLevel)
+        self._initialCleanupLevel = warnLevel
+        if warnLevel > 70:
+            spinButton.set_value(warnLevel)
+        else:
+            spinButton.set_value(70)
+
+    def _icon_cell_render(self, celllayout, cell, model, iter):
+        iconList = self._rsyncStore.get_value(iter, 0)
+        if iconList != None:
+            gicon = gio.ThemedIcon(iconList)
+            cell.set_property("gicon", gicon)
+        else:
+            root = self._rsyncStore.get_value(iter, 2)
+            if root == "Other":
+                cell.set_property("gicon", None)
+
+    def _row_separator(self, model, iter):
+        return model.get_value(iter, 4)
+
+    def _mount_added(self, volume_monitor, mount):
+        icon = mount.get_icon()
+        iconList = icon.get_names()
+        if iconList == None:
+            iconList = ['drive-harddisk', 'drive']
+        root = mount.get_root()
+        path = root.get_path()
+        mountName = mount.get_name()
+        volume = mount.get_volume()
+        if volume == None:
+            volName = mount.get_name()
+            if volName == None:
+                volName = os.path.split(path)[1]
+        else:
+            volName = volume.get_name()
+
+        # Check to see if there is at least one gio.Mount device already
+        # in the ListStore. If not, then we also need to add a separator
+        # row.
+        iter = self._rsyncStore.get_iter_first()
+        if iter and self._rsyncStore.get_value(iter, 3) == False:
+            self._rsyncStore.insert(0, (None, None, None, None, True))
+        
+        self._rsyncStore.insert(0, (iconList, volName, path, True, False))
+        # If this happens to be the already configured backup device
+        # and the user hasn't tried to change device yet, auto select
+        # it.
+        if self._initialRsyncTargetDir == self._newRsyncTargetDir:
+            if self._validate_rsync_target(path) == True:
+                self._rsyncCombo.set_active(0)
+
+    def _mount_removed(self, volume_monitor, mount):
+        root = mount.get_root()
+        path = root.get_path()
+        iter = self._rsyncStore.get_iter_first()
+        mountIter = None
+        numMounts = 0
+        # Search gio.Mount devices
+        while iter != None and \
+            self._rsyncStore.get_value(iter, 3) == True:
+            numMounts += 1
+            compPath = self._rsyncStore.get_value(iter, 2)
+            if compPath == path:
+                mountIter = iter
+                break
+            else:
+                iter = self._rsyncStore.iter_next(iter)
+        if mountIter != None:
+            if numMounts == 1:
+                # Need to remove the separator also since
+                # there will be no more gio.Mount devices
+                # shown in the combo box
+                sepIter = self._rsyncStore.iter_next(mountIter)
+                if self._rsyncStore.get_value(sepIter, 4) == True:
+                    self._rsyncStore.remove(sepIter)                  
+            self._rsyncStore.remove(mountIter)
+            iter = self._rsyncStore.get_iter_first()
+            # Insert a custom folder if none exists already
+            if self._rsyncStore.get_value(iter, 2) == "Other":
+                path = self._initialRsyncTargetDir
+                length = len(path)
+                if length > 1:
+                    name = os.path.split(path)[1]
+                elif length == 1:
+                    name = path
+                else: # Indicates path is unset: ''
+                    name = _("(None)")
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (None,
+                                                       None,
+                                                       None,
+                                                       None,
+                                                       True))
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (['folder'],
+                                                       name,
+                                                       path,
+                                                       False,
+                                                       False))
+            self._rsyncCombo.set_active_iter(iter)
+
+    def _monitor_setup(self, pulseBar):
+        if self._enabler.isAlive() == True:
+            pulseBar.pulse()
+            return True
+        else:
+            gtk.main_quit()   
+
+    def _row_toggled(self, renderer, path):
+        model = self._fsTreeView.get_model()
+        iter = model.get_iter(path)
+        state = renderer.get_active()
+        if state == False:
+            self._fsListStore.set_value(iter, 0, True)
+        else:
+            self._fsListStore.set_value(iter, 0, False)
+            self._fsListStore.set_value(iter, 1, False)
+
+    def _rsync_cell_toggled(self, renderer, path):
+        model = self._fsTreeView.get_model()
+        iter = model.get_iter(path)
+        state = renderer.get_active()
+        rowstate = self._fsListStore.get_value(iter, 0)
+        if rowstate == True:
+            if state == False:
+                self._fsListStore.set_value(iter, 1, True)
+            else:
+                self._fsListStore.set_value(iter, 1, False)
+
+    def _rsync_config_error(self, msg):
+        topLevel = self._xml.get_widget("toplevel")
+        dialog = gtk.MessageDialog(topLevel,
+                                    0,
+                                    gtk.MESSAGE_ERROR,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Unsuitable Backup Location"))
+        dialog.format_secondary_text(msg)
+        dialog.set_icon_name("time-slider-setup")
+        dialog.run()
+        dialog.hide()
+        return
+
+    def _rsync_dev_selected(self, path):
+        iter = self._rsyncStore.get_iter_first()
+        while iter != None:
+            # Break out when we hit a non gio.Mount device
+            if self._rsyncStore.get_value(iter, 3) == False:
+                break
+            compPath = self._rsyncStore.get_value(iter, 2)
+            if compPath == path:
+                self._rsyncCombo.set_active_iter(iter)
+                self._newRsyncTargetDir = path
+                return
+            else:
+                iter = self._rsyncStore.iter_next(iter)
+
+        # Not one of the shortcut RMM devices, so it's
+        # some other path on the filesystem.
+        # iter may be pointing at a separator. Increment
+        # to next row iter if so.
+        if self._rsyncStore.get_value(iter, 4) == True:
+            iter = self._rsyncStore.iter_next(iter)
+
+        if iter != None:
+            if len(path) > 1:
+                name = os.path.split(path)[1]
+            elif len(path) == 1:
+                name = path
+            else: # Indicates path is unset: ''
+                name = _("(None)")
+            # Could be either the custom folder selection
+            # row or the  "Other" row if the custom row
+            # was not created. If "Other" then create the
+            # custom row and separator now at this position
+            if self._rsyncStore.get_value(iter, 2) == "Other":
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (None,
+                                                       None,
+                                                       None,
+                                                       None,
+                                                       True))
+                iter = self._rsyncStore.insert_before(iter,
+                                                      (['folder'],
+                                                       name,
+                                                       path,
+                                                       False,
+                                                       False))
+            else:
+                self._rsyncStore.set(iter,
+                                     1, name,
+                                     2, path)
+            self._rsyncCombo.set_active_iter(iter)
+            self._newRsyncTargetDir = path
+
+    def _rsync_combo_changed(self, combobox):
+        newIter = combobox.get_active_iter()
+        if newIter != None:
+            root = self._rsyncStore.get_value(newIter, 2)
+            if root != "Other":
+                self._newRsyncTargetDir = root
+            else:
+                msg = _("Select A Back Up Device")
+                fileDialog = \
+                    gtk.FileChooserDialog(
+                        msg,
+                        self._xml.get_widget("toplevel"),
+                        gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
+                        (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,
+                        gtk.STOCK_OK,gtk.RESPONSE_OK),
+                        None)
+                self._rsyncCombo.set_sensitive(False)
+                response = fileDialog.run()
+                fileDialog.hide()
+                if response == gtk.RESPONSE_OK:
+                    gFile = fileDialog.get_file()
+                    self._rsync_dev_selected(gFile.get_path())
+                else:
+                    self._rsync_dev_selected(self._newRsyncTargetDir)
+                self._rsyncCombo.set_sensitive(True)
+
+    def _rsync_size_warning(self, zpools, zpoolSize,
+                             rsyncTarget, targetSize):
+        # Using decimal "GB" instead of binary "GiB"
+        KB = 1000
+        MB = 1000 * KB
+        GB = 1000 * MB
+        TB = 1000 * GB
+
+        suggestedSize = RSYNCTARGETRATIO * zpoolSize
+        if suggestedSize > TB:
+            sizeStr = "%.1f TB" % round(suggestedSize / float(TB), 1)
+        elif suggestedSize > GB:
+            sizeStr = "%.1f GB" % round(suggestedSize / float(GB), 1)
+        else:
+            sizeStr = "%.1f MB" % round(suggestedSize / float(MB), 1)
+
+        if targetSize > TB:
+            targetStr = "%.1f TB" % round(targetSize / float(TB), 1)
+        elif targetSize > GB:
+            targetStr = "%.1f GB" % round(targetSize / float(GB), 1)
+        else:
+            targetStr = "%.1f MB" % round(targetSize / float(MB), 1)
+
+
+        msg = _("Time Slider suggests a device with a capacity of at "
+                "least <b>%s</b>.\n"
+                "The device: \'<b>%s</b>\'\nonly has <b>%s</b>\n"
+                "Do you want to use it anyway?") \
+                % (sizeStr, rsyncTarget, targetStr)
+
+        topLevel = self._xml.get_widget("toplevel")
+        dialog = gtk.MessageDialog(topLevel,
+                                   0,
+                                   gtk.MESSAGE_QUESTION,
+                                   gtk.BUTTONS_YES_NO,
+                                   _("Time Slider"))
+        dialog.set_default_response(gtk.RESPONSE_NO)
+        dialog.set_transient_for(topLevel)
+        dialog.set_markup(msg)
+        dialog.set_icon_name("time-slider-setup")
+
+        response = dialog.run()
+        dialog.hide()
+        if response == gtk.RESPONSE_YES:
+            return True
+        else:
+            return False
+
+    def _check_rsync_config(self):
+        """
+           Checks rsync configuration including, filesystem selection,
+           target directory validation and capacity checks.
+           Returns True if everything is OK, otherwise False.
+           Pops up blocking error dialogs to notify users of error
+           conditions before returning.
+        """
+        def _get_mount_point(path):
+            if os.path.ismount(path):
+                return path
+            else:
+                return _get_mount_point(abspath(join(path, pardir)))
+
+        if self._rsyncEnabled != True:
+            return True
+
+        if len(self._newRsyncTargetDir) == 0:
+            msg = _("No backup device was selected.\n"
+                    "Please select an empty device.")
+            self._rsync_config_error(msg)
+            return False
+        # There's little that can be done if the device is from a
+        # previous configuration and currently offline. So just 
+        # treat it as being OK based on the assumption that it was
+        # previously deemed to be OK.
+        if self._initialRsyncTargetDir == self._newRsyncTargetDir and \
+           not os.path.exists(self._newRsyncTargetDir):
+            return True
+        # Perform the required validation checks on the
+        # target directory.
+        newTargetDir = self._newRsyncTargetDir
+
+        # We require the whole device. So find the enclosing
+        # mount point and inspect from there.
+        targetMountPoint = abspath(_get_mount_point(newTargetDir))
+
+        # Check that it's writable.
+        f = None
+        testFile = os.path.join(targetMountPoint, ".ts-test")
+        try:
+            f = open(testFile, 'w')
+        except (OSError, IOError):
+            msg = _("\'%s\'\n"
+                    "is not writable. The backup device must "
+                    "be writable by the system administrator." 
+                    "\n\nPlease use a different device.") \
+                    % (targetMountPoint)
+            self._rsync_config_error(msg)
+            return False
+        f.close()
+
+        # Try to create a symlink. Rsync requires this to
+        # do incremental backups and to ensure it's posix like
+        # enough to correctly set file ownerships and perms.
+        os.chdir(targetMountPoint)
+        try:
+            os.link(testFile, ".ts-test-link")
+        except OSError:
+            msg = _("\'%s\'\n"
+                    "contains an incompatible file system. " 
+                    "The selected device must have a Unix "
+                    "style file system that supports file "
+                    "linking, such as UFS"
+                    "\n\nPlease use a different device.") \
+                    % (targetMountPoint)
+            self._rsync_config_error(msg)
+            return False
+        finally:
+            os.unlink(testFile)
+        os.unlink(".ts-test-link")
+
+        # Check that selected directory is either empty
+        # or already preconfigured as a backup target
+        sys,nodeName,rel,ver,arch = os.uname()
+        basePath = os.path.join(targetMountPoint,
+                                rsyncsmf.RSYNCDIRPREFIX)
+        nodePath = os.path.join(basePath,
+                                nodeName)
+        configPath = os.path.join(basePath,
+                                    rsyncsmf.RSYNCCONFIGFILE)
+        self._newRsyncTargetSelected = True
+        targetDirKey = None
+
+        contents = os.listdir(targetMountPoint)
+        os.chdir(targetMountPoint)
+
+        # The only other exception to an empty directory is
+        # "lost+found".
+        for item in contents:
+            if (item != rsyncsmf.RSYNCDIRPREFIX and \
+                item != "lost+found") or \
+               not os.path.isdir(item) or \
+               os.path.islink(item):
+                msg = _("\'%s\'\n is not an empty device.\n\n"
+                        "Please select an empty device.") \
+                        % (newTargetDir)
+                self._rsync_config_error(msg)
+                return False
+
+        # Validate existing directory structure
+        if os.path.exists(basePath):
+            # We only accept a pre-existing directory if
+            # 1. It has a config key that matches that stored by
+            #    the rsync plugin's SMF configuration
+            # 2. It has a single subfolder that matches the nodename
+            #    of this system,
+
+            # Check for previous config key
+            if os.path.exists(configPath):
+                f = open(configPath, 'r')
+                for line in f.readlines():
+                    key, val = line.strip().split('=')
+                    if key.strip() == "target_key":
+                        targetDirKey = val.strip()
+                        break
+
+            # Examine anything else in the directory
+            self._targetSelectionError = None
+            dirList = [d for d in os.listdir(basePath) if
+                        d != '.rsync-config']
+            os.chdir(basePath)
+            if len(dirList) > 0:
+                msg = _("\'%s\'\n is not an empty device.\n\n"
+                        "Please select an empty device.") \
+                        % (newTargetDir)
+                # No config key or > 1 directory:
+                # User specified a non empty directory.
+                if targetDirKey == None or len(dirList) > 1:
+                    self._rsync_config_error(msg)
+                    return False
+                # Make sure the single item is not a file or symlink.
+                elif os.path.islink(dirList[0]) or \
+                        os.path.isfile(dirList[0]):
+                    self._rsync_config_error(msg)
+                    return False
+                else:
+                    # Has 1 other item and a config key. Other
+                    # item must be a directory and must match the
+                    # system nodename and SMF's key value respectively
+                    # respectively
+                    if dirList[0] != nodeName and \
+                        targetDirKey != self._smfTargetKey:
+                        msg = _("\'%s\'\n"
+                                "is a Time Slider external backup device "
+                                "that is already in use by another system. "
+                                "Backup devices may not be shared between "
+                                "systems." 
+                                "\n\nPlease use a different device.") \
+                                % (newTargetDir)
+                        self._rsync_config_error(msg)                                
+                        return False
+                    else:
+                        if dirList[0] == nodeName and \
+                           targetDirKey != self._smfTargetKey:
+                            # Looks like a device that we previously used,
+                            # but discontinued using in favour of some other
+                            # device.
+                            msg = _("\'<b>%s</b>\' appears to be a a device "
+                                    "previously configured for use by this "
+                                    "system.\n\nDo you want resume use of "
+                                    "this device for backups?") \
+                                    % (newTargetDir)
+
+                            topLevel = self._xml.get_widget("toplevel")
+                            dialog = gtk.MessageDialog(topLevel,
+                                                       0,
+                                                       gtk.MESSAGE_QUESTION,
+                                                       gtk.BUTTONS_YES_NO,
+                                                       _("Time Slider"))
+                            dialog.set_default_response(gtk.RESPONSE_NO)
+                            dialog.set_transient_for(topLevel)
+                            dialog.set_markup(msg)
+                            dialog.set_icon_name("time-slider-setup")
+
+                            response = dialog.run()
+                            dialog.hide()
+                            if response == gtk.RESPONSE_NO:
+                                return False
+                        else:
+                            # Appears to be our own pre-configured directory.
+                            self._newRsyncTargetSelected = False
+
+        # Compare device ID against selected ZFS filesystems
+        # and their enclosing Zpools. The aim is to avoid
+        # a vicous circle caused by backing up snapshots onto
+        # the same pool the snapshots originate from
+        targetDev = os.stat(newTargetDir).st_dev
+        try:
+            fs = self._fsDevices[targetDev]
+            
+            # See if the filesystem itself is selected
+            # and/or any other fileystem on the pool is 
+            # selected.
+            fsEnabled = self._snapStateDic[fs.name]
+            if fsEnabled == True:
+                # Definitely can't use this since it's a
+                # snapshotted filesystem.
+                msg = _("\'%s\'\n"
+                        "belongs to the ZFS filesystem \'%s\' "
+                        "which is already selected for "
+                        "regular ZFS snaphots." 
+                        "\n\nPlease select a drive "
+                        "not already in use by "
+                        "Time Slider") \
+                        % (newTargetDir, fs.name)
+                self._rsync_config_error(msg)
+                return False
+            else:
+                # See if there is anything else on the pool being
+                # snapshotted
+                poolName = fs.name.split("/", 1)[0]
+                for name,mount in self._datasets.list_filesystems():
+                    if name.find(poolName) == 0:
+                        try:
+                            otherEnabled = self._snapStateDic[name]
+                            radioBtn = self._xml.get_widget("defaultfsradio")
+                            snapAll = radioBtn.get_active()
+                            if snapAll or otherEnabled:
+                                msg = _("\'%s\'\n"
+                                        "belongs to the ZFS pool \'%s\' "
+                                        "which is already being used "
+                                        "to store ZFS snaphots." 
+                                        "\n\nPlease select a drive "
+                                        "not already in use by "
+                                        "Time Slider") \
+                                        % (newTargetDir, poolName)
+                                self._rsync_config_error(msg)
+                                return False
+                        except KeyError:
+                            pass               
+        except KeyError:
+            # No match found - good.
+            pass
+
+
+        # Figure out if there's a reasonable amount of free space to
+        # store backups. This is a vague guess at best.
+        allPools = zfs.list_zpools()
+        snapPools = []
+        # FIXME -  this is for custom selection. There is a short
+        # circuit case for default (All) configuration. Don't forget
+        # to implement this short circuit.
+        for poolName in allPools:
+            try:
+                snapPools.index(poolName)
+            except ValueError:
+                pool = zfs.ZPool(poolName)
+                # FIXME - we should include volumes here but they
+                # can only be set from the command line, not via
+                # the GUI, so not crucial.
+                for fsName,mount in pool.list_filesystems():
+                    # Don't try to catch exception. The filesystems
+                    # are already populated in self._snapStateDic
+                    enabled = self._snapStateDic[fsName]
+                    if enabled == True:
+                        snapPools.append(poolName)
+                        break
+
+        sumPoolSize = 0
+        for poolName in snapPools:
+            pool = zfs.ZPool(poolName)
+            # Rough calcualation, but precise enough for
+            # estimation purposes
+            sumPoolSize += pool.get_used_size()
+            sumPoolSize += pool.get_available_size()
+
+
+        # Compare with available space on rsync target dir
+        targetAvail = util.get_available_size(targetMountPoint)
+        targetUsed = util.get_used_size(targetMountPoint)
+        targetSum = targetAvail + targetUsed
+
+        # Recommended Minimum:
+        # At least double the combined size of all pools with
+        # fileystems selected for backup. Variables include,
+        # frequency of data changes, how much efficiency rsync
+        # sacrifices compared to ZFS' block level diff tracking,
+        # whether compression and/or deduplication are enabled 
+        # on the source pool/fileystem.
+        # We don't try to make calculations based on individual
+        # filesystem selection as there are too many unpredictable
+        # variables to make an estimation of any practical use.
+        # Let the user figure that out for themselves.
+
+        # The most consistent measurement is to use the sum of
+        # available and used size on the target fileystem. We
+        # assume based on previous checks that the target device
+        # is only being used for rsync backups and therefore the
+        # used value consists of existing backups and is. Available
+        # space can be reduced for various reasons including the used
+        # value increasing or for nfs mounted zfs fileystems, other
+        # zfs filesystems on the containing pool using up more space.
+        
+
+        targetPoolRatio = targetSum/float(sumPoolSize)
+        if (targetPoolRatio < RSYNCTARGETRATIO):
+            response = self._rsync_size_warning(snapPools,
+                                                 sumPoolSize,
+                                                 targetMountPoint,
+                                                 targetSum)
+            if response == False:
+                return False
+
+        self._newRsyncTargetDir = targetMountPoint
+        return True
+
+    def _on_ok_clicked(self, widget):
+        # Make sure the dictionaries are empty.
+        self._fsIntentDic = {}
+        self._snapStateDic = {}
+        self._rsyncStateDic = {}
+        enabled = self._xml.get_widget("enablebutton").get_active()
+        self._rsyncEnabled = self._xml.get_widget("rsyncbutton").get_active()
+        if enabled == False:
+            if self._rsyncEnabled == False and \
+               self._initialRsyncState == True:
+                self._rsyncSMF.disable_service()
+            if self._initialEnabledState == True:
+                self._sliderSMF.disable_service()
+            # Ignore other changes to the snapshot/rsync configuration
+            # of filesystems. Just broadcast the change and exit.
+            self._configNotify = True
+            self.broadcast_changes()
+            gtk.main_quit()
+        else:
+            model = self._fsTreeView.get_model()
+            snapalldata = self._xml.get_widget("defaultfsradio").get_active()
+                
+            if snapalldata == True:
+                model.foreach(self._set_fs_selection_state, True)
+                if self._rsyncEnabled == True:
+                    model.foreach(self._set_rsync_selection_state, True)
+            else:
+                model.foreach(self._get_fs_selection_state)
+                model.foreach(self._get_rsync_selection_state)
+            for fsname in self._snapStateDic:
+                self._refine_filesys_actions(fsname,
+                                              self._snapStateDic,
+                                              self._fsIntentDic)
+                if self._rsyncEnabled == True:
+                    self._refine_filesys_actions(fsname,
+                                                  self._rsyncStateDic,
+                                                  self._rsyncIntentDic)
+            if self._rsyncEnabled and \
+               not self._check_rsync_config():
+                    return
+
+            self._pulseDialog.show()
+            self._enabler = EnableService(self)
+            self._enabler.start()
+            glib.timeout_add(100,
+                             self._monitor_setup,
+                             self._xml.get_widget("pulsebar"))
+
+    def _on_enablebutton_toggled(self, widget):
+        expander = self._xml.get_widget("expander")
+        enabled = widget.get_active()
+        self._xml.get_widget("filesysframe").set_sensitive(enabled)
+        expander.set_sensitive(enabled)
+        if (enabled == False):
+            expander.set_expanded(False)
+
+    def _on_rsyncbutton_toggled(self, widget):
+        self._rsyncEnabled = widget.get_active()
+        if self._rsyncEnabled == True:
+            self._fsTreeView.insert_column(self._rsyncRadioColumn, 1)
+            self._rsyncCombo.set_sensitive(True)
+        else:
+            self._fsTreeView.remove_column(self._rsyncRadioColumn)
+            self._rsyncCombo.set_sensitive(False)
+
+    def _on_defaultfsradio_toggled(self, widget):
+        if widget.get_active() == True:
+            self._xml.get_widget("fstreeview").set_sensitive(False)
+
+    def _on_selectfsradio_toggled(self, widget):
+       if widget.get_active() == True:
+            self._xml.get_widget("fstreeview").set_sensitive(True)
+
+    def _advancedbox_unmap(self, widget):
+        # Auto shrink the window by subtracting the frame's height
+        # requistion from the window's height requisition
+        myrequest = widget.size_request()
+        toplevel = self._xml.get_widget("toplevel")
+        toprequest = toplevel.size_request()
+        toplevel.resize(toprequest[0], toprequest[1] - myrequest[1])
+
+    def _get_fs_selection_state(self, model, path, iter):
+        fsname = self._fsListStore.get_value(iter, 3)    
+        enabled = self._fsListStore.get_value(iter, 0)
+        self._snapStateDic[fsname] = enabled
+
+    def _get_rsync_selection_state(self, model, path, iter):
+        fsname = self._fsListStore.get_value(iter, 3)
+        enabled = self._fsListStore.get_value(iter, 1)
+        self._rsyncStateDic[fsname] = enabled
+
+    def _set_fs_selection_state(self, model, path, iter, selected):
+        fsname = self._fsListStore.get_value(iter, 3)
+        self._snapStateDic[fsname] = selected
+
+    def _set_rsync_selection_state(self, model, path, iter, selected):
+        fsname = self._fsListStore.get_value(iter, 3)
+        self._rsyncStateDic[fsname] = selected
+
+    def _refine_filesys_actions(self, fsname, inputdic, actions):
+        selected = inputdic[fsname]
+        try:
+            fstag = actions[fsname]
+            # Found so we can skip over.
+        except KeyError:
+            # Need to check parent value to see if
+            # we should set explicitly or just inherit.
+            path = fsname.rsplit("/", 1)
+            parentName = path[0]
+            if parentName == fsname:
+                # Means this filesystem is the root of the pool
+                # so we need to set it explicitly.
+                actions[fsname] = \
+                    FilesystemIntention(fsname, selected, False)
+            else:
+                parentIntent = None
+                inherit = False
+                # Check if parent is already set and if so whether to
+                # inherit or override with a locally set property value.
+                try:
+                    # Parent has already been registered
+                    parentIntent = actions[parentName]
+                except:
+                    # Parent not yet set, so do that recursively to figure
+                    # out if we need to inherit or set a local property on
+                    # this child filesystem.
+                    self._refine_filesys_actions(parentName,
+                                                  inputdic,
+                                                  actions)
+                    parentIntent = actions[parentName]
+                if parentIntent.selected == selected:
+                    inherit = True
+                actions[fsname] = \
+                    FilesystemIntention(fsname, selected, inherit)
+
+    def _validate_rsync_target(self, path):
+        """
+            Tests path to see if it is the pre-configured
+            rsync backup device path.
+            Returns True on success, otherwise False
+        """
+        # FIXME - this is duplicate in applet.py and rsync-backup.py
+        # It should be moved into a shared module
+        if not os.path.exists(path):
+            return False
+        testDir = os.path.join(path,
+                                rsyncsmf.RSYNCDIRPREFIX,
+                                self._nodeName)
+        testKeyFile = os.path.join(path,
+                                    rsyncsmf.RSYNCDIRPREFIX,
+                                    rsyncsmf.RSYNCCONFIGFILE)
+        if os.path.exists(testDir) and \
+            os.path.exists(testKeyFile):
+            testKeyVal = None
+            f = open(testKeyFile, 'r')
+            for line in f.readlines():
+                key, val = line.strip().split('=')
+                if key.strip() == "target_key":
+                    targetKey = val.strip()
+                    break
+            f.close()
+            if targetKey == self._smfTargetKey:
+                return True
+        return False
+
+
+    def commit_filesystem_selection(self):
+        """
+        Commits the intended filesystem selection actions based on the
+        user's UI configuration to disk. Compares with initial startup
+        configuration and applies the minimum set of necessary changes.
+        """
+        for fsname,fsmountpoint in self._datasets.list_filesystems():
+            fs = zfs.Filesystem(fsname, fsmountpoint)
+            try:
+                initialIntent = self._initialFsIntentDic[fsname]
+                intent = self._fsIntentDic[fsname]
+                if intent == initialIntent:
+                    continue
+                fs.set_auto_snap(intent.selected, intent.inherited)
+
+            except KeyError:
+                pass
+
+    def commit_rsync_selection(self):
+        """
+        Commits the intended filesystem selection actions based on the
+        user's UI configuration to disk. Compares with initial startup
+        configuration and applies the minimum set of necessary changes.
+        """
+        for fsname,fsmountpoint in self._datasets.list_filesystems():
+            fs = zfs.Filesystem(fsname, fsmountpoint)
+            try:
+                initialIntent = self._initialRsyncIntentDic[fsname]
+                intent = self._rsyncIntentDic[fsname]
+                if intent == initialIntent:
+                    continue
+                if intent.inherited == True and \
+                    initialIntent.inherited == False:
+                    fs.unset_user_property(rsyncsmf.RSYNCFSTAG)
+                else:
+                    if intent.selected == True:
+                        value = "true"
+                    else:
+                        value = "false"
+                    fs.set_user_property(rsyncsmf.RSYNCFSTAG,
+                                         value)
+            except KeyError:
+                pass
+
+    def setup_rsync_config(self):
+        if self._rsyncEnabled == True:
+            if self._newRsyncTargetSelected == True:
+                sys,nodeName,rel,ver,arch = os.uname()
+                basePath = os.path.join(self._newRsyncTargetDir,
+                                        rsyncsmf.RSYNCDIRPREFIX,)
+                nodePath = os.path.join(basePath,
+                                        nodeName)
+                configPath = os.path.join(basePath,
+                                          rsyncsmf.RSYNCCONFIGFILE)
+                newKey = generate_random_key()
+                try:
+                    origmask = os.umask(0222)
+                    if not os.path.exists(nodePath):
+                        os.makedirs(nodePath, 0755)
+                    f = open(configPath, 'w')
+                    f.write("target_key=%s\n" % (newKey))
+                    f.close()
+                    os.umask(origmask)
+                except OSError as e:
+                    self._pulseDialog.hide()
+                    sys.stderr.write("Error configuring external " \
+                                     "backup device:\n" \
+                                     "%s\n\nReason:\n %s") \
+                                     % (self._newRsyncTargetDir, str(e))
+                    sys.exit(-1)
+                self._rsyncSMF.set_target_dir(self._newRsyncTargetDir)
+                self._rsyncSMF.set_target_key(newKey)
+                # Applet monitors rsyncTargetDir so make sure to notify it.
+                self._configNotify = True
+        return
+
+    def setup_services(self):
+        # Take care of the rsync plugin service first since time-slider
+        # will query it.
+        # Changes to rsync or time-slider SMF service State should be
+        # broadcast to let notification applet refresh.
+        if self._rsyncEnabled == True and \
+            self._initialRsyncState == False:
+            self._rsyncSMF.enable_service()
+            self._configNotify = True
+        elif self._rsyncEnabled == False and \
+            self._initialRsyncState == True:
+            self._rsyncSMF.disable_service()
+            self._configNotify = True
+        customSelection = self._xml.get_widget("selectfsradio").get_active()
+        if customSelection != self._initialCustomSelection:
+            self._sliderSMF.set_custom_selection(customSelection)
+        if self._initialEnabledState == False:
+            enable_default_schedules()
+            self._sliderSMF.enable_service()
+            self._configNotify = True
+
+    def set_cleanup_level(self):
+        """
+        Wrapper function to set the warning level cleanup threshold
+        value as a percentage of pool capacity.
+        """
+        level = self._xml.get_widget("capspinbutton").get_value_as_int()
+        if level != self._initialCleanupLevel:
+            self._sliderSMF.set_cleanup_level("warning", level)
+
+    def broadcast_changes(self):
+        """
+        Blunt instrument to notify D-Bus listeners such as notification
+        applet to rescan service configuration
+        """
+        if self._configNotify == False:
+            return
+        self._dbus.config_changed()
+
+    def _on_deletesnapshots_clicked(self, widget):
+        cmdpath = os.path.join(os.path.dirname(self._execPath), \
+                               "../lib/time-slider-delete")
+        p = subprocess.Popen(cmdpath, close_fds=True)
+
+
+class EnableService(threading.Thread):
+
+    def __init__(self, setupManager):
+        threading.Thread.__init__(self)
+        self._setupManager = setupManager
+
+    def run(self):
+        try:
+            # Set the service state last so that the ZFS filesystems
+            # are correctly tagged before the snapshot scripts check them
+            self._setupManager.commit_filesystem_selection()
+            self._setupManager.commit_rsync_selection()
+            self._setupManager.set_cleanup_level()
+            self._setupManager.setup_rsync_config()
+            self._setupManager.setup_services()
+            self._setupManager.broadcast_changes()
+        except RuntimeError, message:
+            sys.stderr.write(str(message))
+
+def generate_random_key(length=32):
+    """
+    Returns a 'length' byte character composed of random letters and
+    unsigned single digit integers. Used to create a random
+    signature key to identify pre-configured backup directories
+    for the rsync plugin
+    """
+    from string import letters, digits
+    from random import choice
+    return ''.join([choice(letters + digits) \
+              for i in range(length)])
+
+def main(argv):
+    rbacp = RBACprofile()
+    # The setup GUI needs to be run as root in order to ensure
+    # that the rsync backup target directory is accessible by
+    # root and to perform validation checks on it.
+    # This GUI can be launched with an euid of root in one of
+    # the following 3 ways;
+    # 0. Run by the superuser (root)
+    # 1. Run via gksu to allow a non priviliged user to authenticate
+    #    as the superuser (root)
+
+    if os.geteuid() == 0:
+        manager = SetupManager(argv)
+        gtk.gdk.threads_enter()
+        gtk.main()
+        gtk.gdk.threads_leave()
+    elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
+        # Run via gksu, which will prompt for the root password
+        os.unsetenv("DBUS_SESSION_BUS_ADDRESS")
+        os.execl("/usr/bin/gksu", "gksu", argv)
+        # Shouldn't reach this point
+        sys.exit(1)
+    else:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Insufficient Priviliges"))
+        dialog.format_secondary_text(_("The snapshot manager service requires "
+                                       "administrative privileges to run. "
+                                       "You have not been assigned the necessary"
+                                       "administrative priviliges."
+                                       "\n\nConsult your system administrator "))
+        dialog.set_icon_name("time-slider-setup")
+        dialog.run()
+        sys.exit(1)
+
diff --git a/usr/share/time-slider/lib/time_slider/smf.py b/usr/share/time-slider/lib/time_slider/smf.py
new file mode 100644 (file)
index 0000000..b241592
--- /dev/null
@@ -0,0 +1,153 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import subprocess
+import threading
+import util
+
+#SMF EXIT CODES
+SMF_EXIT_OK          = 0
+SMF_EXIT_ERR_FATAL   = 95
+SMF_EXIT_ERR_CONFIG  = 96
+SMF_EXIT_MON_DEGRADE = 97
+SMF_EXIT_MON_OFFLINE = 98
+SMF_EXIT_ERR_NOSMF   = 99
+SMF_EXIT_ERR_PERM    = 100
+#SMF_EXIT_ERR_OTHER = non-zero
+
+
+# Commonly used command paths
+PFCMD = "/usr/bin/pfexec"
+SVCSCMD = "/usr/bin/svcs"
+SVCADMCMD = "/usr/sbin/svcadm"
+SVCCFGCMD = "/usr/sbin/svccfg"
+SVCPROPCMD = "/usr/bin/svcprop"
+
+
+class SMFInstance(Exception):
+
+    def __init__(self, instanceName):
+        self.instanceName = instanceName
+        self.svcstate = self.get_service_state()
+        self.svcdeps = self.get_service_dependencies()
+
+
+    def get_service_dependencies(self):
+        cmd = [SVCSCMD, "-H", "-o", "fmri", "-d", self.instanceName]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip().split("\n")
+        return result
+
+    def get_verbose(self):
+        cmd = [SVCPROPCMD, "-c", "-p", \
+               DAEMONPROPGROUP + '/' + "verbose", \
+               self.instanceName]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        if result == "true":
+            return True
+        else:
+            return False
+
+    def find_dependency_errors(self):
+        errors = []
+        #FIXME - do this in one pass.
+        for dep in self.svcdeps:
+            cmd = [SVCSCMD, "-H", "-o", "state", dep]
+            outdata,errdata = util.run_command(cmd)
+            result = outdata.rstrip()
+            if result != "online":
+                errors.append("%s\t%s" % (result, dep))
+        return errors
+
+    def get_service_state(self):
+        cmd = [SVCSCMD, "-H", "-o", "state", self.instanceName]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        return result
+
+    def get_prop(self, propgroup, propname):
+        cmd = [SVCPROPCMD, "-c", "-p", \
+               propgroup + '/' + propname,\
+               self.instanceName]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+
+        return result
+
+    def set_prop(self, propgroup, propname, proptype, value):
+        cmd = [PFCMD, SVCCFGCMD, "-s", self.instanceName, "setprop", \
+               propgroup + '/' + propname, "=", proptype + ":", \
+               value]
+        util.run_command(cmd)
+        self.refresh_service()
+
+    def set_string_prop(self, propgroup, propname, value):
+        cmd = [PFCMD, SVCCFGCMD, "-s", self.instanceName, "setprop", \
+               propgroup + '/' + propname, "=", "astring:",
+               "\"%s\"" % (value)]
+        util.run_command(cmd)
+        self.refresh_service()
+
+    def set_boolean_prop(self, propgroup, propname, value):
+        if value == True:
+            strval = "true"
+        else:
+            strval = "false"
+        self.set_prop(propgroup, propname, "boolean", strval)
+
+    def set_integer_prop(self, propgroup, propname, value):
+        self.set_prop(propgroup, propname, "integer", str(value))
+
+    def refresh_service(self):
+        cmd = [PFCMD, SVCADMCMD, "refresh", self.instanceName]
+        p = subprocess.Popen(cmd, close_fds=True)
+
+    def disable_service (self):
+        if self.svcstate == "disabled":
+            return
+        cmd = [PFCMD, SVCADMCMD, "disable", self.instanceName]
+        p = subprocess.Popen(cmd, close_fds=True)
+        self.svcstate = self.get_service_state()
+
+    def enable_service (self):
+        if (self.svcstate == "online" or self.svcstate == "degraded"):
+            return
+        cmd = [PFCMD, SVCADMCMD, "enable", self.instanceName]
+        p = subprocess.Popen(cmd, close_fds=True)
+        self.svcstate = self.get_service_state()
+
+    def mark_maintenance (self):
+        cmd = [SVCADMCMD, "mark", "maintenance", self.instanceName]
+        subprocess.Popen(cmd, close_fds=True)
+
+    def __str__(self):
+        ret = "SMF Instance:\n" +\
+              "\tName:\t\t\t%s\n" % (self.instanceName) +\
+              "\tState:\t\t\t%s\n" % (self.svcstate)
+        return ret
+
+
+if __name__ == "__main__":
+  S = SMFInstance('svc:/application/time-slider')
+  print S
+
diff --git a/usr/share/time-slider/lib/time_slider/snapnowui.py b/usr/share/time-slider/lib/time_slider/snapnowui.py
new file mode 100755 (executable)
index 0000000..9e6c7c4
--- /dev/null
@@ -0,0 +1,224 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import datetime
+import getopt
+import string
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+try:
+    import glib
+    import gobject
+except:
+    sys.exit(1)
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from rbac import RBACprofile
+
+class SnapshotNowDialog:
+
+    def __init__(self, dir_path, zfs_fs):
+        self.dir_path = dir_path
+        self.zfs_fs = zfs_fs
+        self.xml = gtk.glade.XML("%s/../../glade/time-slider-snapshot.glade" \
+                                  % (os.path.dirname(__file__)))
+        self.dialog = self.xml.get_widget("dialog")
+        self.dir_label = self.xml.get_widget("dir_label")
+        self.snap_name_entry = self.xml.get_widget("snapshot_name_entry")
+       # signal dictionary     
+        dic = {"on_closebutton_clicked" : gtk.main_quit,
+               "on_window_delete_event" : gtk.main_quit,
+               "on_cancel_clicked" : gtk.main_quit,
+               "on_ok_clicked" : self.__on_ok_clicked}
+        self.xml.signal_autoconnect(dic)
+
+       self.snap_name_entry.connect("activate", self.__on_entry_activate, 0)
+
+       self.dir_label.set_text(self.dir_path)
+       self.snap_name_entry.set_text("my-snapshot-%s" % datetime.datetime.now().strftime("%Y-%m-%d_%Hh%M:%S"))
+
+       self.dialog.show ()
+
+    def validate_name (self, name, showErrorDialog=False):
+       #check name validity
+       # from http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/common/zfs/zfs_namecheck.c#dataset_namecheck
+       # http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/common/zfs/zfs_namecheck.c#valid_char
+
+       invalid = False
+       _validchars = string.ascii_letters + string.digits + \
+                     "-_.:"
+       _allchars = string.maketrans("", "")
+       _invalidchars = _allchars.translate(_allchars, _validchars)
+  
+       valid_name = ""
+
+       for c in name:
+         if c not in _invalidchars:
+           valid_name = valid_name + c
+         else:
+           invalid = True
+
+       if invalid and showErrorDialog:
+         dialog = gtk.MessageDialog(None,
+                                    0,
+                                    gtk.MESSAGE_ERROR,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Invalid characters in snapshot name"))
+         dialog.set_title (_("Error"))
+         dialog.format_secondary_text(_("Allowed characters for snapshot names are :\n"
+                                        "[a-z][A-Z][0-9][-_.:\n"
+                                        "All invalid characters will be removed\n"))
+         dialog.run ()                                  
+         dialog.destroy ()
+       return valid_name
+       
+
+    def __on_entry_activate (self, widget, none):
+       self.snap_name_entry.set_text (self.validate_name (self.snap_name_entry.get_text(), True))
+       return
+       
+
+    def __on_ok_clicked (self, widget):
+      name = self.snap_name_entry.get_text()
+      valid_name = self.validate_name (name, True)
+      if name == valid_name:
+       cmd = "pfexec /usr/sbin/zfs snapshot %s@%s" % (self.zfs_fs, self.validate_name (self.snap_name_entry.get_text()))
+       fin,fout,ferr = os.popen3(cmd)
+        # Check for any error output generated and
+        # return it to caller if so.
+        error = ferr.read()
+       self.dialog.hide ()
+        if len(error) > 0:
+         dialog = gtk.MessageDialog(None,
+                                    0,
+                                    gtk.MESSAGE_ERROR,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Error occured while creating the snapshot"))
+         dialog.set_title (_("Error"))
+         dialog.format_secondary_text(error)
+         dialog.run ()
+        else:
+         dialog = gtk.MessageDialog(None,
+                                    0,
+                                    gtk.MESSAGE_INFO,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Snapshot created successfully"))
+         dialog.set_title (_("Success"))
+         dialog.format_secondary_text(_("A snapshot of zfs filesystem %(zfs_fs)s\n"
+                                      "named %(valid_name)s\n"
+                                      "has been created.\n") %
+                                      { "zfs_fs" : self.zfs_fs, "valid_name" : valid_name})
+         dialog.run ()
+
+       sys.exit(1)
+      else:
+       self.snap_name_entry.set_text (valid_name)
+
+def main(argv):
+    try:
+        opts,args = getopt.getopt(sys.argv[1:], "", [])
+    except getopt.GetoptError:
+        sys.exit(2)
+    #FIXME
+    #check for 2 args here we assume the arguments are correct
+    if len(args) != 2:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Invalid arguments count."))
+       dialog.set_title (_("Error"))
+        dialog.format_secondary_text(_("Snapshot Now requires"
+                                       " 2 arguments :\n- The path of the "
+                                      "directory to be snapshotted.\n"
+                                       "- The zfs filesystem corresponding "
+                                      "to this directory."))
+        dialog.run()
+       sys.exit (2)
+       
+    rbacp = RBACprofile()
+    # The user security attributes checked are the following:
+    # 1. The "Primary Administrator" role
+    # 4. The "ZFS Files System Management" profile.
+    #
+    # Valid combinations of the above are:
+    # - 1 or 4
+    # Note that an effective UID=0 will match any profile search so
+    # no need to check it explicitly.
+    if rbacp.has_profile("ZFS File System Management"):
+       manager = SnapshotNowDialog(args[0],args[1])
+        gtk.main()
+    elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
+        # Run via gksu, which will prompt for the root password
+        newargs = ["gksu", argv]
+        for arg in args:
+            newargs.append(arg)
+        os.execv("/usr/bin/gksu", newargs)
+        # Shouldn't reach this point
+        sys.exit(1)
+    else:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Insufficient Priviliges"))
+       dialog.set_title (_("Error"))
+        dialog.format_secondary_text(_("Snapshot Now requires "
+                                       "administrative privileges to run. "
+                                       "You have not been assigned the necessary"
+                                       "administrative priviliges."
+                                       "\n\nConsult your system administrator "))
+        dialog.run()
+        print argv + "is not a valid executable path"
+        sys.exit(1)
+
diff --git a/usr/share/time-slider/lib/time_slider/snapnowui.py~ b/usr/share/time-slider/lib/time_slider/snapnowui.py~
new file mode 100755 (executable)
index 0000000..9e6c7c4
--- /dev/null
@@ -0,0 +1,224 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import datetime
+import getopt
+import string
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+try:
+    import glib
+    import gobject
+except:
+    sys.exit(1)
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from rbac import RBACprofile
+
+class SnapshotNowDialog:
+
+    def __init__(self, dir_path, zfs_fs):
+        self.dir_path = dir_path
+        self.zfs_fs = zfs_fs
+        self.xml = gtk.glade.XML("%s/../../glade/time-slider-snapshot.glade" \
+                                  % (os.path.dirname(__file__)))
+        self.dialog = self.xml.get_widget("dialog")
+        self.dir_label = self.xml.get_widget("dir_label")
+        self.snap_name_entry = self.xml.get_widget("snapshot_name_entry")
+       # signal dictionary     
+        dic = {"on_closebutton_clicked" : gtk.main_quit,
+               "on_window_delete_event" : gtk.main_quit,
+               "on_cancel_clicked" : gtk.main_quit,
+               "on_ok_clicked" : self.__on_ok_clicked}
+        self.xml.signal_autoconnect(dic)
+
+       self.snap_name_entry.connect("activate", self.__on_entry_activate, 0)
+
+       self.dir_label.set_text(self.dir_path)
+       self.snap_name_entry.set_text("my-snapshot-%s" % datetime.datetime.now().strftime("%Y-%m-%d_%Hh%M:%S"))
+
+       self.dialog.show ()
+
+    def validate_name (self, name, showErrorDialog=False):
+       #check name validity
+       # from http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/common/zfs/zfs_namecheck.c#dataset_namecheck
+       # http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/common/zfs/zfs_namecheck.c#valid_char
+
+       invalid = False
+       _validchars = string.ascii_letters + string.digits + \
+                     "-_.:"
+       _allchars = string.maketrans("", "")
+       _invalidchars = _allchars.translate(_allchars, _validchars)
+  
+       valid_name = ""
+
+       for c in name:
+         if c not in _invalidchars:
+           valid_name = valid_name + c
+         else:
+           invalid = True
+
+       if invalid and showErrorDialog:
+         dialog = gtk.MessageDialog(None,
+                                    0,
+                                    gtk.MESSAGE_ERROR,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Invalid characters in snapshot name"))
+         dialog.set_title (_("Error"))
+         dialog.format_secondary_text(_("Allowed characters for snapshot names are :\n"
+                                        "[a-z][A-Z][0-9][-_.:\n"
+                                        "All invalid characters will be removed\n"))
+         dialog.run ()                                  
+         dialog.destroy ()
+       return valid_name
+       
+
+    def __on_entry_activate (self, widget, none):
+       self.snap_name_entry.set_text (self.validate_name (self.snap_name_entry.get_text(), True))
+       return
+       
+
+    def __on_ok_clicked (self, widget):
+      name = self.snap_name_entry.get_text()
+      valid_name = self.validate_name (name, True)
+      if name == valid_name:
+       cmd = "pfexec /usr/sbin/zfs snapshot %s@%s" % (self.zfs_fs, self.validate_name (self.snap_name_entry.get_text()))
+       fin,fout,ferr = os.popen3(cmd)
+        # Check for any error output generated and
+        # return it to caller if so.
+        error = ferr.read()
+       self.dialog.hide ()
+        if len(error) > 0:
+         dialog = gtk.MessageDialog(None,
+                                    0,
+                                    gtk.MESSAGE_ERROR,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Error occured while creating the snapshot"))
+         dialog.set_title (_("Error"))
+         dialog.format_secondary_text(error)
+         dialog.run ()
+        else:
+         dialog = gtk.MessageDialog(None,
+                                    0,
+                                    gtk.MESSAGE_INFO,
+                                    gtk.BUTTONS_CLOSE,
+                                    _("Snapshot created successfully"))
+         dialog.set_title (_("Success"))
+         dialog.format_secondary_text(_("A snapshot of zfs filesystem %(zfs_fs)s\n"
+                                      "named %(valid_name)s\n"
+                                      "has been created.\n") %
+                                      { "zfs_fs" : self.zfs_fs, "valid_name" : valid_name})
+         dialog.run ()
+
+       sys.exit(1)
+      else:
+       self.snap_name_entry.set_text (valid_name)
+
+def main(argv):
+    try:
+        opts,args = getopt.getopt(sys.argv[1:], "", [])
+    except getopt.GetoptError:
+        sys.exit(2)
+    #FIXME
+    #check for 2 args here we assume the arguments are correct
+    if len(args) != 2:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Invalid arguments count."))
+       dialog.set_title (_("Error"))
+        dialog.format_secondary_text(_("Snapshot Now requires"
+                                       " 2 arguments :\n- The path of the "
+                                      "directory to be snapshotted.\n"
+                                       "- The zfs filesystem corresponding "
+                                      "to this directory."))
+        dialog.run()
+       sys.exit (2)
+       
+    rbacp = RBACprofile()
+    # The user security attributes checked are the following:
+    # 1. The "Primary Administrator" role
+    # 4. The "ZFS Files System Management" profile.
+    #
+    # Valid combinations of the above are:
+    # - 1 or 4
+    # Note that an effective UID=0 will match any profile search so
+    # no need to check it explicitly.
+    if rbacp.has_profile("ZFS File System Management"):
+       manager = SnapshotNowDialog(args[0],args[1])
+        gtk.main()
+    elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
+        # Run via gksu, which will prompt for the root password
+        newargs = ["gksu", argv]
+        for arg in args:
+            newargs.append(arg)
+        os.execv("/usr/bin/gksu", newargs)
+        # Shouldn't reach this point
+        sys.exit(1)
+    else:
+        dialog = gtk.MessageDialog(None,
+                                   0,
+                                   gtk.MESSAGE_ERROR,
+                                   gtk.BUTTONS_CLOSE,
+                                   _("Insufficient Priviliges"))
+       dialog.set_title (_("Error"))
+        dialog.format_secondary_text(_("Snapshot Now requires "
+                                       "administrative privileges to run. "
+                                       "You have not been assigned the necessary"
+                                       "administrative priviliges."
+                                       "\n\nConsult your system administrator "))
+        dialog.run()
+        print argv + "is not a valid executable path"
+        sys.exit(1)
+
diff --git a/usr/share/time-slider/lib/time_slider/timesliderd.py b/usr/share/time-slider/lib/time_slider/timesliderd.py
new file mode 100755 (executable)
index 0000000..eb2e341
--- /dev/null
@@ -0,0 +1,977 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import subprocess
+import re
+import threading
+import getopt
+import syslog
+import time
+import datetime
+import calendar
+import signal
+
+import glib
+import gobject
+import dbus
+import dbus.service
+import dbus.mainloop
+import dbus.mainloop.glib
+
+import dbussvc
+import zfs
+import smf
+import timeslidersmf
+import autosnapsmf
+import plugin
+from rbac import RBACprofile
+import util
+
+_MINUTE = 60
+_HOUR = _MINUTE * 60
+_DAY = _HOUR * 24
+_WEEK = _DAY * 7
+
+
+# Status codes for actual zpool capacity levels.
+# These are relative to the SMF property defined
+# levels for: user, warning and emergenecy levels
+STATUS_OK = 0 # Below user specified threshhold. Everything was OK
+STATUS_WARNING = 1 # Above specified user threshold level
+STATUS_CRITICAL = 2 # Above specified critical threshhold level
+STATUS_EMERGENCY = 3 # Above specified emergency threshhold level
+
+intervals = {"weeks" : _WEEK, "days" : _DAY, "hours" : _HOUR, "minutes" : _MINUTE}
+
+
+class SnapshotManager(threading.Thread):
+
+    def __init__(self, bus):
+        # Used to wake up the run() method prematurely in the event
+        # of a SIGHUP/SMF refresh
+        self._conditionLock = threading.Condition(threading.RLock())
+        # Used when schedules are being rebuilt or examined.
+        self._refreshLock = threading.Lock()
+        # Indicates that cleanup is in progress when locked
+        self._cleanupLock = threading.Lock()
+        self._datasets = zfs.Datasets()
+        # Indicates that schedules need to be rebuilt from scratch
+        self._stale = True
+        self._lastCleanupCheck = 0;
+        self._zpools = []
+        self._poolstatus = {}
+        self._destroyedsnaps = []
+
+        # This is also checked during the refresh() method but we need
+        # to know it sooner for instantiation of the PluginManager
+        self._smf = timeslidersmf.TimeSliderSMF()
+        try:
+            self.verbose = self._smf.get_verbose()
+        except RuntimeError,message:
+            sys.stderr.write("Error determing whether debugging is enabled\n")
+            self.verbose = False
+
+        self._dbus = dbussvc.AutoSnap(bus,
+                                      '/org/opensolaris/TimeSlider/autosnap',
+                                      self)
+
+        self._plugin = plugin.PluginManager(self.verbose)
+        self.exitCode = smf.SMF_EXIT_OK
+        self.refresh()
+
+        # Seems we're up and running OK. 
+        # Signal our parent so we can daemonise
+        os.kill(os.getppid(), signal.SIGUSR1)
+
+        # SMF/svc.startd sends SIGHUP to force a
+        # a refresh of the daemon
+        signal.signal(signal.SIGHUP, self._signalled)
+
+        # Init done. Now initiaslise threading.
+        threading.Thread.__init__ (self)
+        self.setDaemon(True)
+
+    def run(self):
+        # Deselect swap and dump volumes so they don't get snapshotted.
+        for vol in self._datasets.list_volumes():
+            name = vol.rsplit("/")
+            try:
+                if (name[1] == "swap" or name[1] == "dump"):
+                    util.debug("Auto excluding %s volume" % vol, self.verbose)
+                    volume = zfs.Volume(vol)
+                    volume.set_auto_snap(False)
+            except IndexError:
+                pass
+            
+        nexttime = None
+        waittime = None
+        while True:
+            try:
+                self.refresh()
+                # First check and, if necessary, perform any remedial cleanup.
+                # This is best done before creating any new snapshots which may
+                # otherwise get immediately gobbled up by the remedial cleanup.
+                if self._needs_cleanup() == True:
+                    self._perform_cleanup()
+                    # Check to see if cleanup actually deleted anything before
+                    # notifying the user. Avoids the popup appearing continuously
+                    if len(self._destroyedsnaps) > 0:
+                        self._send_notification()
+                    self._send_to_syslog()
+
+                nexttime = self._check_snapshots()
+                # Overdue snapshots are already taken automatically
+                # inside _check_snapshots() so nexttime should never be
+                # < 0. It can be None however, which is fine since it 
+                # will cause the scheduler thread to sleep indefinitely
+                # or until a SIGHUP is caught.
+                if nexttime:
+                    util.debug("Waiting until " + str (nexttime), self.verbose)
+                waittime = None
+                if nexttime != None:
+                    waittime = nexttime - long(time.time())
+                    if (waittime <= 0):
+                        # We took too long and missed a snapshot, so break out
+                        # and catch up on it the next time through the loop
+                        continue
+                # waittime could be None if no auto-snap schedules are online
+                self._conditionLock.acquire()
+                if waittime:
+                    util.debug("Waiting %d seconds" % (waittime), self.verbose)
+                    self._conditionLock.wait(waittime)
+                else: #None. Just wait a while to check for cleanups.
+                    util.debug("No auto-snapshot schedules online.", \
+                               self.verbose)
+                    self._conditionLock.wait(_MINUTE * 15)
+
+            except OSError, message:
+                sys.stderr.write("Caught OSError exception in snapshot" +
+                                 " manager thread\n")
+                sys.stderr.write("Error details:\n" + \
+                                 "--------BEGIN ERROR MESSAGE--------\n" + \
+                                 str(message) + \
+                                 "\n--------END ERROR MESSAGE--------\n")
+                self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                # Exit this thread
+                break
+            except RuntimeError,message:
+                sys.stderr.write("Caught RuntimeError exception in snapshot" +
+                                 " manager thread\n")
+                sys.stderr.write("Error details:\n" + \
+                                 "--------BEGIN ERROR MESSAGE--------\n" + \
+                                 str(message) + \
+                                 "\n--------END ERROR MESSAGE--------\n")
+                # Exit this thread
+                break
+
+    def _signalled(self, signum, frame):
+        if signum == signal.SIGHUP:
+            if self._refreshLock.acquire(False) == False:
+                return
+            self._stale = True
+            self._refreshLock.release()
+            self._conditionLock.acquire()
+            self._conditionLock.notify()
+            self._conditionLock.release()
+
+    def refresh(self):
+        """
+        Checks if defined snapshot schedules are out
+        of date and rebuilds and updates if necessary
+        """
+        self._refreshLock.acquire()
+        if self._stale == True:
+            self._configure_svc_props()
+            self._rebuild_schedules()
+            self._update_schedules()
+            self._plugin.refresh()
+            self._stale = False
+        self._refreshLock.release()
+
+    def _configure_svc_props(self):
+        try:
+            self.verbose = self._smf.get_verbose()
+        except RuntimeError,message:
+            sys.stderr.write("Error determing whether debugging is enabled\n")
+            self.verbose = False
+
+        try:
+            cleanup = self._smf.get_remedial_cleanup()
+            warn = self._smf.get_cleanup_level("warning")
+            util.debug("Warning level value is:   %d%%" % warn, self.verbose)
+            crit = self._smf.get_cleanup_level("critical")
+            util.debug("Critical level value is:  %d%%" % crit, self.verbose)
+            emer = self._smf.get_cleanup_level("emergency")
+            util.debug("Emergency level value is: %d%%" % emer, self.verbose)
+        except RuntimeError,message:
+            sys.stderr.write("Failed to determine cleanup threshhold levels\n")
+            sys.stderr.write("Details:\n" + \
+                             "--------BEGIN ERROR MESSAGE--------\n" + \
+                             str(message) + \
+                             "\n---------END ERROR MESSAGE---------\n")
+            sys.stderr.write("Using factory defaults of 80%, 90% and 95%\n")
+            #Go with defaults
+            #FIXME - this would be an appropriate case to mark svc as degraded
+            self._remedialCleanup = True
+            self._warningLevel = 80
+            self._criticalLevel = 90
+            self._emergencyLevel = 95
+        else:
+            self._remedialCleanup = cleanup
+            self._warningLevel = warn
+            self._criticalLevel = crit
+            self._emergencyLevel = emer
+
+        try:
+            self._keepEmpties = self._smf.get_keep_empties()
+        except RuntimeError,message:
+            # Not fatal, just assume we delete them (default configuration)
+            sys.stderr.write("Can't determine whether to keep empty snapshots\n")
+            sys.stderr.write("Details:\n" + \
+                             "--------BEGIN ERROR MESSAGE--------\n" + \
+                             str(message) + \
+                             "\n---------END ERROR MESSAGE---------\n")
+            sys.stderr.write("Assuming default value: False\n")
+            self._keepEmpties = False
+
+        # Previously, snapshot labels used the ":" character was used as a 
+        # separator character for datestamps. Windows filesystems such as
+        # CIFS and FAT choke on this character so now we use a user definable
+        # separator value, with a default value of "_"
+        # We need to check for both the old and new format when looking for
+        # snapshots.
+        self._separator = self._smf.get_separator()
+        self._prefix = "%s[:%s]" \
+            % (autosnapsmf.SNAPLABELPREFIX, self._separator)
+
+        # Rebuild pool list
+        self._zpools = []
+        try:
+            for poolname in zfs.list_zpools():
+                # Do not try to examine FAULTED pools
+                zpool = zfs.ZPool(poolname)
+                if zpool.health == "FAULTED":
+                    util.debug("Ignoring faulted Zpool: %s\n" \
+                               % (zpool.name), \
+                               self.verbose)
+                else:
+                    self._zpools.append(zpool)
+                util.debug(str(zpool), self.verbose)
+        except RuntimeError,message:
+            sys.stderr.write("Could not list Zpools\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            # Propogate exception up to thread's run() method
+            raise RuntimeError,message
+
+
+    def _rebuild_schedules(self):
+        """
+        Builds 2 lists of default and custom auto-snapshot SMF instances
+        """
+
+        self._last = {}
+        self._next = {}
+        self._keep = {}
+
+        try:
+            _defaultSchedules = autosnapsmf.get_default_schedules()
+            _customSchedules = autosnapsmf.get_custom_schedules()
+        except RuntimeError,message:
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            raise RuntimeError, "Error reading SMF schedule instances\n" + \
+                                "Details:\n" + str(message)
+        else:
+            # Now set it in stone.
+            self._defaultSchedules = tuple(_defaultSchedules)
+            self._customSchedules = tuple(_customSchedules)
+            
+            # Build the combined schedule tuple from default + custom schedules
+            _defaultSchedules.extend(_customSchedules)
+            self._allSchedules = tuple(_defaultSchedules)
+            for schedule,i,p,keep in self._allSchedules:
+                self._last[schedule] = 0
+                self._next[schedule] = 0
+                self._keep[schedule] = keep
+
+    def _update_schedules(self):
+        interval = 0
+        idx = 1 # Used to index subsets for schedule overlap calculation
+        last = None
+
+        for schedule,interval,period,keep in self._allSchedules:
+            # Shortcut if we've already processed this schedule and it's 
+            # still up to date. Don't skip the default schedules though
+            # because overlap affects their scheduling
+            if [schedule,interval,period,keep] not in \
+                self._defaultSchedules and \
+                (self._next[schedule] > self._last[schedule]):
+                util.debug("Short circuiting %s recalculation" \
+                           % (schedule), \
+                           self.verbose)
+                continue
+
+            # If we don't have an internal timestamp for the given schedule
+            # ask zfs for the last snapshot and get it's creation timestamp.
+            if self._last[schedule] == 0:
+                try:
+                    snaps = self._datasets.list_snapshots("%s%s" % \
+                                                         (self._prefix,
+                                                          schedule))
+                except RuntimeError,message:
+                    self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                    sys.stderr.write("Failed to list snapshots during schedule update\n")
+                    #Propogate up to the thread's run() method
+                    raise RuntimeError,message
+
+                if len(snaps) > 0:
+                    util.debug("Last %s snapshot was: %s" % \
+                               (schedule, snaps[-1][0]), \
+                               self.verbose)
+                    self._last[schedule] = snaps[-1][1]
+
+            last = self._last[schedule]
+            if interval != "months": # months is non-constant. See below.
+                util.debug("Recalculating %s schedule" % (schedule), \
+                           self.verbose)
+                try:
+                    totalinterval = intervals[interval] * period
+                except KeyError:
+                    self.exitCode = smf.SMF_EXIT_ERR_CONFIG
+                    sys.stderr.write(schedule + \
+                                      " schedule has invalid interval: " + \
+                                      "'%s\'\n" % interval)
+                    #Propogate up to thread's run() method
+                    raise RuntimeError
+                if [schedule,interval,period,keep] in self._defaultSchedules:
+                    # This is one of the default schedules so check for an
+                    # overlap with one of the dominant shchedules.
+                    for s,i,p,k in self._defaultSchedules[:idx]:
+                        last = max(last, self._last[s])
+                    idx += 1
+
+            else: # interval == "months"
+                if self._next[schedule] > last:
+                    util.debug("Short circuiting " + \
+                               schedule + \
+                               " recalculation", \
+                               self.verbose)
+                    continue
+                util.debug("Recalculating %s schedule" % (schedule), \
+                           self.verbose)
+                snap_tm = time.gmtime(self._last[schedule])
+                # Increment year if period >= than 1 calender year.
+                year = snap_tm.tm_year
+                year += period / 12
+                period = period % 12
+
+                mon = (snap_tm.tm_mon + period) % 12
+                # Result of 0 actually means december.
+                if mon == 0:
+                    mon = 12
+                # Account for period that spans calendar year boundary.
+                elif snap_tm.tm_mon + period > 12:
+                    year += 1
+
+                d,dlastmon = calendar.monthrange(snap_tm.tm_year, snap_tm.tm_mon)
+                d,dnewmon = calendar.monthrange(year, mon)
+                mday = snap_tm.tm_mday
+                if dlastmon > dnewmon and snap_tm.tm_mday > dnewmon:
+                   mday = dnewmon
+                
+                tm =(year, mon, mday, \
+                    snap_tm.tm_hour, snap_tm.tm_min, snap_tm.tm_sec, \
+                    0, 0, -1)
+                newt = calendar.timegm(tm)
+                new_tm = time.gmtime(newt)
+                totalinterval = newt - self._last[schedule]
+
+            self._next[schedule] = last + totalinterval
+
+    def _next_due(self):
+        schedule = None
+        earliest = None
+        now = long(time.time())
+        
+        for s,i,p,k in self._defaultSchedules:
+            due = self._next[s]
+            if due <= now:
+                #Default Schedule - so break out at the first 
+                #schedule that is overdue. The subordinate schedules
+                #will re-adjust afterwards.
+                earliest,schedule = due,s
+                break
+            elif earliest != None:
+                if due < earliest:
+                    earliest,schedule = due,s
+            else: #FIXME better optimisation with above condition
+                earliest,schedule = due,s
+        for s,i,p,k in self._customSchedules:
+            due = self._next[s]
+            if earliest != None:
+                if due < earliest:
+                    earliest,schedule = due,s
+            else: #FIXME better optimisation with above condition
+                earliest,schedule = due,s
+        return earliest,schedule
+
+    def _check_snapshots(self):
+        """
+        Check the schedules and see what the required snapshot is.
+        Take one immediately on the first overdue snapshot required
+        """
+        # Make sure a refresh() doesn't mess with the schedule while
+        # we're reading through it.
+        self._refreshLock.acquire()
+        next,schedule = self._next_due()
+        self._refreshLock.release()
+        now = long(time.time())
+        while next != None and next <= now:
+            label = self._take_snapshots(schedule)
+            self._plugin.execute_plugins(schedule, label)
+            self._refreshLock.acquire()
+            self._update_schedules()
+            next,schedule = self._next_due();
+            self._refreshLock.release()
+            dt = datetime.datetime.fromtimestamp(next)
+            util.debug("Next snapshot is %s due at: %s" % \
+                       (schedule, dt.isoformat()), \
+                       self.verbose)
+        return next
+                    
+    def _take_snapshots(self, schedule):
+        # Set the time before taking snapshot to avoid clock skew due
+        # to time taken to complete snapshot.
+        tm = long(time.time())
+        label = "%s%s%s-%s" % \
+                (autosnapsmf.SNAPLABELPREFIX, self._separator, schedule,
+                 datetime.datetime.now().strftime("%Y-%m-%d-%Hh%M"))
+        try:
+            self._datasets.create_auto_snapshot_set(label, tag=schedule)
+        except RuntimeError, message:
+            # Write an error message, set the exit code and pass it up the
+            # stack so the thread can terminate
+            sys.stderr.write("Failed to create snapshots for schedule: %s\n" \
+                             % (schedule))
+            self.exitCode = smf.SMF_EXIT_MON_DEGRADE
+            raise RuntimeError,message
+        self._last[schedule] = tm;
+        self._perform_purge(schedule)
+        return label
+
+    def _prune_snapshots(self, dataset, schedule):
+        """Cleans out zero sized snapshots, kind of cautiously"""
+            # Per schedule: We want to delete 0 sized
+            # snapshots but we need to keep at least one around (the most
+            # recent one) for each schedule so that that overlap is 
+            # maintained from frequent -> hourly -> daily etc.
+            # Start off with the smallest interval schedule first and
+            # move up. This increases the amount of data retained where
+            # several snapshots are taken together like a frequent hourly
+            # and daily snapshot taken at 12:00am. If 3 snapshots are all
+            # identical and reference the same identical data they will all
+            # be initially reported as zero for used size. Deleting the
+            # daily first then the hourly would shift make the data referenced
+            # by all 3 snapshots unique to the frequent scheduled snapshot.
+            # This snapshot would probably be purged within an how ever and the
+            # data referenced by it would be gone for good.
+            # Doing it the other way however ensures that the data should
+            # remain accessible to the user for at least a week as long as
+            # the pool doesn't run low on available space before that.
+
+        try:
+            snaps = dataset.list_snapshots("%s%s" % (self._prefix,schedule))
+            # Clone the list because we want to remove items from it
+            # while iterating through it.
+            remainingsnaps = snaps[:]
+        except RuntimeError,message:
+            sys.stderr.write("Failed to list snapshots during snapshot cleanup\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            raise RuntimeError,message
+
+        if (self._keepEmpties == False):
+            try: # remove the newest one from the list.
+                snaps.pop()
+            except IndexError:
+                pass
+            for snapname in snaps:
+                try:
+                    snapshot = zfs.Snapshot(snapname)
+                except Exception,message:
+                    sys.stderr.write(str(message))
+                    # Not fatal, just skip to the next snapshot
+                    continue
+
+                try:
+                    if snapshot.get_used_size() == 0:
+                        util.debug("Destroying zero sized: " + snapname, \
+                                   self.verbose)
+                        try:
+                            snapshot.destroy()
+                        except RuntimeError,message:
+                            sys.stderr.write("Failed to destroy snapshot: " +
+                                             snapname + "\n")
+                            self.exitCode = smf.SMF_EXIT_MON_DEGRADE
+                            # Propogate exception so thread can exit
+                            raise RuntimeError,message
+                        remainingsnaps.remove(snapname)
+                except RuntimeError,message:
+                    sys.stderr.write("Can not determine used size of: " + \
+                                     snapname + "\n")
+                    self.exitCode = smf.SMF_EXIT_MON_DEGRADE
+                    #Propogate the exception to the thead run() method
+                    raise RuntimeError,message
+
+        # Deleting individual snapshots instead of recursive sets
+        # breaks the recursion chain and leaves child snapshots
+        # dangling so we need to take care of cleaning up the 
+        # snapshots.
+        target = len(remainingsnaps) - self._keep[schedule]
+        counter = 0
+        while counter < target:
+            util.debug("Destroy expired snapshot: " + \
+                       remainingsnaps[counter], 
+                       self.verbose)
+            try:
+                snapshot = zfs.Snapshot(remainingsnaps[counter])
+            except Exception,message:
+                    sys.stderr.write(str(message))
+                    # Not fatal, just skip to the next snapshot
+                    counter += 1
+                    continue
+            try:
+                snapshot.destroy()
+            except RuntimeError,message:
+                sys.stderr.write("Failed to destroy snapshot: " +
+                                 snapshot.name + "\n")
+                self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                # Propogate exception so thread can exit
+                raise RuntimeError,message
+            else:
+                counter += 1
+
+    def _perform_purge(self, schedule):
+        """Cautiously cleans out zero sized snapshots"""
+        # We need to avoid accidentally pruning auto snapshots received
+        # from one zpool to another. We ensure this by examining only
+        # snapshots whose parent fileystems and volumes are explicitly
+        # tagged to be snapshotted.
+        try:
+            for name in self._datasets.list_auto_snapshot_sets(schedule):
+                dataset = zfs.ReadWritableDataset(name)
+                self._prune_snapshots(dataset, schedule)
+        except RuntimeError,message:
+            sys.stderr.write("Error listing datasets during " + \
+                             "removal of expired snapshots\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            # Propogate up to thread's run() method
+            raise RuntimeError,message
+
+    def _needs_cleanup(self):
+        if self._remedialCleanup == False:
+            # Sys admin has explicitly instructed for remedial cleanups
+            # not to be performed.
+            return False
+        now = long(time.time())
+        # Don't run checks any less than 15 minutes apart.
+        if self._cleanupLock.acquire(False) == False:
+            #Indicates that a cleanup is already running.
+            return False
+        # FIXME - Make the cleanup interval equal to the minimum snapshot interval
+        # if custom snapshot schedules are defined and enabled.
+        elif ((now - self._lastCleanupCheck) < (_MINUTE * 15)):
+            pass
+        else:
+            for zpool in self._zpools:
+                try:
+                    if zpool.get_capacity() > self._warningLevel:
+                        # Before getting into a panic, determine if the pool
+                        # is one we actually take snapshots on, by checking
+                        # for one of the "auto-snapshot:<schedule> tags. Not
+                        # super fast, but it only happens under exceptional
+                        # circumstances of a zpool nearing it's capacity.
+
+                        for sched in self._allSchedules:
+                            sets = zpool.list_auto_snapshot_sets(sched[0])
+                            if len(sets) > 0:
+                                util.debug("%s needs a cleanup" \
+                                           % zpool.name, \
+                                           self.verbose)
+                                self._cleanupLock.release()
+                                return True
+                except RuntimeError, message:
+                    sys.stderr.write("Error checking zpool capacity of: " + \
+                                     zpool.name + "\n")
+                    self._cleanupLock.release()
+                    self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                    # Propogate up to thread's run() mehod.
+                    raise RuntimeError,message
+            self._lastCleanupCheck = long(time.time())
+        self._cleanupLock.release()
+        return False
+
+    def _perform_cleanup(self):
+        if self._cleanupLock.acquire(False) == False:
+            # Cleanup already running. Skip
+            return
+        self._destroyedsnaps = []
+        for zpool in self._zpools:
+            try:
+                self._poolstatus[zpool.name] = 0
+                capacity = zpool.get_capacity()
+                if capacity > self._warningLevel:
+                    self._run_warning_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 1
+                    capacity = zpool.get_capacity()
+                if capacity > self._criticalLevel:
+                    self._run_critical_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 2
+                    capacity = zpool.get_capacity()
+                if capacity > self._emergencyLevel:
+                    self._run_emergency_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 3
+                    capacity = zpool.get_capacity()
+                if capacity > self._emergencyLevel:
+                    self._run_emergency_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 4
+            # This also catches exceptions thrown from _run_<level>_cleanup()
+            # and _run_cleanup() in methods called by _perform_cleanup()
+            except RuntimeError,message:
+                sys.stderr.write("Remedial space cleanup failed because " + \
+                                 "of failure to determinecapacity of: " + \
+                                 zpool.name + "\n")
+                self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                self._cleanupLock.release()
+                # Propogate up to thread's run() method.
+                raise RuntimeError,message
+
+            # Bad - there's no more snapshots left and nothing 
+            # left to delete. We don't disable the service since
+            # it will permit self recovery and snapshot
+            # retention when space becomes available on
+            # the pool (hopefully).
+            util.debug("%s pool status after cleanup:" \
+                       % zpool.name, \
+                       self.verbose)
+            util.debug(zpool, self.verbose)
+        util.debug("Cleanup completed. %d snapshots were destroyed" \
+                   % len(self._destroyedsnaps), \
+                   self.verbose)
+        # Avoid needless list iteration for non-debug mode
+        if self.verbose == True and len(self._destroyedsnaps) > 0:
+            for snap in self._destroyedsnaps:
+                sys.stderr.write("\t%s\n" % snap)
+        self._cleanupLock.release()
+
+    def _run_warning_cleanup(self, zpool):
+        util.debug("Performing warning level cleanup on %s" % \
+                   zpool.name, \
+                   self.verbose)
+        self._run_cleanup(zpool, "daily", self._warningLevel)
+        if zpool.get_capacity() > self._warningLevel:
+            self._run_cleanup(zpool, "hourly", self._warningLevel)
+
+    def _run_critical_cleanup(self, zpool):
+        util.debug("Performing critical level cleanup on %s" % \
+                   zpool.name, \
+                   self.verbose)
+        self._run_cleanup(zpool, "weekly", self._criticalLevel)
+        if zpool.get_capacity() > self._criticalLevel:
+            self._run_cleanup(zpool, "daily", self._criticalLevel)
+        if zpool.get_capacity() > self._criticalLevel:
+            self._run_cleanup(zpool, "hourly", self._criticalLevel)
+
+    def _run_emergency_cleanup(self, zpool):
+        util.debug("Performing emergency level cleanup on %s" % \
+                   zpool.name, \
+                   self.verbose)
+        self._run_cleanup(zpool, "monthly", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "weekly", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "daily", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "hourly", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "frequent", self._emergencyLevel)
+        #Finally, as a last resort, delete custom scheduled snaphots
+        for schedule,i,p,k in self._customSchedules:
+            if zpool.get_capacity() < self._emergencyLevel:
+                break
+            else:
+                self._run_cleanup(zpool, schedule, self._emergencyLevel)
+
+    def _run_cleanup(self, zpool, schedule, threshold):
+        clonedsnaps = []
+        snapshots = []
+        try:
+            clonedsnaps = self._datasets.list_cloned_snapshots()
+        except RuntimeError,message:
+                sys.stderr.write("Error (non-fatal) listing cloned snapshots" +
+                                 " while recovering pool capacity\n")
+                sys.stderr.write("Error details:\n" + \
+                                 "--------BEGIN ERROR MESSAGE--------\n" + \
+                                 str(message) + \
+                                 "\n--------END ERROR MESSAGE--------\n")    
+
+        # Build a list of snapshots in the given schedule, that are not
+        # cloned, and sort the result in reverse chronological order.
+        try:
+            snapshots = [s for s,t in \
+                            zpool.list_snapshots("%s%s" \
+                            % (self._prefix,schedule)) \
+                            if not s in clonedsnaps]
+            snapshots.reverse()
+        except RuntimeError,message:
+            sys.stderr.write("Error listing snapshots" +
+                             " while recovering pool capacity\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            # Propogate the error up to the thread's run() method.
+            raise RuntimeError,message
+   
+        while zpool.get_capacity() > threshold:
+            if len(snapshots) == 0:
+                syslog.syslog(syslog.LOG_NOTICE,
+                              "No more %s snapshots left" \
+                               % schedule)
+                return
+
+            """This is not an exact science. Deleteing a zero sized 
+            snapshot can have unpredictable results. For example a
+            pair of snapshots may share exclusive reference to a large
+            amount of data (eg. a large core file). The usage of both
+            snapshots will initially be seen to be 0 by zfs(1). Deleting
+            one of the snapshots will make the data become unique to the
+            single remaining snapshot that references it uniquely. The
+            remaining snapshot's size will then show up as non zero. So
+            deleting 0 sized snapshot is not as pointless as it might seem.
+            It also means we have to loop through this, each snapshot set
+            at a time and observe the before and after results. Perhaps
+            better way exists...."""
+
+            # Start with the oldest first
+            snapname = snapshots.pop()
+            snapshot = zfs.Snapshot(snapname)
+            # It would be nicer, for performance purposes, to delete sets
+            # of snapshots recursively but this might destroy more data than
+            # absolutely necessary, plus the previous purging of zero sized
+            # snapshots can easily break the recursion chain between
+            # filesystems.
+            # On the positive side there should be fewer snapshots and they
+            # will mostly non-zero so we should get more effectiveness as a
+            # result of deleting snapshots since they should be nearly always
+            # non zero sized.
+            util.debug("Destroying %s" % snapname, self.verbose)
+            try:
+                snapshot.destroy()
+            except RuntimeError,message:
+                # Would be nice to be able to mark service as degraded here
+                # but it's better to try to continue on rather than to give
+                # up alltogether (SMF maintenance state)
+                sys.stderr.write("Warning: Cleanup failed to destroy: %s\n" % \
+                                 (snapshot.name))
+                sys.stderr.write("Details:\n%s\n" % (str(message)))
+            else:
+                self._destroyedsnaps.append(snapname)
+            # Give zfs some time to recalculate.
+            time.sleep(3)
+        
+    def _send_to_syslog(self):
+        for zpool in self._zpools:
+            status = self._poolstatus[zpool.name]
+            if status == 4:
+                syslog.syslog(syslog.LOG_EMERG,
+                              "%s is over %d%% capacity. " \
+                              "All automatic snapshots were destroyed" \
+                               % (zpool.name, self._emergencyLevel))
+            elif status == 3:
+                syslog.syslog(syslog.LOG_ALERT,
+                              "%s exceeded %d%% capacity. " \
+                              "Automatic snapshots over 1 hour old were destroyed" \
+                               % (zpool.name, self._emergencyLevel))
+            elif status == 2:
+                syslog.syslog(syslog.LOG_CRIT,
+                              "%s exceeded %d%% capacity. " \
+                              "Weekly, hourly and daily automatic snapshots were destroyed" \
+                               % (zpool.name, self._criticalLevel))                             
+            elif status == 1:
+                syslog.syslog(syslog.LOG_WARNING,
+                              "%s exceeded %d%% capacity. " \
+                              "Hourly and daily automatic snapshots were destroyed" \
+                               % (zpool.name, self._warningLevel))
+
+        if len(self._destroyedsnaps) > 0:
+            syslog.syslog(syslog.LOG_NOTICE,
+                          "%d automatic snapshots were destroyed" \
+                           % len(self._destroyedsnaps))
+
+    def _send_notification(self):
+        worstpool = None
+        worststatus = 0
+
+        for zpool in self._zpools:
+            status = self._poolstatus[zpool.name]
+            # >= to ensure that something should always be set.
+            if status >= worststatus:
+                worstpool = zpool.name
+                worststatus = status
+
+        #FIXME make the various levels indexible
+        if worststatus == 4:
+            self._dbus.capacity_exceeded(worstpool, 4, self._emergencyLevel)
+        elif worststatus == 3:
+            self._dbus.capacity_exceeded(worstpool, 3, self._emergencyLevel)
+        elif worststatus == 2:
+            self._dbus.capacity_exceeded(worstpool, 2, self._criticalLevel)
+        elif worststatus == 1:
+            self._dbus.capacity_exceeded(worstpool, 1, self._warningLevel)
+        #elif: 0 everything is fine. Do nothing.
+
+
+def monitor_threads(snapthread):
+    if snapthread.is_alive():
+        return True
+    else:
+        sys.stderr.write("Snapshot monitor thread exited.\n")
+        if snapthread.exitCode == smf.SMF_EXIT_MON_DEGRADE:
+            # FIXME - it would be nicer to mark the service as degraded than
+            # go into maintenance state for some situations such as a
+            # particular snapshot schedule failing.
+            # But for now SMF does not implement this feature. But if/when it
+            # does it's better to use svcadm to put the # service into the
+            # correct state since the daemon shouldn't exit whentransitioning
+            # to a degraded state.
+            #sys.stderr.write("Placing service into maintenance state\n")
+            #subprocess.call(["/usr/sbin/svcadm", "mark", "maintenance",
+            #                 os.getenv("SMF_FMRI")])
+            # SMF will take care of kill the daemon
+            sys.exit(smf.SMF_EXIT_ERR_FATAL)
+            return False
+        elif snapthread.exitCode == smf.SMF_EXIT_ERR_FATAL:
+            #sys.stderr.write("Placing service into maintenance state\n")
+            #subprocess.call(["/usr/sbin/svcadm", "mark", "maintenance",
+            #                 os.getenv("SMF_FMRI")])
+            # SMF will take care of killing the daemon
+            sys.exit(smf.SMF_EXIT_ERR_FATAL)
+            return False
+        else:
+            sys.stderr.write("Snapshot monitor thread exited abnormally\n")
+            sys.stderr.write("Exit code: %d\n" % (snapthread.exitCode))
+            #subprocess.call(["/usr/sbin/svcadm", "mark", "maintenance",
+            #                 os.getenv("SMF_FMRI")])
+            sys.exit(smf.SMF_EXIT_ERR_FATAL)
+            return False
+
+
+def child_sig_handler(signum, frame):
+    if signum == signal.SIGUSR1:
+        sys.exit(smf.SMF_EXIT_OK)
+    elif signum == signal.SIGCHLD:
+        sys.exit(smf.SMF_EXIT_ERR_FATAL)
+    elif signum == signal.SIGALRM:
+        sys.exit(smf.SMF_EXIT_ERR_FATAL)
+
+# Default daemon parameters.
+# File mode creation mask of the daemon.
+UMASK = 0
+# Default working directory for the daemon.
+WORKDIR = "/"
+# Default maximum for the number of available file descriptors.
+MAXFD = 1024
+
+def create_daemon():
+    """
+    Detach a process from the controlling terminal and run it in the
+    background as a daemon.
+    """
+    #Catch signals that we might receive from child
+    signal.signal(signal.SIGCHLD, child_sig_handler)
+    signal.signal(signal.SIGUSR1, child_sig_handler)
+    signal.signal(signal.SIGALRM, child_sig_handler)
+    try:
+        pid = os.fork()
+    except OSError, e:
+        raise Exception, "%s [%d]" % (e.strerror, e.errno)
+
+    if (pid == 0):
+        #Reset signals that we set to trap in parent
+        signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+        signal.signal(signal.SIGUSR1, signal.SIG_DFL)
+        signal.signal(signal.SIGALRM, signal.SIG_DFL)
+        os.setsid()
+        os.chdir(WORKDIR)
+        os.umask(UMASK)
+    else:
+        #Wait for the child to give the OK or otherwise.
+        signal.pause()
+
+
+def main(argv):
+
+    # Check SMF invocation environment
+    if os.getenv("SMF_FMRI") == None or os.getenv("SMF_METHOD") != "start":
+        sys.stderr.write("Command line invocation of %s unsupported.\n" \
+                         % (sys.argv[0]))
+        sys.stderr.write("This command is intended for smf(5) invocation only.\n")
+        sys.exit(smf.SMF_EXIT_ERR_NOSMF)
+
+    # Daemonise the service.
+    create_daemon()
+
+    # The user security attributes checked are the following:
+    # Note that UID == 0 will match any profile search so
+    # no need to check it explicitly.
+    syslog.openlog("time-sliderd", 0, syslog.LOG_DAEMON)
+    rbacp = RBACprofile()
+    if rbacp.has_profile("ZFS File System Management"):
+
+        gobject.threads_init()
+
+        # Tell dbus to use the gobject mainloop for async ops
+        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+        dbus.mainloop.glib.threads_init()
+        # Register a bus name with the system dbus daemon
+        systemBus = dbus.SystemBus()
+        name = dbus.service.BusName("org.opensolaris.TimeSlider", systemBus)
+
+        # Create and start the snapshot manger. Takes care of
+        # auto snapshotting service and auto cleanup.
+        snapshot = SnapshotManager(systemBus)
+        snapshot.start()
+        gobject.timeout_add(2000, monitor_threads, snapshot)
+
+        mainloop = gobject.MainLoop()
+        try:
+            mainloop.run()
+        except KeyboardInterrupt:
+            mainloop.quit()
+            sys.exit(smf.SMF_EXIT_OK)
+    else:
+        syslog.syslog(syslog.LOG_ERR,
+               "%s has insufficient privileges to run time-sliderd!" \
+               % rbacp.name)
+        syslog.closelog()    
+        sys.exit(smf.SMF_EXIT_ERR_PERM)
+    syslog.closelog()
+    sys.exit(smf.SMF_EXIT_OK)
+
diff --git a/usr/share/time-slider/lib/time_slider/timesliderd.py~ b/usr/share/time-slider/lib/time_slider/timesliderd.py~
new file mode 100755 (executable)
index 0000000..eb2e341
--- /dev/null
@@ -0,0 +1,977 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import sys
+import os
+import subprocess
+import re
+import threading
+import getopt
+import syslog
+import time
+import datetime
+import calendar
+import signal
+
+import glib
+import gobject
+import dbus
+import dbus.service
+import dbus.mainloop
+import dbus.mainloop.glib
+
+import dbussvc
+import zfs
+import smf
+import timeslidersmf
+import autosnapsmf
+import plugin
+from rbac import RBACprofile
+import util
+
+_MINUTE = 60
+_HOUR = _MINUTE * 60
+_DAY = _HOUR * 24
+_WEEK = _DAY * 7
+
+
+# Status codes for actual zpool capacity levels.
+# These are relative to the SMF property defined
+# levels for: user, warning and emergenecy levels
+STATUS_OK = 0 # Below user specified threshhold. Everything was OK
+STATUS_WARNING = 1 # Above specified user threshold level
+STATUS_CRITICAL = 2 # Above specified critical threshhold level
+STATUS_EMERGENCY = 3 # Above specified emergency threshhold level
+
+intervals = {"weeks" : _WEEK, "days" : _DAY, "hours" : _HOUR, "minutes" : _MINUTE}
+
+
+class SnapshotManager(threading.Thread):
+
+    def __init__(self, bus):
+        # Used to wake up the run() method prematurely in the event
+        # of a SIGHUP/SMF refresh
+        self._conditionLock = threading.Condition(threading.RLock())
+        # Used when schedules are being rebuilt or examined.
+        self._refreshLock = threading.Lock()
+        # Indicates that cleanup is in progress when locked
+        self._cleanupLock = threading.Lock()
+        self._datasets = zfs.Datasets()
+        # Indicates that schedules need to be rebuilt from scratch
+        self._stale = True
+        self._lastCleanupCheck = 0;
+        self._zpools = []
+        self._poolstatus = {}
+        self._destroyedsnaps = []
+
+        # This is also checked during the refresh() method but we need
+        # to know it sooner for instantiation of the PluginManager
+        self._smf = timeslidersmf.TimeSliderSMF()
+        try:
+            self.verbose = self._smf.get_verbose()
+        except RuntimeError,message:
+            sys.stderr.write("Error determing whether debugging is enabled\n")
+            self.verbose = False
+
+        self._dbus = dbussvc.AutoSnap(bus,
+                                      '/org/opensolaris/TimeSlider/autosnap',
+                                      self)
+
+        self._plugin = plugin.PluginManager(self.verbose)
+        self.exitCode = smf.SMF_EXIT_OK
+        self.refresh()
+
+        # Seems we're up and running OK. 
+        # Signal our parent so we can daemonise
+        os.kill(os.getppid(), signal.SIGUSR1)
+
+        # SMF/svc.startd sends SIGHUP to force a
+        # a refresh of the daemon
+        signal.signal(signal.SIGHUP, self._signalled)
+
+        # Init done. Now initiaslise threading.
+        threading.Thread.__init__ (self)
+        self.setDaemon(True)
+
+    def run(self):
+        # Deselect swap and dump volumes so they don't get snapshotted.
+        for vol in self._datasets.list_volumes():
+            name = vol.rsplit("/")
+            try:
+                if (name[1] == "swap" or name[1] == "dump"):
+                    util.debug("Auto excluding %s volume" % vol, self.verbose)
+                    volume = zfs.Volume(vol)
+                    volume.set_auto_snap(False)
+            except IndexError:
+                pass
+            
+        nexttime = None
+        waittime = None
+        while True:
+            try:
+                self.refresh()
+                # First check and, if necessary, perform any remedial cleanup.
+                # This is best done before creating any new snapshots which may
+                # otherwise get immediately gobbled up by the remedial cleanup.
+                if self._needs_cleanup() == True:
+                    self._perform_cleanup()
+                    # Check to see if cleanup actually deleted anything before
+                    # notifying the user. Avoids the popup appearing continuously
+                    if len(self._destroyedsnaps) > 0:
+                        self._send_notification()
+                    self._send_to_syslog()
+
+                nexttime = self._check_snapshots()
+                # Overdue snapshots are already taken automatically
+                # inside _check_snapshots() so nexttime should never be
+                # < 0. It can be None however, which is fine since it 
+                # will cause the scheduler thread to sleep indefinitely
+                # or until a SIGHUP is caught.
+                if nexttime:
+                    util.debug("Waiting until " + str (nexttime), self.verbose)
+                waittime = None
+                if nexttime != None:
+                    waittime = nexttime - long(time.time())
+                    if (waittime <= 0):
+                        # We took too long and missed a snapshot, so break out
+                        # and catch up on it the next time through the loop
+                        continue
+                # waittime could be None if no auto-snap schedules are online
+                self._conditionLock.acquire()
+                if waittime:
+                    util.debug("Waiting %d seconds" % (waittime), self.verbose)
+                    self._conditionLock.wait(waittime)
+                else: #None. Just wait a while to check for cleanups.
+                    util.debug("No auto-snapshot schedules online.", \
+                               self.verbose)
+                    self._conditionLock.wait(_MINUTE * 15)
+
+            except OSError, message:
+                sys.stderr.write("Caught OSError exception in snapshot" +
+                                 " manager thread\n")
+                sys.stderr.write("Error details:\n" + \
+                                 "--------BEGIN ERROR MESSAGE--------\n" + \
+                                 str(message) + \
+                                 "\n--------END ERROR MESSAGE--------\n")
+                self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                # Exit this thread
+                break
+            except RuntimeError,message:
+                sys.stderr.write("Caught RuntimeError exception in snapshot" +
+                                 " manager thread\n")
+                sys.stderr.write("Error details:\n" + \
+                                 "--------BEGIN ERROR MESSAGE--------\n" + \
+                                 str(message) + \
+                                 "\n--------END ERROR MESSAGE--------\n")
+                # Exit this thread
+                break
+
+    def _signalled(self, signum, frame):
+        if signum == signal.SIGHUP:
+            if self._refreshLock.acquire(False) == False:
+                return
+            self._stale = True
+            self._refreshLock.release()
+            self._conditionLock.acquire()
+            self._conditionLock.notify()
+            self._conditionLock.release()
+
+    def refresh(self):
+        """
+        Checks if defined snapshot schedules are out
+        of date and rebuilds and updates if necessary
+        """
+        self._refreshLock.acquire()
+        if self._stale == True:
+            self._configure_svc_props()
+            self._rebuild_schedules()
+            self._update_schedules()
+            self._plugin.refresh()
+            self._stale = False
+        self._refreshLock.release()
+
+    def _configure_svc_props(self):
+        try:
+            self.verbose = self._smf.get_verbose()
+        except RuntimeError,message:
+            sys.stderr.write("Error determing whether debugging is enabled\n")
+            self.verbose = False
+
+        try:
+            cleanup = self._smf.get_remedial_cleanup()
+            warn = self._smf.get_cleanup_level("warning")
+            util.debug("Warning level value is:   %d%%" % warn, self.verbose)
+            crit = self._smf.get_cleanup_level("critical")
+            util.debug("Critical level value is:  %d%%" % crit, self.verbose)
+            emer = self._smf.get_cleanup_level("emergency")
+            util.debug("Emergency level value is: %d%%" % emer, self.verbose)
+        except RuntimeError,message:
+            sys.stderr.write("Failed to determine cleanup threshhold levels\n")
+            sys.stderr.write("Details:\n" + \
+                             "--------BEGIN ERROR MESSAGE--------\n" + \
+                             str(message) + \
+                             "\n---------END ERROR MESSAGE---------\n")
+            sys.stderr.write("Using factory defaults of 80%, 90% and 95%\n")
+            #Go with defaults
+            #FIXME - this would be an appropriate case to mark svc as degraded
+            self._remedialCleanup = True
+            self._warningLevel = 80
+            self._criticalLevel = 90
+            self._emergencyLevel = 95
+        else:
+            self._remedialCleanup = cleanup
+            self._warningLevel = warn
+            self._criticalLevel = crit
+            self._emergencyLevel = emer
+
+        try:
+            self._keepEmpties = self._smf.get_keep_empties()
+        except RuntimeError,message:
+            # Not fatal, just assume we delete them (default configuration)
+            sys.stderr.write("Can't determine whether to keep empty snapshots\n")
+            sys.stderr.write("Details:\n" + \
+                             "--------BEGIN ERROR MESSAGE--------\n" + \
+                             str(message) + \
+                             "\n---------END ERROR MESSAGE---------\n")
+            sys.stderr.write("Assuming default value: False\n")
+            self._keepEmpties = False
+
+        # Previously, snapshot labels used the ":" character was used as a 
+        # separator character for datestamps. Windows filesystems such as
+        # CIFS and FAT choke on this character so now we use a user definable
+        # separator value, with a default value of "_"
+        # We need to check for both the old and new format when looking for
+        # snapshots.
+        self._separator = self._smf.get_separator()
+        self._prefix = "%s[:%s]" \
+            % (autosnapsmf.SNAPLABELPREFIX, self._separator)
+
+        # Rebuild pool list
+        self._zpools = []
+        try:
+            for poolname in zfs.list_zpools():
+                # Do not try to examine FAULTED pools
+                zpool = zfs.ZPool(poolname)
+                if zpool.health == "FAULTED":
+                    util.debug("Ignoring faulted Zpool: %s\n" \
+                               % (zpool.name), \
+                               self.verbose)
+                else:
+                    self._zpools.append(zpool)
+                util.debug(str(zpool), self.verbose)
+        except RuntimeError,message:
+            sys.stderr.write("Could not list Zpools\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            # Propogate exception up to thread's run() method
+            raise RuntimeError,message
+
+
+    def _rebuild_schedules(self):
+        """
+        Builds 2 lists of default and custom auto-snapshot SMF instances
+        """
+
+        self._last = {}
+        self._next = {}
+        self._keep = {}
+
+        try:
+            _defaultSchedules = autosnapsmf.get_default_schedules()
+            _customSchedules = autosnapsmf.get_custom_schedules()
+        except RuntimeError,message:
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            raise RuntimeError, "Error reading SMF schedule instances\n" + \
+                                "Details:\n" + str(message)
+        else:
+            # Now set it in stone.
+            self._defaultSchedules = tuple(_defaultSchedules)
+            self._customSchedules = tuple(_customSchedules)
+            
+            # Build the combined schedule tuple from default + custom schedules
+            _defaultSchedules.extend(_customSchedules)
+            self._allSchedules = tuple(_defaultSchedules)
+            for schedule,i,p,keep in self._allSchedules:
+                self._last[schedule] = 0
+                self._next[schedule] = 0
+                self._keep[schedule] = keep
+
+    def _update_schedules(self):
+        interval = 0
+        idx = 1 # Used to index subsets for schedule overlap calculation
+        last = None
+
+        for schedule,interval,period,keep in self._allSchedules:
+            # Shortcut if we've already processed this schedule and it's 
+            # still up to date. Don't skip the default schedules though
+            # because overlap affects their scheduling
+            if [schedule,interval,period,keep] not in \
+                self._defaultSchedules and \
+                (self._next[schedule] > self._last[schedule]):
+                util.debug("Short circuiting %s recalculation" \
+                           % (schedule), \
+                           self.verbose)
+                continue
+
+            # If we don't have an internal timestamp for the given schedule
+            # ask zfs for the last snapshot and get it's creation timestamp.
+            if self._last[schedule] == 0:
+                try:
+                    snaps = self._datasets.list_snapshots("%s%s" % \
+                                                         (self._prefix,
+                                                          schedule))
+                except RuntimeError,message:
+                    self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                    sys.stderr.write("Failed to list snapshots during schedule update\n")
+                    #Propogate up to the thread's run() method
+                    raise RuntimeError,message
+
+                if len(snaps) > 0:
+                    util.debug("Last %s snapshot was: %s" % \
+                               (schedule, snaps[-1][0]), \
+                               self.verbose)
+                    self._last[schedule] = snaps[-1][1]
+
+            last = self._last[schedule]
+            if interval != "months": # months is non-constant. See below.
+                util.debug("Recalculating %s schedule" % (schedule), \
+                           self.verbose)
+                try:
+                    totalinterval = intervals[interval] * period
+                except KeyError:
+                    self.exitCode = smf.SMF_EXIT_ERR_CONFIG
+                    sys.stderr.write(schedule + \
+                                      " schedule has invalid interval: " + \
+                                      "'%s\'\n" % interval)
+                    #Propogate up to thread's run() method
+                    raise RuntimeError
+                if [schedule,interval,period,keep] in self._defaultSchedules:
+                    # This is one of the default schedules so check for an
+                    # overlap with one of the dominant shchedules.
+                    for s,i,p,k in self._defaultSchedules[:idx]:
+                        last = max(last, self._last[s])
+                    idx += 1
+
+            else: # interval == "months"
+                if self._next[schedule] > last:
+                    util.debug("Short circuiting " + \
+                               schedule + \
+                               " recalculation", \
+                               self.verbose)
+                    continue
+                util.debug("Recalculating %s schedule" % (schedule), \
+                           self.verbose)
+                snap_tm = time.gmtime(self._last[schedule])
+                # Increment year if period >= than 1 calender year.
+                year = snap_tm.tm_year
+                year += period / 12
+                period = period % 12
+
+                mon = (snap_tm.tm_mon + period) % 12
+                # Result of 0 actually means december.
+                if mon == 0:
+                    mon = 12
+                # Account for period that spans calendar year boundary.
+                elif snap_tm.tm_mon + period > 12:
+                    year += 1
+
+                d,dlastmon = calendar.monthrange(snap_tm.tm_year, snap_tm.tm_mon)
+                d,dnewmon = calendar.monthrange(year, mon)
+                mday = snap_tm.tm_mday
+                if dlastmon > dnewmon and snap_tm.tm_mday > dnewmon:
+                   mday = dnewmon
+                
+                tm =(year, mon, mday, \
+                    snap_tm.tm_hour, snap_tm.tm_min, snap_tm.tm_sec, \
+                    0, 0, -1)
+                newt = calendar.timegm(tm)
+                new_tm = time.gmtime(newt)
+                totalinterval = newt - self._last[schedule]
+
+            self._next[schedule] = last + totalinterval
+
+    def _next_due(self):
+        schedule = None
+        earliest = None
+        now = long(time.time())
+        
+        for s,i,p,k in self._defaultSchedules:
+            due = self._next[s]
+            if due <= now:
+                #Default Schedule - so break out at the first 
+                #schedule that is overdue. The subordinate schedules
+                #will re-adjust afterwards.
+                earliest,schedule = due,s
+                break
+            elif earliest != None:
+                if due < earliest:
+                    earliest,schedule = due,s
+            else: #FIXME better optimisation with above condition
+                earliest,schedule = due,s
+        for s,i,p,k in self._customSchedules:
+            due = self._next[s]
+            if earliest != None:
+                if due < earliest:
+                    earliest,schedule = due,s
+            else: #FIXME better optimisation with above condition
+                earliest,schedule = due,s
+        return earliest,schedule
+
+    def _check_snapshots(self):
+        """
+        Check the schedules and see what the required snapshot is.
+        Take one immediately on the first overdue snapshot required
+        """
+        # Make sure a refresh() doesn't mess with the schedule while
+        # we're reading through it.
+        self._refreshLock.acquire()
+        next,schedule = self._next_due()
+        self._refreshLock.release()
+        now = long(time.time())
+        while next != None and next <= now:
+            label = self._take_snapshots(schedule)
+            self._plugin.execute_plugins(schedule, label)
+            self._refreshLock.acquire()
+            self._update_schedules()
+            next,schedule = self._next_due();
+            self._refreshLock.release()
+            dt = datetime.datetime.fromtimestamp(next)
+            util.debug("Next snapshot is %s due at: %s" % \
+                       (schedule, dt.isoformat()), \
+                       self.verbose)
+        return next
+                    
+    def _take_snapshots(self, schedule):
+        # Set the time before taking snapshot to avoid clock skew due
+        # to time taken to complete snapshot.
+        tm = long(time.time())
+        label = "%s%s%s-%s" % \
+                (autosnapsmf.SNAPLABELPREFIX, self._separator, schedule,
+                 datetime.datetime.now().strftime("%Y-%m-%d-%Hh%M"))
+        try:
+            self._datasets.create_auto_snapshot_set(label, tag=schedule)
+        except RuntimeError, message:
+            # Write an error message, set the exit code and pass it up the
+            # stack so the thread can terminate
+            sys.stderr.write("Failed to create snapshots for schedule: %s\n" \
+                             % (schedule))
+            self.exitCode = smf.SMF_EXIT_MON_DEGRADE
+            raise RuntimeError,message
+        self._last[schedule] = tm;
+        self._perform_purge(schedule)
+        return label
+
+    def _prune_snapshots(self, dataset, schedule):
+        """Cleans out zero sized snapshots, kind of cautiously"""
+            # Per schedule: We want to delete 0 sized
+            # snapshots but we need to keep at least one around (the most
+            # recent one) for each schedule so that that overlap is 
+            # maintained from frequent -> hourly -> daily etc.
+            # Start off with the smallest interval schedule first and
+            # move up. This increases the amount of data retained where
+            # several snapshots are taken together like a frequent hourly
+            # and daily snapshot taken at 12:00am. If 3 snapshots are all
+            # identical and reference the same identical data they will all
+            # be initially reported as zero for used size. Deleting the
+            # daily first then the hourly would shift make the data referenced
+            # by all 3 snapshots unique to the frequent scheduled snapshot.
+            # This snapshot would probably be purged within an how ever and the
+            # data referenced by it would be gone for good.
+            # Doing it the other way however ensures that the data should
+            # remain accessible to the user for at least a week as long as
+            # the pool doesn't run low on available space before that.
+
+        try:
+            snaps = dataset.list_snapshots("%s%s" % (self._prefix,schedule))
+            # Clone the list because we want to remove items from it
+            # while iterating through it.
+            remainingsnaps = snaps[:]
+        except RuntimeError,message:
+            sys.stderr.write("Failed to list snapshots during snapshot cleanup\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            raise RuntimeError,message
+
+        if (self._keepEmpties == False):
+            try: # remove the newest one from the list.
+                snaps.pop()
+            except IndexError:
+                pass
+            for snapname in snaps:
+                try:
+                    snapshot = zfs.Snapshot(snapname)
+                except Exception,message:
+                    sys.stderr.write(str(message))
+                    # Not fatal, just skip to the next snapshot
+                    continue
+
+                try:
+                    if snapshot.get_used_size() == 0:
+                        util.debug("Destroying zero sized: " + snapname, \
+                                   self.verbose)
+                        try:
+                            snapshot.destroy()
+                        except RuntimeError,message:
+                            sys.stderr.write("Failed to destroy snapshot: " +
+                                             snapname + "\n")
+                            self.exitCode = smf.SMF_EXIT_MON_DEGRADE
+                            # Propogate exception so thread can exit
+                            raise RuntimeError,message
+                        remainingsnaps.remove(snapname)
+                except RuntimeError,message:
+                    sys.stderr.write("Can not determine used size of: " + \
+                                     snapname + "\n")
+                    self.exitCode = smf.SMF_EXIT_MON_DEGRADE
+                    #Propogate the exception to the thead run() method
+                    raise RuntimeError,message
+
+        # Deleting individual snapshots instead of recursive sets
+        # breaks the recursion chain and leaves child snapshots
+        # dangling so we need to take care of cleaning up the 
+        # snapshots.
+        target = len(remainingsnaps) - self._keep[schedule]
+        counter = 0
+        while counter < target:
+            util.debug("Destroy expired snapshot: " + \
+                       remainingsnaps[counter], 
+                       self.verbose)
+            try:
+                snapshot = zfs.Snapshot(remainingsnaps[counter])
+            except Exception,message:
+                    sys.stderr.write(str(message))
+                    # Not fatal, just skip to the next snapshot
+                    counter += 1
+                    continue
+            try:
+                snapshot.destroy()
+            except RuntimeError,message:
+                sys.stderr.write("Failed to destroy snapshot: " +
+                                 snapshot.name + "\n")
+                self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                # Propogate exception so thread can exit
+                raise RuntimeError,message
+            else:
+                counter += 1
+
+    def _perform_purge(self, schedule):
+        """Cautiously cleans out zero sized snapshots"""
+        # We need to avoid accidentally pruning auto snapshots received
+        # from one zpool to another. We ensure this by examining only
+        # snapshots whose parent fileystems and volumes are explicitly
+        # tagged to be snapshotted.
+        try:
+            for name in self._datasets.list_auto_snapshot_sets(schedule):
+                dataset = zfs.ReadWritableDataset(name)
+                self._prune_snapshots(dataset, schedule)
+        except RuntimeError,message:
+            sys.stderr.write("Error listing datasets during " + \
+                             "removal of expired snapshots\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            # Propogate up to thread's run() method
+            raise RuntimeError,message
+
+    def _needs_cleanup(self):
+        if self._remedialCleanup == False:
+            # Sys admin has explicitly instructed for remedial cleanups
+            # not to be performed.
+            return False
+        now = long(time.time())
+        # Don't run checks any less than 15 minutes apart.
+        if self._cleanupLock.acquire(False) == False:
+            #Indicates that a cleanup is already running.
+            return False
+        # FIXME - Make the cleanup interval equal to the minimum snapshot interval
+        # if custom snapshot schedules are defined and enabled.
+        elif ((now - self._lastCleanupCheck) < (_MINUTE * 15)):
+            pass
+        else:
+            for zpool in self._zpools:
+                try:
+                    if zpool.get_capacity() > self._warningLevel:
+                        # Before getting into a panic, determine if the pool
+                        # is one we actually take snapshots on, by checking
+                        # for one of the "auto-snapshot:<schedule> tags. Not
+                        # super fast, but it only happens under exceptional
+                        # circumstances of a zpool nearing it's capacity.
+
+                        for sched in self._allSchedules:
+                            sets = zpool.list_auto_snapshot_sets(sched[0])
+                            if len(sets) > 0:
+                                util.debug("%s needs a cleanup" \
+                                           % zpool.name, \
+                                           self.verbose)
+                                self._cleanupLock.release()
+                                return True
+                except RuntimeError, message:
+                    sys.stderr.write("Error checking zpool capacity of: " + \
+                                     zpool.name + "\n")
+                    self._cleanupLock.release()
+                    self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                    # Propogate up to thread's run() mehod.
+                    raise RuntimeError,message
+            self._lastCleanupCheck = long(time.time())
+        self._cleanupLock.release()
+        return False
+
+    def _perform_cleanup(self):
+        if self._cleanupLock.acquire(False) == False:
+            # Cleanup already running. Skip
+            return
+        self._destroyedsnaps = []
+        for zpool in self._zpools:
+            try:
+                self._poolstatus[zpool.name] = 0
+                capacity = zpool.get_capacity()
+                if capacity > self._warningLevel:
+                    self._run_warning_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 1
+                    capacity = zpool.get_capacity()
+                if capacity > self._criticalLevel:
+                    self._run_critical_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 2
+                    capacity = zpool.get_capacity()
+                if capacity > self._emergencyLevel:
+                    self._run_emergency_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 3
+                    capacity = zpool.get_capacity()
+                if capacity > self._emergencyLevel:
+                    self._run_emergency_cleanup(zpool)
+                    self._poolstatus[zpool.name] = 4
+            # This also catches exceptions thrown from _run_<level>_cleanup()
+            # and _run_cleanup() in methods called by _perform_cleanup()
+            except RuntimeError,message:
+                sys.stderr.write("Remedial space cleanup failed because " + \
+                                 "of failure to determinecapacity of: " + \
+                                 zpool.name + "\n")
+                self.exitCode = smf.SMF_EXIT_ERR_FATAL
+                self._cleanupLock.release()
+                # Propogate up to thread's run() method.
+                raise RuntimeError,message
+
+            # Bad - there's no more snapshots left and nothing 
+            # left to delete. We don't disable the service since
+            # it will permit self recovery and snapshot
+            # retention when space becomes available on
+            # the pool (hopefully).
+            util.debug("%s pool status after cleanup:" \
+                       % zpool.name, \
+                       self.verbose)
+            util.debug(zpool, self.verbose)
+        util.debug("Cleanup completed. %d snapshots were destroyed" \
+                   % len(self._destroyedsnaps), \
+                   self.verbose)
+        # Avoid needless list iteration for non-debug mode
+        if self.verbose == True and len(self._destroyedsnaps) > 0:
+            for snap in self._destroyedsnaps:
+                sys.stderr.write("\t%s\n" % snap)
+        self._cleanupLock.release()
+
+    def _run_warning_cleanup(self, zpool):
+        util.debug("Performing warning level cleanup on %s" % \
+                   zpool.name, \
+                   self.verbose)
+        self._run_cleanup(zpool, "daily", self._warningLevel)
+        if zpool.get_capacity() > self._warningLevel:
+            self._run_cleanup(zpool, "hourly", self._warningLevel)
+
+    def _run_critical_cleanup(self, zpool):
+        util.debug("Performing critical level cleanup on %s" % \
+                   zpool.name, \
+                   self.verbose)
+        self._run_cleanup(zpool, "weekly", self._criticalLevel)
+        if zpool.get_capacity() > self._criticalLevel:
+            self._run_cleanup(zpool, "daily", self._criticalLevel)
+        if zpool.get_capacity() > self._criticalLevel:
+            self._run_cleanup(zpool, "hourly", self._criticalLevel)
+
+    def _run_emergency_cleanup(self, zpool):
+        util.debug("Performing emergency level cleanup on %s" % \
+                   zpool.name, \
+                   self.verbose)
+        self._run_cleanup(zpool, "monthly", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "weekly", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "daily", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "hourly", self._emergencyLevel)
+        if zpool.get_capacity() > self._emergencyLevel:
+            self._run_cleanup(zpool, "frequent", self._emergencyLevel)
+        #Finally, as a last resort, delete custom scheduled snaphots
+        for schedule,i,p,k in self._customSchedules:
+            if zpool.get_capacity() < self._emergencyLevel:
+                break
+            else:
+                self._run_cleanup(zpool, schedule, self._emergencyLevel)
+
+    def _run_cleanup(self, zpool, schedule, threshold):
+        clonedsnaps = []
+        snapshots = []
+        try:
+            clonedsnaps = self._datasets.list_cloned_snapshots()
+        except RuntimeError,message:
+                sys.stderr.write("Error (non-fatal) listing cloned snapshots" +
+                                 " while recovering pool capacity\n")
+                sys.stderr.write("Error details:\n" + \
+                                 "--------BEGIN ERROR MESSAGE--------\n" + \
+                                 str(message) + \
+                                 "\n--------END ERROR MESSAGE--------\n")    
+
+        # Build a list of snapshots in the given schedule, that are not
+        # cloned, and sort the result in reverse chronological order.
+        try:
+            snapshots = [s for s,t in \
+                            zpool.list_snapshots("%s%s" \
+                            % (self._prefix,schedule)) \
+                            if not s in clonedsnaps]
+            snapshots.reverse()
+        except RuntimeError,message:
+            sys.stderr.write("Error listing snapshots" +
+                             " while recovering pool capacity\n")
+            self.exitCode = smf.SMF_EXIT_ERR_FATAL
+            # Propogate the error up to the thread's run() method.
+            raise RuntimeError,message
+   
+        while zpool.get_capacity() > threshold:
+            if len(snapshots) == 0:
+                syslog.syslog(syslog.LOG_NOTICE,
+                              "No more %s snapshots left" \
+                               % schedule)
+                return
+
+            """This is not an exact science. Deleteing a zero sized 
+            snapshot can have unpredictable results. For example a
+            pair of snapshots may share exclusive reference to a large
+            amount of data (eg. a large core file). The usage of both
+            snapshots will initially be seen to be 0 by zfs(1). Deleting
+            one of the snapshots will make the data become unique to the
+            single remaining snapshot that references it uniquely. The
+            remaining snapshot's size will then show up as non zero. So
+            deleting 0 sized snapshot is not as pointless as it might seem.
+            It also means we have to loop through this, each snapshot set
+            at a time and observe the before and after results. Perhaps
+            better way exists...."""
+
+            # Start with the oldest first
+            snapname = snapshots.pop()
+            snapshot = zfs.Snapshot(snapname)
+            # It would be nicer, for performance purposes, to delete sets
+            # of snapshots recursively but this might destroy more data than
+            # absolutely necessary, plus the previous purging of zero sized
+            # snapshots can easily break the recursion chain between
+            # filesystems.
+            # On the positive side there should be fewer snapshots and they
+            # will mostly non-zero so we should get more effectiveness as a
+            # result of deleting snapshots since they should be nearly always
+            # non zero sized.
+            util.debug("Destroying %s" % snapname, self.verbose)
+            try:
+                snapshot.destroy()
+            except RuntimeError,message:
+                # Would be nice to be able to mark service as degraded here
+                # but it's better to try to continue on rather than to give
+                # up alltogether (SMF maintenance state)
+                sys.stderr.write("Warning: Cleanup failed to destroy: %s\n" % \
+                                 (snapshot.name))
+                sys.stderr.write("Details:\n%s\n" % (str(message)))
+            else:
+                self._destroyedsnaps.append(snapname)
+            # Give zfs some time to recalculate.
+            time.sleep(3)
+        
+    def _send_to_syslog(self):
+        for zpool in self._zpools:
+            status = self._poolstatus[zpool.name]
+            if status == 4:
+                syslog.syslog(syslog.LOG_EMERG,
+                              "%s is over %d%% capacity. " \
+                              "All automatic snapshots were destroyed" \
+                               % (zpool.name, self._emergencyLevel))
+            elif status == 3:
+                syslog.syslog(syslog.LOG_ALERT,
+                              "%s exceeded %d%% capacity. " \
+                              "Automatic snapshots over 1 hour old were destroyed" \
+                               % (zpool.name, self._emergencyLevel))
+            elif status == 2:
+                syslog.syslog(syslog.LOG_CRIT,
+                              "%s exceeded %d%% capacity. " \
+                              "Weekly, hourly and daily automatic snapshots were destroyed" \
+                               % (zpool.name, self._criticalLevel))                             
+            elif status == 1:
+                syslog.syslog(syslog.LOG_WARNING,
+                              "%s exceeded %d%% capacity. " \
+                              "Hourly and daily automatic snapshots were destroyed" \
+                               % (zpool.name, self._warningLevel))
+
+        if len(self._destroyedsnaps) > 0:
+            syslog.syslog(syslog.LOG_NOTICE,
+                          "%d automatic snapshots were destroyed" \
+                           % len(self._destroyedsnaps))
+
+    def _send_notification(self):
+        worstpool = None
+        worststatus = 0
+
+        for zpool in self._zpools:
+            status = self._poolstatus[zpool.name]
+            # >= to ensure that something should always be set.
+            if status >= worststatus:
+                worstpool = zpool.name
+                worststatus = status
+
+        #FIXME make the various levels indexible
+        if worststatus == 4:
+            self._dbus.capacity_exceeded(worstpool, 4, self._emergencyLevel)
+        elif worststatus == 3:
+            self._dbus.capacity_exceeded(worstpool, 3, self._emergencyLevel)
+        elif worststatus == 2:
+            self._dbus.capacity_exceeded(worstpool, 2, self._criticalLevel)
+        elif worststatus == 1:
+            self._dbus.capacity_exceeded(worstpool, 1, self._warningLevel)
+        #elif: 0 everything is fine. Do nothing.
+
+
+def monitor_threads(snapthread):
+    if snapthread.is_alive():
+        return True
+    else:
+        sys.stderr.write("Snapshot monitor thread exited.\n")
+        if snapthread.exitCode == smf.SMF_EXIT_MON_DEGRADE:
+            # FIXME - it would be nicer to mark the service as degraded than
+            # go into maintenance state for some situations such as a
+            # particular snapshot schedule failing.
+            # But for now SMF does not implement this feature. But if/when it
+            # does it's better to use svcadm to put the # service into the
+            # correct state since the daemon shouldn't exit whentransitioning
+            # to a degraded state.
+            #sys.stderr.write("Placing service into maintenance state\n")
+            #subprocess.call(["/usr/sbin/svcadm", "mark", "maintenance",
+            #                 os.getenv("SMF_FMRI")])
+            # SMF will take care of kill the daemon
+            sys.exit(smf.SMF_EXIT_ERR_FATAL)
+            return False
+        elif snapthread.exitCode == smf.SMF_EXIT_ERR_FATAL:
+            #sys.stderr.write("Placing service into maintenance state\n")
+            #subprocess.call(["/usr/sbin/svcadm", "mark", "maintenance",
+            #                 os.getenv("SMF_FMRI")])
+            # SMF will take care of killing the daemon
+            sys.exit(smf.SMF_EXIT_ERR_FATAL)
+            return False
+        else:
+            sys.stderr.write("Snapshot monitor thread exited abnormally\n")
+            sys.stderr.write("Exit code: %d\n" % (snapthread.exitCode))
+            #subprocess.call(["/usr/sbin/svcadm", "mark", "maintenance",
+            #                 os.getenv("SMF_FMRI")])
+            sys.exit(smf.SMF_EXIT_ERR_FATAL)
+            return False
+
+
+def child_sig_handler(signum, frame):
+    if signum == signal.SIGUSR1:
+        sys.exit(smf.SMF_EXIT_OK)
+    elif signum == signal.SIGCHLD:
+        sys.exit(smf.SMF_EXIT_ERR_FATAL)
+    elif signum == signal.SIGALRM:
+        sys.exit(smf.SMF_EXIT_ERR_FATAL)
+
+# Default daemon parameters.
+# File mode creation mask of the daemon.
+UMASK = 0
+# Default working directory for the daemon.
+WORKDIR = "/"
+# Default maximum for the number of available file descriptors.
+MAXFD = 1024
+
+def create_daemon():
+    """
+    Detach a process from the controlling terminal and run it in the
+    background as a daemon.
+    """
+    #Catch signals that we might receive from child
+    signal.signal(signal.SIGCHLD, child_sig_handler)
+    signal.signal(signal.SIGUSR1, child_sig_handler)
+    signal.signal(signal.SIGALRM, child_sig_handler)
+    try:
+        pid = os.fork()
+    except OSError, e:
+        raise Exception, "%s [%d]" % (e.strerror, e.errno)
+
+    if (pid == 0):
+        #Reset signals that we set to trap in parent
+        signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+        signal.signal(signal.SIGUSR1, signal.SIG_DFL)
+        signal.signal(signal.SIGALRM, signal.SIG_DFL)
+        os.setsid()
+        os.chdir(WORKDIR)
+        os.umask(UMASK)
+    else:
+        #Wait for the child to give the OK or otherwise.
+        signal.pause()
+
+
+def main(argv):
+
+    # Check SMF invocation environment
+    if os.getenv("SMF_FMRI") == None or os.getenv("SMF_METHOD") != "start":
+        sys.stderr.write("Command line invocation of %s unsupported.\n" \
+                         % (sys.argv[0]))
+        sys.stderr.write("This command is intended for smf(5) invocation only.\n")
+        sys.exit(smf.SMF_EXIT_ERR_NOSMF)
+
+    # Daemonise the service.
+    create_daemon()
+
+    # The user security attributes checked are the following:
+    # Note that UID == 0 will match any profile search so
+    # no need to check it explicitly.
+    syslog.openlog("time-sliderd", 0, syslog.LOG_DAEMON)
+    rbacp = RBACprofile()
+    if rbacp.has_profile("ZFS File System Management"):
+
+        gobject.threads_init()
+
+        # Tell dbus to use the gobject mainloop for async ops
+        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+        dbus.mainloop.glib.threads_init()
+        # Register a bus name with the system dbus daemon
+        systemBus = dbus.SystemBus()
+        name = dbus.service.BusName("org.opensolaris.TimeSlider", systemBus)
+
+        # Create and start the snapshot manger. Takes care of
+        # auto snapshotting service and auto cleanup.
+        snapshot = SnapshotManager(systemBus)
+        snapshot.start()
+        gobject.timeout_add(2000, monitor_threads, snapshot)
+
+        mainloop = gobject.MainLoop()
+        try:
+            mainloop.run()
+        except KeyboardInterrupt:
+            mainloop.quit()
+            sys.exit(smf.SMF_EXIT_OK)
+    else:
+        syslog.syslog(syslog.LOG_ERR,
+               "%s has insufficient privileges to run time-sliderd!" \
+               % rbacp.name)
+        syslog.closelog()    
+        sys.exit(smf.SMF_EXIT_ERR_PERM)
+    syslog.closelog()
+    sys.exit(smf.SMF_EXIT_OK)
+
diff --git a/usr/share/time-slider/lib/time_slider/timeslidersmf.py b/usr/share/time-slider/lib/time_slider/timeslidersmf.py
new file mode 100755 (executable)
index 0000000..6a50761
--- /dev/null
@@ -0,0 +1,154 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import subprocess
+import threading
+import smf
+import util
+
+#SMF EXIT CODES
+SMF_EXIT_OK          = 0
+SMF_EXIT_ERR_FATAL   = 95
+SMF_EXIT_ERR_CONFIG  = 96
+SMF_EXIT_MON_DEGRADE = 97
+SMF_EXIT_MON_OFFLINE = 98
+SMF_EXIT_ERR_NOSMF   = 99
+SMF_EXIT_ERR_PERM    = 100
+#SMF_EXIT_ERR_OTHER = non-zero
+
+cleanupTypes = ("warning", "critical", "emergency")
+
+SMFNAME = 'svc:/application/time-slider'
+ZFSPROPGROUP = "zfs"
+ZPOOLPROPGROUP = "zpool"
+DAEMONPROPGROUP = "daemon"
+
+# Commonly used command paths
+PFCMD = "/usr/bin/pfexec"
+SVCSCMD = "/usr/bin/svcs"
+SVCADMCMD = "/usr/sbin/svcadm"
+SVCCFGCMD = "/usr/sbin/svccfg"
+SVCPROPCMD = "/usr/bin/svcprop"
+
+
+class TimeSliderSMF(smf.SMFInstance):
+
+    def __init__(self, instanceName = SMFNAME):
+        smf.SMFInstance.__init__(self, instanceName)
+        self._cleanupLevels = {}
+        self._cleanupLevelsLock = threading.Lock()
+
+    def get_keep_empties(self):
+        if self.get_prop(ZFSPROPGROUP, "keep-empties") == "true":
+            return True
+        else:
+            return False
+
+    def is_custom_selection(self):
+        value = self.get_prop(ZFSPROPGROUP, "custom-selection")
+        if value == "true":
+            return True
+        else:
+            return False
+
+    def get_separator(self):
+        result = self.get_prop(ZFSPROPGROUP, "sep")
+        if len(result) != 1:
+            raise ValueError("zfs/sep must be a single character length")
+        return result
+
+    def get_remedial_cleanup(self):
+        value = self.get_prop(ZPOOLPROPGROUP, "remedial-cleanup")
+        if value == "false":
+            return False
+        else:
+            return True
+
+    def get_cleanup_level(self, cleanupType):
+        if cleanupType not in cleanupTypes:
+            raise ValueError("\'%s\' is not a valid cleanup type" % \
+                           (cleanupType))
+        self._cleanupLevelsLock.acquire()
+        value = self.get_prop(ZPOOLPROPGROUP, "%s-level" % (cleanupType))
+        self._cleanupLevelsLock.release()
+        return int(value)
+
+    def set_cleanup_level(self, cleanupType, level):
+        if cleanupType not in cleanupTypes:
+            raise ValueError("\'%s\' is not a valid cleanup type" % \
+                           (cleanupType))
+        if level < 0:
+            raise ValueError("Cleanup level value can not not be negative")
+        if cleanupType == "warning" and \
+            level > self.get_cleanup_level("critical"):
+            raise ValueError("Warning cleanup level value can not exceed " + \
+                             "critical cleanup level value")
+        elif cleanupType == "critical" and \
+            level > self.get_cleanup_level("emergency"):
+            raise ValueError("Critical cleanup level value can not " + \
+                             "exceed emergency cleanup level value")
+        elif level > 100: # Emergency type value
+            raise ValueError("Cleanup level value can not exceed 100")
+
+        self._cleanupLevelsLock.acquire()
+        propname = "%s-level" % (cleanupType)
+        self.set_integer_prop(ZPOOLPROPGROUP, propname, level)
+        self._cleanupLevels[cleanupType] = level
+        self._cleanupLevelsLock.release()
+        self.refresh_service()
+
+    def set_custom_selection(self, value):
+        self.set_boolean_prop(ZFSPROPGROUP, "custom-selection", value)
+        self.refresh_service()
+
+    def get_verbose(self):
+        value = self.get_prop(DAEMONPROPGROUP, "verbose")
+        if value == "true":
+            return True
+        else:
+            return False
+
+    def __eq__(self, other):
+        if self.fs_name == other.fs_name and \
+           self.interval == other.interval and \
+           self.period == other.period:
+            return True
+        return False
+       
+    def __str__(self):
+        ret = "SMF Instance:\n" +\
+              "\tName:\t\t\t%s\n" % (self.instanceName) +\
+              "\tState:\t\t\t%s\n" % (self.svcstate) + \
+              "\tVerbose:\t\t%s\n" % str(self.get_verbose()) + \
+              "\tCustom Selction:\t%s\n" % str(self.is_custom_selection()) +\
+              "\tKeep Empties:\t\t%s\n" % str(self.get_keep_empties()) +\
+              "\tWarning Level:\t\t%d\n" % (self.get_cleanup_level("warning")) + \
+              "\tCritical Level:\t\t%d\n" % (self.get_cleanup_level("critical")) + \
+              "\tEmergency Level:\t%d\n" % (self.get_cleanup_level("emergency")) + \
+              "\tSeparator Char:\t\t\'%s\'" % (self.get_separator())
+        return ret
+
+
+if __name__ == "__main__":
+  S = TimeSliderSMF('svc:/application/time-slider')
+  print S
+
diff --git a/usr/share/time-slider/lib/time_slider/tmp.py b/usr/share/time-slider/lib/time_slider/tmp.py
new file mode 100755 (executable)
index 0000000..4072f3b
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/python2.6
+import os
+
+backupDirs = []
+
+for root, dirs, files in os.walk("/ts-test/TIMESLIDER/nanmbp"):
+    if '.time-slider' in dirs:
+#        dirs.remove('.time-slider')
+        backupDirs.append(os.path.join(root, ".time-slider/rsync"))
+       print "root %s" % root
+       s1 = root.split ("/ts-test/TIMESLIDER/nanmbp/", 1)
+       print s1
+
+for dirName in backupDirs:
+    print "dirName %s " % dirName
+    s1 = dirName.split ("/ts-test/TIMESLIDER/nanmbp/",1)
+    s2 = s1[1].split ("/.time-slider/rsync",1)
+    print s2[0]
+    os.chdir(dirName)
+    dirList = ["toto %s" % d for d in os.listdir(dirName) \
+                if os.path.isdir(d) and
+                not os.path.islink(d)] 
+    print dirList
diff --git a/usr/share/time-slider/lib/time_slider/tmp.py~ b/usr/share/time-slider/lib/time_slider/tmp.py~
new file mode 100755 (executable)
index 0000000..4072f3b
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/python2.6
+import os
+
+backupDirs = []
+
+for root, dirs, files in os.walk("/ts-test/TIMESLIDER/nanmbp"):
+    if '.time-slider' in dirs:
+#        dirs.remove('.time-slider')
+        backupDirs.append(os.path.join(root, ".time-slider/rsync"))
+       print "root %s" % root
+       s1 = root.split ("/ts-test/TIMESLIDER/nanmbp/", 1)
+       print s1
+
+for dirName in backupDirs:
+    print "dirName %s " % dirName
+    s1 = dirName.split ("/ts-test/TIMESLIDER/nanmbp/",1)
+    s2 = s1[1].split ("/.time-slider/rsync",1)
+    print s2[0]
+    os.chdir(dirName)
+    dirList = ["toto %s" % d for d in os.listdir(dirName) \
+                if os.path.isdir(d) and
+                not os.path.islink(d)] 
+    print dirList
diff --git a/usr/share/time-slider/lib/time_slider/tmp2.py b/usr/share/time-slider/lib/time_slider/tmp2.py
new file mode 100755 (executable)
index 0000000..d581a5b
--- /dev/null
@@ -0,0 +1,183 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import threading
+import sys
+import os
+import time
+import getopt
+import locale
+import shutil
+import fcntl
+from bisect import insort
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+try:
+    import glib
+    import gobject
+except:
+    sys.exit(1)
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import rsyncsmf
+
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from rbac import RBACprofile
+
+class RsyncBackup:
+
+    def __init__(self, mountpoint, rsync_dir = None,  fsname= None, snaplabel= None, creationtime= None):
+
+       if rsync_dir == None:
+         self.__init_from_mp (mountpoint)
+       else:
+         self.rsync_dir = rsync_dir
+          self.mountpoint = mountpoint
+          self.fsname = fsname
+          self.snaplabel = snaplabel
+  
+          self.creationtime = creationtime
+          try:
+              tm = time.localtime(self.creationtime)
+              self.creationtime_str = unicode(time.strftime ("%c", tm),
+                         locale.getpreferredencoding()).encode('utf-8')
+          except:
+              self.creationtime_str = time.ctime(self.creationtime)
+    
+    def __init_from_mp (self, mountpoint):
+       self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsync_dir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+       self.mountpoint = mountpoint
+       
+       s1 = mountpoint.split ("%s/" % self.rsync_dir, 1)
+       s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+       s3 = s2[1].split ('/',2)
+        self.fsname = s2[0]
+        self.snaplabel =  s3[1]
+       self.creationtime = os.stat(mountpoint).st_mtime
+
+    def __str__(self):
+       ret = "self.rsync_dir = %s\n \
+              self.mountpoint = %s\n \
+              self.fsname = %s\n \
+              self.snaplabel = %s\n" % (self.rsync_dir, 
+                                        self.mountpoint, self.fsname,
+                                        self.snaplabel)
+       return ret                                       
+
+
+    def exists(self):
+        return os.path.exists(self.mountpoint)
+
+    def destroy(self):
+       lockFileDir = os.path.join(self.rsync_dir,
+                            self.fsname,
+                            rsyncsmf.RSYNCLOCKSUFFIX)
+
+       if not os.path.exists(lockFileDir):
+         os.makedirs(lockFileDir, 0755)
+       
+       lockFile = os.path.join(lockFileDir, self.snaplabel + ".lock")
+       try:
+         lockFp = open(lockFile, 'w')
+         fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+       except IOError:
+         raise RuntimeError, \
+         "couldn't delete %s, already used by another process" % self.mountpoint
+         return 
+
+       trashDir = os.path.join(self.rsync_dir,
+                         self.fsname,
+                         rsyncsmf.RSYNCTRASHSUFFIX)
+       if not os.path.exists(trashDir):
+         os.makedirs(trashDir, 0755)
+
+       backupTrashDir = os.path.join (self.rsync_dir,
+                                self.fsname,
+                                rsyncsmf.RSYNCTRASHSUFFIX,
+                                self.snaplabel)
+
+       # move then delete
+       os.rename (self.mountpoint, backupTrashDir)
+       shutil.rmtree (backupTrashDir)
+
+       log = "%s/%s/%s/%s/%s.log" % (self.rsync_dir,
+                                  self.fsname,
+                                  rsyncsmf.RSYNCDIRSUFFIX,
+                                  ".partial",
+                                  self.snaplabel)
+       if os.path.exists (log):
+            os.unlink (log)
+
+       lockFp.close()
+       os.unlink(lockFile)
+
+
+backupDirs = []
+for root, dirs, files in os.walk(rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI)).get_target_dir ()):
+            if '.time-slider' in dirs:
+                dirs.remove('.time-slider')
+                backupDir = os.path.join(root, rsyncsmf.RSYNCDIRSUFFIX)
+                if os.path.exists(backupDir):
+                    insort(backupDirs, os.path.abspath(backupDir))
+
+
+print backupDirs
+
+
diff --git a/usr/share/time-slider/lib/time_slider/tmp2.py~ b/usr/share/time-slider/lib/time_slider/tmp2.py~
new file mode 100755 (executable)
index 0000000..84a3a59
--- /dev/null
@@ -0,0 +1,183 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import threading
+import sys
+import os
+import time
+import getopt
+import locale
+import shutil
+import fcntl
+import bisect import insort
+
+try:
+    import pygtk
+    pygtk.require("2.4")
+except:
+    pass
+try:
+    import gtk
+    import gtk.glade
+    gtk.gdk.threads_init()
+except:
+    sys.exit(1)
+try:
+    import glib
+    import gobject
+except:
+    sys.exit(1)
+
+from os.path import abspath, dirname, join, pardir
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin"))
+import plugin
+sys.path.insert(0, join(dirname(__file__), pardir, "plugin", "rsync"))
+import rsyncsmf
+
+
+# here we define the path constants so that other modules can use it.
+# this allows us to get access to the shared files without having to
+# know the actual location, we just use the location of the current
+# file and use paths relative to that.
+SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                               os.path.pardir,
+                               os.path.pardir))
+LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
+RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
+
+# the name of the gettext domain. because we have our translation files
+# not in a global folder this doesn't really matter, setting it to the
+# application name is a good idea tough.
+GETTEXT_DOMAIN = 'time-slider'
+
+# set up the glade gettext system and locales
+gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
+gtk.glade.textdomain(GETTEXT_DOMAIN)
+
+import zfs
+from rbac import RBACprofile
+
+class RsyncBackup:
+
+    def __init__(self, mountpoint, rsync_dir = None,  fsname= None, snaplabel= None, creationtime= None):
+
+       if rsync_dir == None:
+         self.__init_from_mp (mountpoint)
+       else:
+         self.rsync_dir = rsync_dir
+          self.mountpoint = mountpoint
+          self.fsname = fsname
+          self.snaplabel = snaplabel
+  
+          self.creationtime = creationtime
+          try:
+              tm = time.localtime(self.creationtime)
+              self.creationtime_str = unicode(time.strftime ("%c", tm),
+                         locale.getpreferredencoding()).encode('utf-8')
+          except:
+              self.creationtime_str = time.ctime(self.creationtime)
+    
+    def __init_from_mp (self, mountpoint):
+       self.rsyncsmf = rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI))
+        rsyncBaseDir = self.rsyncsmf.get_target_dir()
+        sys,nodeName,rel,ver,arch = os.uname()
+        self.rsync_dir = os.path.join(rsyncBaseDir,
+                                     rsyncsmf.RSYNCDIRPREFIX,
+                                     nodeName)
+       self.mountpoint = mountpoint
+       
+       s1 = mountpoint.split ("%s/" % self.rsync_dir, 1)
+       s2 = s1[1].split ("/%s" % rsyncsmf.RSYNCDIRSUFFIX, 1)
+       s3 = s2[1].split ('/',2)
+        self.fsname = s2[0]
+        self.snaplabel =  s3[1]
+       self.creationtime = os.stat(mountpoint).st_mtime
+
+    def __str__(self):
+       ret = "self.rsync_dir = %s\n \
+              self.mountpoint = %s\n \
+              self.fsname = %s\n \
+              self.snaplabel = %s\n" % (self.rsync_dir, 
+                                        self.mountpoint, self.fsname,
+                                        self.snaplabel)
+       return ret                                       
+
+
+    def exists(self):
+        return os.path.exists(self.mountpoint)
+
+    def destroy(self):
+       lockFileDir = os.path.join(self.rsync_dir,
+                            self.fsname,
+                            rsyncsmf.RSYNCLOCKSUFFIX)
+
+       if not os.path.exists(lockFileDir):
+         os.makedirs(lockFileDir, 0755)
+       
+       lockFile = os.path.join(lockFileDir, self.snaplabel + ".lock")
+       try:
+         lockFp = open(lockFile, 'w')
+         fcntl.flock(lockFp, fcntl.LOCK_EX | fcntl.LOCK_NB)
+       except IOError:
+         raise RuntimeError, \
+         "couldn't delete %s, already used by another process" % self.mountpoint
+         return 
+
+       trashDir = os.path.join(self.rsync_dir,
+                         self.fsname,
+                         rsyncsmf.RSYNCTRASHSUFFIX)
+       if not os.path.exists(trashDir):
+         os.makedirs(trashDir, 0755)
+
+       backupTrashDir = os.path.join (self.rsync_dir,
+                                self.fsname,
+                                rsyncsmf.RSYNCTRASHSUFFIX,
+                                self.snaplabel)
+
+       # move then delete
+       os.rename (self.mountpoint, backupTrashDir)
+       shutil.rmtree (backupTrashDir)
+
+       log = "%s/%s/%s/%s/%s.log" % (self.rsync_dir,
+                                  self.fsname,
+                                  rsyncsmf.RSYNCDIRSUFFIX,
+                                  ".partial",
+                                  self.snaplabel)
+       if os.path.exists (log):
+            os.unlink (log)
+
+       lockFp.close()
+       os.unlink(lockFile)
+
+
+backupDirs = []
+for root, dirs, files in os.walk(rsyncsmf.RsyncSMF("%s:rsync" %(plugin.PLUGINBASEFMRI)).get_target_dir ()):
+            if '.time-slider' in dirs:
+                dirs.remove('.time-slider')
+                backupDir = os.path.join(root, rsyncsmf.RSYNCDIRSUFFIX)
+                if os.path.exists(backupDir):
+                    insort(backupDirs, os.path.abspath(backupDir))
+
+
+print backupDirs
+
+
diff --git a/usr/share/time-slider/lib/time_slider/util.py b/usr/share/time-slider/lib/time_slider/util.py
new file mode 100644 (file)
index 0000000..e48326c
--- /dev/null
@@ -0,0 +1,134 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import subprocess
+import sys
+import syslog
+import statvfs
+import math
+import gio
+
+def run_command(command, raise_on_try=True):
+    """
+    Wrapper function around subprocess.Popen
+    Returns a tuple of standard out and stander error.
+    Throws a RunTimeError if the command failed to execute or
+    if the command returns a non-zero exit status.
+    """
+    try:
+        p = subprocess.Popen(command,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE,
+                             close_fds=True)
+        outdata,errdata = p.communicate()
+        err = p.wait()
+    except OSError, message:
+        raise RuntimeError, "%s subprocess error:\n %s" % \
+                            (command, str(message))
+    if err != 0 and raise_on_try:
+        raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                            (str(command), err, errdata)
+    return outdata,errdata
+
+def debug(message, verbose):
+    """
+    Prints message out to standard error and syslog if
+    verbose = True.
+    Note that the caller needs to first establish a syslog
+    context using syslog.openlog()
+    """
+    if verbose:
+        syslog.syslog(syslog.LOG_NOTICE, message + '\n')
+        sys.stderr.write(message + '\n')
+
+def log_error(loglevel, message):
+    """
+    Trivial syslog wrapper that also outputs to stderr
+    Requires caller to have first opened a syslog session
+    using syslog.openlog()
+    """
+    syslog.syslog(loglevel, message + '\n')
+    sys.stderr.write(message + '\n')
+
+def get_filesystem_capacity(path):
+    """Returns filesystem space usage of path as an integer percentage of
+       the entire capacity of path.
+    """
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+
+    unavailBlocks = f[statvfs.F_BLOCKS] - f[statvfs.F_BAVAIL]
+    capacity = int(math.ceil(100 * (unavailBlocks / float(f[statvfs.F_BLOCKS]))))
+
+    return capacity
+
+def get_available_size(path):
+    """Returns the available space in bytes under path"""
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+    free = long(f[statvfs.F_BAVAIL] * f[statvfs.F_FRSIZE])
+    
+    return free
+
+def get_used_size(path):
+    """Returns the used space in bytes of fileystem associated
+       with path"""
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+
+    unavailBlocks = f[statvfs.F_BLOCKS] - f[statvfs.F_BAVAIL]
+    used = long(unavailBlocks * f[statvfs.F_FRSIZE])
+
+    return used
+
+def get_total_size(path):
+    """Returns the total storage space in bytes of fileystem
+       associated with path"""
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+    total = long(f[statvfs.F_BLOCKS] * f[statvfs.F_FRSIZE])
+
+    return total
+
+def path_to_volume(path):
+    """
+       Tries to map a given path name to a gio Volume and
+       returns the gio.Volume object the enclosing
+       volume.
+       If it fails to find an enclosing volume it returns
+       None
+    """
+    gFile = gio.File(path)
+    try:
+        mount = gFile.find_enclosing_mount()
+    except gio.Error:
+        return None
+    else:
+        if mount != None:
+            volume = mount.get_volume()
+            return volume
+    return None
diff --git a/usr/share/time-slider/lib/time_slider/util.py~ b/usr/share/time-slider/lib/time_slider/util.py~
new file mode 100644 (file)
index 0000000..e48326c
--- /dev/null
@@ -0,0 +1,134 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import os
+import subprocess
+import sys
+import syslog
+import statvfs
+import math
+import gio
+
+def run_command(command, raise_on_try=True):
+    """
+    Wrapper function around subprocess.Popen
+    Returns a tuple of standard out and stander error.
+    Throws a RunTimeError if the command failed to execute or
+    if the command returns a non-zero exit status.
+    """
+    try:
+        p = subprocess.Popen(command,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE,
+                             close_fds=True)
+        outdata,errdata = p.communicate()
+        err = p.wait()
+    except OSError, message:
+        raise RuntimeError, "%s subprocess error:\n %s" % \
+                            (command, str(message))
+    if err != 0 and raise_on_try:
+        raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                            (str(command), err, errdata)
+    return outdata,errdata
+
+def debug(message, verbose):
+    """
+    Prints message out to standard error and syslog if
+    verbose = True.
+    Note that the caller needs to first establish a syslog
+    context using syslog.openlog()
+    """
+    if verbose:
+        syslog.syslog(syslog.LOG_NOTICE, message + '\n')
+        sys.stderr.write(message + '\n')
+
+def log_error(loglevel, message):
+    """
+    Trivial syslog wrapper that also outputs to stderr
+    Requires caller to have first opened a syslog session
+    using syslog.openlog()
+    """
+    syslog.syslog(loglevel, message + '\n')
+    sys.stderr.write(message + '\n')
+
+def get_filesystem_capacity(path):
+    """Returns filesystem space usage of path as an integer percentage of
+       the entire capacity of path.
+    """
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+
+    unavailBlocks = f[statvfs.F_BLOCKS] - f[statvfs.F_BAVAIL]
+    capacity = int(math.ceil(100 * (unavailBlocks / float(f[statvfs.F_BLOCKS]))))
+
+    return capacity
+
+def get_available_size(path):
+    """Returns the available space in bytes under path"""
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+    free = long(f[statvfs.F_BAVAIL] * f[statvfs.F_FRSIZE])
+    
+    return free
+
+def get_used_size(path):
+    """Returns the used space in bytes of fileystem associated
+       with path"""
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+
+    unavailBlocks = f[statvfs.F_BLOCKS] - f[statvfs.F_BAVAIL]
+    used = long(unavailBlocks * f[statvfs.F_FRSIZE])
+
+    return used
+
+def get_total_size(path):
+    """Returns the total storage space in bytes of fileystem
+       associated with path"""
+    if not os.path.exists(path):
+        raise ValueError("%s is a non-existent path" % path)
+    f = os.statvfs(path)
+    total = long(f[statvfs.F_BLOCKS] * f[statvfs.F_FRSIZE])
+
+    return total
+
+def path_to_volume(path):
+    """
+       Tries to map a given path name to a gio Volume and
+       returns the gio.Volume object the enclosing
+       volume.
+       If it fails to find an enclosing volume it returns
+       None
+    """
+    gFile = gio.File(path)
+    try:
+        mount = gFile.find_enclosing_mount()
+    except gio.Error:
+        return None
+    else:
+        if mount != None:
+            volume = mount.get_volume()
+            return volume
+    return None
diff --git a/usr/share/time-slider/lib/time_slider/zfs.py b/usr/share/time-slider/lib/time_slider/zfs.py
new file mode 100755 (executable)
index 0000000..b35e58d
--- /dev/null
@@ -0,0 +1,1049 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import subprocess
+import re
+import threading
+from bisect import insort, bisect_left, bisect_right
+
+import util
+
+BYTESPERMB = 1048576
+
+# Commonly used command paths
+PFCMD = "/usr/bin/pfexec"
+ZFSCMD = "/usr/sbin/zfs"
+ZPOOLCMD = "/usr/sbin/zpool"
+
+
+class Datasets(Exception):
+    """
+    Container class for all zfs datasets. Maintains a centralised
+    list of datasets (generated on demand) and accessor methods. 
+    Also allows clients to notify when a refresh might be necessary.
+    """
+    # Class wide instead of per-instance in order to avoid duplication
+    filesystems = None
+    volumes = None
+    snapshots = None
+    
+    # Mutex locks to prevent concurrent writes to above class wide
+    # dataset lists.
+    _filesystemslock = threading.Lock()
+    _volumeslock = threading.Lock()
+    snapshotslock = threading.Lock()
+
+    def create_auto_snapshot_set(self, label, tag = None):
+        """
+        Create a complete set of snapshots as if this were
+        for a standard zfs-auto-snapshot operation.
+        
+        Keyword arguments:
+        label:
+            A label to apply to the snapshot name. Cannot be None.
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" for will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        everything = []
+        included = []
+        excluded = []
+        single = []
+        recursive = []
+        finalrecursive = []
+
+        # Get auto-snap property in two passes. First with the schedule
+        # specific tag override value, then with the general property value
+        cmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+               "-o", "name,com.sun:auto-snapshot", "-s", "name"]
+        if tag:
+            overrideprop = "com.sun:auto-snapshot:" + tag
+            scmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+                    "-o", "name," + overrideprop, "-s", "name"]
+            outdata,errdata = util.run_command(scmd)
+            for line in outdata.rstrip().split('\n'):
+                line = line.split()
+                # Skip over unset values. 
+                if line[1] == "-":
+                    continue
+                # Add to everything list. This is used later
+                # for identifying parents/children of a given
+                # filesystem or volume.
+                everything.append(line[0])
+                if line[1] == "true":
+                    included.append(line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+        # Now use the general property. If no value
+        # was set in the first pass, we set it here.
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            line = line.split()
+            idx = bisect_right(everything, line[0])
+            if len(everything) == 0 or \
+               everything[idx-1] != line[0]:           
+                # Dataset is neither included nor excluded so far
+                if line[1] == "-":
+                    continue
+                everything.insert(idx, line[0])
+                if line[1] == "true":
+                    included.insert(0, line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+
+        # Now figure out what can be recursively snapshotted and what
+        # must be singly snapshotted. Single snapshot restrictions apply
+        # to those datasets who have a child in the excluded list.
+        # 'included' is sorted in reverse alphabetical order. 
+        for datasetname in included:
+            excludedchild = False
+            idx = bisect_right(everything, datasetname)
+            children = [name for name in everything[idx:] if \
+                        name.find(datasetname) == 0]
+            for child in children:
+                idx = bisect_left(excluded, child)
+                if idx < len(excluded) and excluded[idx] == child:
+                    excludedchild = True
+                    single.append(datasetname)
+                    break
+            if excludedchild == False:
+                # We want recursive list sorted in alphabetical order
+                # so insert instead of append to the list.
+                recursive.insert(0, datasetname)
+
+        for datasetname in recursive:
+            parts = datasetname.rsplit('/', 1)
+            parent = parts[0]
+            if parent == datasetname:
+                # Root filesystem of the Zpool, so
+                # this can't be inherited and must be
+                # set locally.
+                finalrecursive.append(datasetname)
+                continue
+            idx = bisect_right(recursive, parent)
+            if len(recursive) > 0 and \
+               recursive[idx-1] == parent:
+                # Parent already marked for recursive snapshot: so skip
+                continue
+            else:
+                finalrecursive.append(datasetname)
+
+        for name in finalrecursive:
+            dataset = ReadWritableDataset(name)
+            dataset.create_snapshot(label, True)
+        for name in single:
+            dataset = ReadWritableDataset(name)
+            dataset.create_snapshot(label, False)
+
+    def list_auto_snapshot_sets(self, tag = None):
+        """
+        Returns a list of zfs filesystems and volumes tagged with
+        the "com.sun:auto-snapshot" property set to "true", either
+        set locally or inherited. Snapshots are excluded from the
+        returned result.
+
+        Keyword Arguments:
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        #Get auto-snap property in two passes. First with the global
+        #value, then overriding with the label/schedule specific value
+
+        included = []
+        excluded = []
+
+        cmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+               "-o", "name,com.sun:auto-snapshot", "-s", "name"]
+        if tag:
+            overrideprop = "com.sun:auto-snapshot:" + tag
+            scmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+                    "-o", "name," + overrideprop, "-s", "name"]
+            outdata,errdata = util.run_command(scmd)
+            for line in outdata.rstrip().split('\n'):
+                line = line.split()
+                if line[1] == "true":
+                    included.append(line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            line = line.split()
+            # Only set values that aren't already set. Don't override
+            try:
+                included.index(line[0])
+                continue
+            except ValueError:
+                try:
+                    excluded.index(line[0])
+                    continue
+                except ValueError:
+                    # Dataset is not listed in either list.
+                    if line[1] == "true":
+                        included.append(line[0])
+        return included
+
+    def list_filesystems(self, pattern = None):
+        """
+        List pattern matching filesystems sorted by name.
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        filesystems = []
+        # Need to first ensure no other thread is trying to
+        # build this list at the same time.
+        Datasets._filesystemslock.acquire()
+        if Datasets.filesystems == None:
+            Datasets.filesystems = []
+            cmd = [ZFSCMD, "list", "-H", "-t", "filesystem", \
+                   "-o", "name,mountpoint", "-s", "name"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err = p.wait()
+            except OSError, message:
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets._filesystemslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for line in outdata.rstrip().split('\n'):
+                line = line.rstrip().split()
+                Datasets.filesystems.append([line[0], line[1]])
+        Datasets._filesystemslock.release()
+
+        if pattern == None:
+            filesystems = Datasets.filesystems[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*%s.*" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for fsname,fsmountpoint in Datasets.filesystems:
+                patternmatchobj = re.match(patternobj, fsname)
+                if patternmatchobj != None:
+                    filesystems.append(fsname, fsmountpoint)
+        return filesystems
+
+    def list_volumes(self, pattern = None):
+        """
+        List pattern matching volumes sorted by name.
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        volumes = []
+        Datasets._volumeslock.acquire()
+        if Datasets.volumes == None:
+            Datasets.volumes = []
+            cmd = [ZFSCMD, "list", "-H", "-t", "volume", \
+                   "-o", "name", "-s", "name"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err = p.wait()
+            except OSError, message:
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets._volumeslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for line in outdata.rstrip().split('\n'):
+                Datasets.volumes.append(line.rstrip())
+        Datasets._volumeslock.release()
+
+        if pattern == None:
+            volumes = Datasets.volumes[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*%s.*" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for volname in Datasets.volumes:
+                patternmatchobj = re.match(patternobj, volname)
+                if patternmatchobj != None:
+                    volumes.append(volname)
+        return volumes
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        snapshots = []
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            Datasets.snapshots = []
+            snaps = []
+            cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value,name", "creation"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err= p.wait()
+            except OSError, message:
+                Datasets.snapshotslock.release()
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets.snapshotslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for dataset in outdata.rstrip().split('\n'):
+                if re.search("@", dataset):
+                    insort(snaps, dataset.split())
+            for snap in snaps:
+                Datasets.snapshots.append([snap[1], long(snap[0])])
+        if pattern == None:
+            snapshots = Datasets.snapshots[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*@.*%s" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for snapname,snaptime in Datasets.snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append([snapname, snaptime])
+        Datasets.snapshotslock.release()
+        return snapshots
+
+    def list_cloned_snapshots(self):
+        """
+        Returns a list of snapshots that have cloned filesystems
+        dependent on them.
+        Snapshots with cloned filesystems can not be destroyed
+        unless dependent cloned filesystems are first destroyed.
+        """
+        cmd = [ZFSCMD, "list", "-H", "-o", "origin"]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            details = line.rstrip()
+            if details != "-":
+                try:
+                    result.index(details)
+                except ValueError:
+                    result.append(details)
+        return result
+
+    def list_held_snapshots(self):
+        """
+        Returns a list of snapshots that have a "userrefs"
+        property value of greater than 0. Resul list is
+        sorted in order of creation time. Oldest listed first.
+        """
+        cmd = [ZFSCMD, "list", "-H",
+               "-t", "snapshot",
+               "-s", "creation",
+               "-o", "userrefs,name"]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            details = line.split()
+            if details[0] != "0":
+                result.append(details[1])
+        return result
+
+    def refresh_snapshots(self):
+        """
+        Should be called when snapshots have been created or deleted
+        and a rescan should be performed. Rescan gets deferred until
+        next invocation of zfs.Dataset.list_snapshots()
+        """
+        # FIXME in future.
+        # This is a little sub-optimal because we should be able to modify
+        # the snapshot list in place in some situations and regenerate the 
+        # snapshot list without calling out to zfs(1m). But on the
+        # pro side, we will pick up any new snapshots since the last
+        # scan that we would be otherwise unaware of.
+        Datasets.snapshotslock.acquire()
+        Datasets.snapshots = None
+        Datasets.snapshotslock.release()
+
+
+class ZPool:
+    """
+    Base class for ZFS storage pool objects
+    """
+    def __init__(self, name):
+        self.name = name
+        self.health = self.__get_health()
+        self.__datasets = Datasets()
+        self.__filesystems = None
+        self.__volumes = None
+        self.__snapshots = None
+
+    def __get_health(self):
+        """
+        Returns pool health status: 'ONLINE', 'DEGRADED' or 'FAULTED'
+        """
+        cmd = [ZPOOLCMD, "list", "-H", "-o", "health", self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        return result
+
+    def get_capacity(self):
+        """
+        Returns the percentage of total pool storage in use.
+        Calculated based on the "used" and "available" properties
+        of the pool's top-level filesystem because the values account
+        for reservations and quotas of children in their calculations,
+        giving a more practical indication of how much capacity is used
+        up on the pool.
+        """
+        if self.health == "FAULTED":
+            raise ZPoolFaultedError("Can not determine capacity of zpool: %s" \
+                                    "because it is in a FAULTED state" \
+                                    % (self.name))
+
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", \
+               "used,available", self.name]
+        outdata,errdata = util.run_command(cmd)
+        _used,_available = outdata.rstrip().split('\n')
+        used = float(_used)
+        available = float(_available) 
+        return 100.0 * used/(used + available)
+
+    def get_available_size(self):
+        """
+        How much unused space is available for use on this Zpool.
+        Answer in bytes.
+        """
+        # zpool(1) doesn't report available space in
+        # units suitable for calulations but zfs(1)
+        # can so use it to find the value for the
+        # filesystem matching the pool.
+        # The root filesystem of the pool is simply
+        # the pool name.
+        poolfs = Filesystem(self.name)
+        avail = poolfs.get_available_size()
+        return avail
+
+    def get_used_size(self):
+        """
+        How much space is in use on this Zpool.
+        Answer in bytes
+        """
+        # Same as ZPool.get_available_size(): zpool(1)
+        # doesn't generate suitable out put so use
+        # zfs(1) on the toplevel filesystem
+        if self.health == "FAULTED":
+            raise ZPoolFaultedError("Can not determine used size of zpool: %s" \
+                                    "because it is in a FAULTED state" \
+                                    % (self.name))
+        poolfs = Filesystem(self.name)
+        used = poolfs.get_used_size()
+        return used
+
+    def list_filesystems(self):
+        """
+        Return a list of filesystems on this Zpool.
+        List is sorted by name.
+        """
+        if self.__filesystems == None:
+            result = []
+            # Provides pre-sorted filesystem list
+            for fsname,fsmountpoint in self.__datasets.list_filesystems():
+                if re.match(self.name, fsname):
+                    result.append([fsname, fsmountpoint])
+            self.__filesystems = result
+        return self.__filesystems
+
+    def list_volumes(self):
+        """
+        Return a list of volumes (zvol) on this Zpool
+        List is sorted by name
+        """
+        if self.__volumes == None:
+            result = []
+            regexpattern = "^%s" % self.name
+            patternobj = re.compile(regexpattern)
+            for volname in self.__datasets.list_volumes():
+                patternmatchobj = re.match(patternobj, volname)
+                if patternmatchobj != None:
+                    result.append(volname)
+            result.sort()
+            self.__volumes = result
+        return self.__volumes
+
+    def list_auto_snapshot_sets(self, tag = None):
+        """
+        Returns a list of zfs filesystems and volumes tagged with
+        the "com.sun:auto-snapshot" property set to "true", either
+        set locally or inherited. Snapshots are excluded from the
+        returned result. Results are not sorted.
+
+        Keyword Arguments:
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        result = []
+        allsets = self.__datasets.list_auto_snapshot_sets(tag)
+        if len(allsets) == 0:
+            return result
+
+        regexpattern = "^%s" % self.name
+        patternobj = re.compile(regexpattern)
+        for datasetname in allsets:
+            patternmatchobj = re.match(patternobj, datasetname)
+            if patternmatchobj != None:
+                result.append(datasetname)
+        return result
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+           
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)   
+        """
+        # If there isn't a list of snapshots for this dataset
+        # already, create it now and store it in order to save
+        # time later for potential future invocations.
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            self.__snapshots = None
+        Datasets.snapshotslock.release()
+        if self.__snapshots == None:
+            result = []
+            regexpattern = "^%s.*@"  % self.name
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__datasets.list_snapshots():
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    result.append([snapname, snaptime])
+            # Results already sorted by creation time
+            self.__snapshots = result
+        if pattern == None:
+            return self.__snapshots
+        else:
+            snapshots = []
+            regexpattern = "^%s.*@.*%s" % (self.name, pattern)
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append([snapname, snaptime])
+            return snapshots
+
+    def __str__(self):
+        return_string = "ZPool name: " + self.name
+        return_string = return_string + "\n\tHealth: " + self.health
+        try:
+            return_string = return_string + \
+                            "\n\tUsed: " + \
+                            str(self.get_used_size()/BYTESPERMB) + "Mb"
+            return_string = return_string + \
+                            "\n\tAvailable: " + \
+                            str(self.get_available_size()/BYTESPERMB) + "Mb"
+            return_string = return_string + \
+                            "\n\tCapacity: " + \
+                            str(self.get_capacity()) + "%"
+        except ZPoolFaultedError:
+            pass
+        return return_string
+
+
+class ReadableDataset:
+    """
+    Base class for Filesystem, Volume and Snapshot classes
+    Provides methods for read only operations common to all.
+    """
+    def __init__(self, name, creation = None):
+        self.name = name
+        self.__creationTime = creation
+        self.datasets = Datasets()
+
+    def __str__(self):
+        return_string = "ReadableDataset name: " + self.name + "\n"
+        return return_string
+
+    def get_creation_time(self):
+        if self.__creationTime == None:
+            cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "creation",
+                   self.name]
+            outdata,errdata = util.run_command(cmd)
+            self.__creationTime = long(outdata.rstrip())
+        return self.__creationTime
+
+    def exists(self):
+        """
+        Returns True if the dataset is still existent on the system.
+        False otherwise
+        """
+        # Test existance of the dataset by checking the output of a 
+        # simple zfs get command on the snapshot
+        cmd = [ZFSCMD, "get", "-H", "-o", "name", "type", self.name]
+        try:
+            p = subprocess.Popen(cmd,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE,
+                                 close_fds=True)
+            outdata,errdata = p.communicate()
+            err = p.wait()
+        except OSError, message:
+            raise RuntimeError, "%s subprocess error:\n %s" % \
+                            (command, str(message))
+        if err != 0:
+            # Doesn't exist
+            return False
+
+        result = outdata.rstrip()
+        if result == self.name:
+            return True
+        else:
+            return False
+
+    def get_used_size(self):
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "used", self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def get_user_property(self, prop, local=False):
+        if local == True:
+            cmd = [ZFSCMD, "get", "-s", "local", "-H", "-o", "value", prop, self.name]
+        else:
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", prop, self.name]
+        outdata,errdata = util.run_command(cmd)
+        return outdata.rstrip()
+
+    def set_user_property(self, prop, value):
+        cmd = [PFCMD, ZFSCMD, "set", "%s=%s" % (prop, value), self.name]
+        outdata,errdata = util.run_command(cmd)
+    
+    def unset_user_property(self, prop):
+        cmd = [PFCMD, ZFSCMD, "inherit", prop, self.name]
+        outdata,errdata = util.run_command(cmd)
+
+class Snapshot(ReadableDataset):
+    """
+    ZFS Snapshot object class.
+    Provides information and operations specfic to ZFS snapshots
+    """    
+    def __init__(self, name, creation = None):
+        """
+        Keyword arguments:
+        name -- Name of the ZFS snapshot
+        creation -- Creation time of the snapshot if known (Default None)
+        """
+        ReadableDataset.__init__(self, name, creation)
+        self.fsname, self.snaplabel = self.__split_snapshot_name()
+        self.poolname = self.__get_pool_name()
+
+    def __get_pool_name(self):
+        name = self.fsname.split("/", 1)
+        return name[0]
+
+    def __split_snapshot_name(self):
+        name = self.name.split("@", 1)
+        # Make sure this is really a snapshot and not a
+        # filesystem otherwise a filesystem could get 
+        # destroyed instead of a snapshot. That would be
+        # really really bad.
+        if name[0] == self.name:
+            raise SnapshotError("\'%s\' is not a valid snapshot name" \
+                                % (self.name))
+        return name[0],name[1]
+
+    def get_referenced_size(self):
+        """
+        How much unique storage space is used by this snapshot.
+        Answer in bytes
+        """
+        cmd = [ZFSCMD, "get", "-H", "-p", \
+               "-o", "value", "referenced", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def list_children(self):
+        """Returns a recursive list of child snapshots of this snapshot"""
+        cmd = [ZFSCMD,
+               "list", "-t", "snapshot", "-H", "-r", "-o", "name",
+               self.fsname]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if re.search("@%s" % (self.snaplabel), line) and \
+                line != self.name:
+                    result.append(line)
+        return result
+
+    def has_clones(self):
+        """Returns True if the snapshot has any dependent clones"""
+        cmd = [ZFSCMD, "list", "-H", "-o", "origin,name"]
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            details = line.rstrip().split()
+            if details[0] == self.name and \
+                details[1] != '-':
+                return True
+        return False
+
+    def destroy(self, deferred=True):
+        """
+        Permanently remove this snapshot from the filesystem
+        Performs deferred destruction by default.
+        """
+        # Be sure it genuninely exists before trying to destroy it
+        if self.exists() == False:
+            return
+        if deferred == False:
+            cmd = [PFCMD, ZFSCMD, "destroy", self.name]
+        else:
+            cmd = [PFCMD, ZFSCMD, "destroy", "-d", self.name]
+
+        outdata,errdata = util.run_command(cmd)
+        # Clear the global snapshot cache so that a rescan will be
+        # triggered on the next call to Datasets.list_snapshots()
+        self.datasets.refresh_snapshots()
+
+    def hold(self, tag):
+        """
+        Place a hold on the snapshot with the specified "tag" string.
+        """
+        # FIXME - fails if hold is already held
+        # Be sure it genuninely exists before trying to place a hold
+        if self.exists() == False:
+            return
+
+        cmd = [PFCMD, ZFSCMD, "hold", tag, self.name]
+        outdata,errdata = util.run_command(cmd)
+
+    def holds(self):
+        """
+        Returns a list of user hold tags for this snapshot
+        """
+        cmd = [ZFSCMD, "holds", self.name]
+        results = []
+        outdata,errdata = util.run_command(cmd)
+
+        for line in outdata.rstrip().split('\n'):
+            if len(line) == 0:
+                continue
+            # The first line heading columns are  NAME TAG TIMESTAMP
+            # Filter that line out.
+            line = line.split()
+            if (line[0] != "NAME" and line[1] != "TAG"):
+                results.append(line[1])
+        return results
+
+    def release(self, tag,):
+        """
+        Release the hold on the snapshot with the specified "tag" string.
+        """
+        # FIXME raises exception if no hold exists.
+        # Be sure it genuninely exists before trying to destroy it
+        if self.exists() == False:
+            return
+
+        cmd = [PFCMD, ZFSCMD, "release", tag, self.name]
+
+        outdata,errdata = util.run_command(cmd)
+        # Releasing the snapshot might cause it get automatically
+        # deleted by zfs.
+        # Clear the global snapshot cache so that a rescan will be
+        # triggered on the next call to Datasets.list_snapshots()
+        self.datasets.refresh_snapshots()
+
+
+    def __str__(self):
+        return_string = "Snapshot name: " + self.name
+        return_string = return_string + "\n\tCreation time: " \
+                        + str(self.get_creation_time())
+        return_string = return_string + "\n\tUsed Size: " \
+                        + str(self.get_used_size())
+        return_string = return_string + "\n\tReferenced Size: " \
+                        + str(self.get_referenced_size())
+        return return_string
+
+
+class ReadWritableDataset(ReadableDataset):
+    """
+    Base class for ZFS filesystems and volumes.
+    Provides methods for operations and properties
+    common to both filesystems and volumes.
+    """
+    def __init__(self, name, creation = None):
+        ReadableDataset.__init__(self, name, creation)
+        self.__snapshots = None
+
+    def __str__(self):
+        return_string = "ReadWritableDataset name: " + self.name + "\n"
+        return return_string
+
+    def get_auto_snap(self, schedule = None):
+        if schedule:
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", \
+               "com.sun:auto-snapshot", self.name]
+        cmd = [ZFSCMD, "get", "-H", "-o", "value", \
+               "com.sun:auto-snapshot", self.name]
+        outdata,errdata = util.run_command(cmd)
+        if outdata.rstrip() == "true":
+            return True
+        else:
+            return False
+
+    def get_available_size(self):
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "available", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def create_snapshot(self, snaplabel, recursive = False):
+        """
+        Create a snapshot for the ReadWritable dataset using the supplied
+        snapshot label.
+
+        Keyword Arguments:
+        snaplabel:
+            A string to use as the snapshot label.
+            The bit that comes after the "@" part of the snapshot
+            name.
+        recursive:
+            Recursively snapshot childfren of this dataset.
+            Default = False
+        """
+        cmd = [PFCMD, ZFSCMD, "snapshot"]
+        if recursive == True:
+            cmd.append("-r")
+        cmd.append("%s@%s" % (self.name, snaplabel))
+        outdata,errdata = util.run_command(cmd, False)
+       if errdata:
+         print errdata
+        self.datasets.refresh_snapshots()
+
+    def list_children(self):
+        
+        # Note, if more dataset types ever come around they will
+        # need to be added to the filsystem,volume args below.
+        # Not for the forseeable future though.
+        cmd = [ZFSCMD, "list", "-H", "-r", "-t", "filesystem,volume",
+               "-o", "name", self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if line.rstrip() != self.name:
+                result.append(line.rstrip())
+        return result
+
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+           
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)   
+        """
+        # If there isn't a list of snapshots for this dataset
+        # already, create it now and store it in order to save
+        # time later for potential future invocations.
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            self.__snapshots = None
+        Datasets.snapshotslock.release()
+        if self.__snapshots == None:
+            result = []
+            regexpattern = "^%s@" % self.name
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.datasets.list_snapshots():
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    result.append([snapname, snaptime])
+            # Results already sorted by creation time
+            self.__snapshots = result
+        if pattern == None:
+            return self.__snapshots
+        else:
+            snapshots = []
+            regexpattern = "^%s@.*%s" % (self.name, pattern)
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append(snapname)
+            return snapshots
+
+    def set_auto_snap(self, include, inherit = False):
+        if inherit == True:
+            self.unset_user_property("com.sun:auto-snapshot")
+        else:
+            if include == True:
+                value = "true"
+            else:
+                value = "false"
+            self.set_user_property("com.sun:auto-snapshot", value)
+
+        return
+
+
+class Filesystem(ReadWritableDataset):
+    """ZFS Filesystem class"""
+    def __init__(self, name, mountpoint = None):
+        ReadWritableDataset.__init__(self, name)
+        self.__mountpoint = mountpoint
+
+    def __str__(self):
+        return_string = "Filesystem name: " + self.name + \
+                        "\n\tMountpoint: " + self.get_mountpoint() + \
+                        "\n\tMounted: " + str(self.is_mounted()) + \
+                        "\n\tAuto snap: " + str(self.get_auto_snap())
+        return return_string
+
+    def get_mountpoint(self):
+        if (self.__mountpoint == None):
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", "mountpoint", \
+                   self.name]
+            outdata,errdata = util.run_command(cmd)
+            result = outdata.rstrip()
+            self.__mountpoint = result
+        return self.__mountpoint
+
+    def is_mounted(self):
+        cmd = [ZFSCMD, "get", "-H", "-o", "value", "mounted", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        if result == "yes":
+            return True
+        else:
+            return False
+
+    def list_children(self):
+        cmd = [ZFSCMD, "list", "-H", "-r", "-t", "filesystem", "-o", "name",
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if line.rstrip() != self.name:
+                result.append(line.rstrip())
+        return result
+
+
+class Volume(ReadWritableDataset):
+    """
+    ZFS Volume Class
+    This is basically just a stub and does nothing
+    unique from ReadWritableDataset parent class.
+    """
+    def __init__(self, name):
+        ReadWritableDataset.__init__(self, name)
+
+    def __str__(self):
+        return_string = "Volume name: " + self.name + "\n"
+        return return_string
+
+
+class ZFSError(Exception):
+    """Generic base class for ZPoolFaultedError and SnapshotError
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __str__(self):
+        return repr(self.msg)
+
+
+class ZPoolFaultedError(ZFSError):
+    """Exception raised for queries made against ZPools that
+       are in a FAULTED state
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        ZFSError.__init__(self, msg)
+
+
+class SnapshotError(ZFSError):
+    """Exception raised for invalid snapshot names provided to
+       Snapshot() constructor.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        ZFSError.__init__(self, msg)
+
+
+def list_zpools():
+    """Returns a list of all zpools on the system"""
+    result = []
+    cmd = [ZPOOLCMD, "list", "-H", "-o", "name"]
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        result.append(line.rstrip())
+    return result
+
+
+if __name__ == "__main__":
+    for zpool in list_zpools():
+        pool = ZPool(zpool)
+        print pool
+        for filesys,mountpoint in pool.list_filesystems():
+            fs = Filesystem(filesys, mountpoint)
+            print fs
+            print "\tSnapshots:"
+            for snapshot, snaptime in fs.list_snapshots():
+                snap = Snapshot(snapshot, snaptime)
+                print "\t\t" + snap.name
+
+        for volname in pool.list_volumes():
+            vol = Volume(volname)
+            print vol
+            print "\tSnapshots:"
+            for snapshot, snaptime in vol.list_snapshots():
+                snap = Snapshot(snapshot, snaptime)
+                print "\t\t" + snap.name
+
diff --git a/usr/share/time-slider/lib/time_slider/zfs.py.safe b/usr/share/time-slider/lib/time_slider/zfs.py.safe
new file mode 100755 (executable)
index 0000000..77b1150
--- /dev/null
@@ -0,0 +1,1055 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import subprocess
+import re
+import threading
+from bisect import insort, bisect_left, bisect_right
+
+import util
+
+BYTESPERMB = 1048576
+
+# Commonly used command paths
+PFCMD = "/usr/bin/pfexec"
+ZFSCMD = "/usr/sbin/zfs"
+ZPOOLCMD = "/usr/sbin/zpool"
+
+
+class Datasets(Exception):
+    """
+    Container class for all zfs datasets. Maintains a centralised
+    list of datasets (generated on demand) and accessor methods. 
+    Also allows clients to notify when a refresh might be necessary.
+    """
+    # Class wide instead of per-instance in order to avoid duplication
+    filesystems = None
+    volumes = None
+    snapshots = None
+    
+    # Mutex locks to prevent concurrent writes to above class wide
+    # dataset lists.
+    _filesystemslock = threading.Lock()
+    _volumeslock = threading.Lock()
+    snapshotslock = threading.Lock()
+
+    def create_auto_snapshot_set(self, label, tag = None):
+        """
+        Create a complete set of snapshots as if this were
+        for a standard zfs-auto-snapshot operation.
+        
+        Keyword arguments:
+        label:
+            A label to apply to the snapshot name. Cannot be None.
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" for will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        everything = []
+        included = []
+        excluded = []
+        single = []
+        recursive = []
+        finalrecursive = []
+
+        # Get auto-snap property in two passes. First with the schedule
+        # specific tag override value, then with the general property value
+        cmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+               "-o", "name,com.sun:auto-snapshot", "-s", "name"]
+        if tag:
+            overrideprop = "com.sun:auto-snapshot:" + tag
+            scmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+                    "-o", "name," + overrideprop, "-s", "name"]
+            outdata,errdata = util.run_command(scmd)
+            for line in outdata.rstrip().split('\n'):
+                line = line.split()
+                # Skip over unset values. 
+                if line[1] == "-":
+                    continue
+                # Add to everything list. This is used later
+                # for identifying parents/children of a given
+                # filesystem or volume.
+                everything.append(line[0])
+                if line[1] == "true":
+                    included.append(line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+        # Now use the general property. If no value
+        # was set in the first pass, we set it here.
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            line = line.split()
+            idx = bisect_right(everything, line[0])
+            if len(everything) == 0 or \
+               everything[idx-1] != line[0]:           
+                # Dataset is neither included nor excluded so far
+                if line[1] == "-":
+                    continue
+                everything.insert(idx, line[0])
+                if line[1] == "true":
+                    included.insert(0, line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+
+        # Now figure out what can be recursively snapshotted and what
+        # must be singly snapshotted. Single snapshot restrictions apply
+        # to those datasets who have a child in the excluded list.
+        # 'included' is sorted in reverse alphabetical order. 
+        for datasetname in included:
+            excludedchild = False
+            idx = bisect_right(everything, datasetname)
+            children = [name for name in everything[idx:] if \
+                        name.find(datasetname) == 0]
+            for child in children:
+                idx = bisect_left(excluded, child)
+                if excluded[idx] == child:
+                    excludedchild = True
+                    single.append(datasetname)
+                    break
+            if excludedchild == False:
+                # We want recursive list sorted in alphabetical order
+                # so insert instead of append to the list.
+                recursive.insert(0, datasetname)
+
+        for datasetname in recursive:
+            parts = datasetname.rsplit('/', 1)
+            parent = parts[0]
+            if parent == datasetname:
+                # Root filesystem of the Zpool, so
+                # this can't be inherited and must be
+                # set locally.
+                finalrecursive.append(datasetname)
+                continue
+            idx = bisect_right(recursive, parent)
+            if len(recursive) > 0 and \
+               recursive[idx-1] == parent:
+                # Parent already marked for recursive snapshot: so skip
+                continue
+            else:
+                finalrecursive.append(datasetname)
+
+        for name in finalrecursive:
+            dataset = ReadWritableDataset(name)
+            dataset.create_snapshot(label, True)
+        for name in single:
+            dataset = ReadWritableDataset(name)
+            dataset.create_snapshot(label, False)
+
+    def list_auto_snapshot_sets(self, tag = None):
+        """
+        Returns a list of zfs filesystems and volumes tagged with
+        the "com.sun:auto-snapshot" property set to "true", either
+        set locally or inherited. Snapshots are excluded from the
+        returned result.
+
+        Keyword Arguments:
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        #Get auto-snap property in two passes. First with the global
+        #value, then overriding with the label/schedule specific value
+
+        included = []
+        excluded = []
+
+        cmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+               "-o", "name,com.sun:auto-snapshot", "-s", "name"]
+        if tag:
+            overrideprop = "com.sun:auto-snapshot:" + tag
+            scmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+                    "-o", "name," + overrideprop, "-s", "name"]
+            outdata,errdata = util.run_command(scmd)
+            for line in outdata.rstrip().split('\n'):
+                line = line.split()
+                if line[1] == "true":
+                    included.append(line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            line = line.split()
+            # Only set values that aren't already set. Don't override
+            try:
+                included.index(line[0])
+                continue
+            except ValueError:
+                try:
+                    excluded.index(line[0])
+                    continue
+                except ValueError:
+                    # Dataset is not listed in either list.
+                    if line[1] == "true":
+                        included.append(line[0])
+        return included
+
+    def list_filesystems(self, pattern = None):
+        """
+        List pattern matching filesystems sorted by name.
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        filesystems = []
+        # Need to first ensure no other thread is trying to
+        # build this list at the same time.
+        Datasets._filesystemslock.acquire()
+        if Datasets.filesystems == None:
+            Datasets.filesystems = []
+            cmd = [ZFSCMD, "list", "-H", "-t", "filesystem", \
+                   "-o", "name,mountpoint", "-s", "name"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err = p.wait()
+            except OSError, message:
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets._filesystemslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for line in outdata.rstrip().split('\n'):
+                line = line.rstrip().split()
+                Datasets.filesystems.append([line[0], line[1]])
+        Datasets._filesystemslock.release()
+
+        if pattern == None:
+            filesystems = Datasets.filesystems[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*%s.*" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for fsname,fsmountpoint in Datasets.filesystems:
+                patternmatchobj = re.match(patternobj, fsname)
+                if patternmatchobj != None:
+                    filesystems.append(fsname, fsmountpoint)
+        return filesystems
+
+    def list_volumes(self, pattern = None):
+        """
+        List pattern matching volumes sorted by name.
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        volumes = []
+        Datasets._volumeslock.acquire()
+        if Datasets.volumes == None:
+            Datasets.volumes = []
+            cmd = [ZFSCMD, "list", "-H", "-t", "volume", \
+                   "-o", "name", "-s", "name"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err = p.wait()
+            except OSError, message:
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets._volumeslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for line in outdata.rstrip().split('\n'):
+                Datasets.volumes.append(line.rstrip())
+        Datasets._volumeslock.release()
+
+        if pattern == None:
+            volumes = Datasets.volumes[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*%s.*" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for volname in Datasets.volumes:
+                patternmatchobj = re.match(patternobj, volname)
+                if patternmatchobj != None:
+                    volumes.append(volname)
+        return volumes
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        snapshots = []
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            Datasets.snapshots = []
+            snaps = []
+            cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value,name", "creation"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err= p.wait()
+            except OSError, message:
+                Datasets.snapshotslock.release()
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets.snapshotslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for dataset in outdata.rstrip().split('\n'):
+                if re.search("@", dataset):
+                    insort(snaps, dataset.split())
+            for snap in snaps:
+                Datasets.snapshots.append([snap[1], long(snap[0])])
+        if pattern == None:
+            snapshots = Datasets.snapshots[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*@.*%s" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for snapname,snaptime in Datasets.snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append([snapname, snaptime])
+        Datasets.snapshotslock.release()
+        return snapshots
+
+    def list_cloned_snapshots(self):
+        """
+        Returns a list of snapshots that have cloned filesystems
+        dependent on them.
+        Snapshots with cloned filesystems can not be destroyed
+        unless dependent cloned filesystems are first destroyed.
+        """
+        cmd = [ZFSCMD, "list", "-H", "-o", "origin"]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            details = line.rstrip()
+            if details != "-":
+                try:
+                    result.index(details)
+                except ValueError:
+                    result.append(details)
+        return result
+
+    def list_held_snapshots(self):
+        """
+        Returns a list of snapshots that have a "userrefs"
+        property value of greater than 0. Resul list is
+        sorted in order of creation time. Oldest listed first.
+        """
+        cmd = [ZFSCMD, "list", "-H",
+               "-t", "snapshot",
+               "-s", "creation",
+               "-o", "userrefs,name"]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            details = line.split()
+            if details[0] != "0":
+                result.append(details[1])
+        return result
+
+    def refresh_snapshots(self):
+        """
+        Should be called when snapshots have been created or deleted
+        and a rescan should be performed. Rescan gets deferred until
+        next invocation of zfs.Dataset.list_snapshots()
+        """
+        # FIXME in future.
+        # This is a little sub-optimal because we should be able to modify
+        # the snapshot list in place in some situations and regenerate the 
+        # snapshot list without calling out to zfs(1m). But on the
+        # pro side, we will pick up any new snapshots since the last
+        # scan that we would be otherwise unaware of.
+        Datasets.snapshotslock.acquire()
+        Datasets.snapshots = None
+        Datasets.snapshotslock.release()
+
+
+class ZPool:
+    """
+    Base class for ZFS storage pool objects
+    """
+    def __init__(self, name):
+        self.name = name
+        self.health = self.__get_health()
+        self.__datasets = Datasets()
+        self.__filesystems = None
+        self.__volumes = None
+        self.__snapshots = None
+
+    def __get_health(self):
+        """
+        Returns pool health status: 'ONLINE', 'DEGRADED' or 'FAULTED'
+        """
+        cmd = [ZPOOLCMD, "list", "-H", "-o", "health", self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        return result
+
+    def get_capacity(self):
+        """
+        Returns the percentage of total pool storage in use.
+        Calculated based on the "used" and "available" properties
+        of the pool's top-level filesystem because the values account
+        for reservations and quotas of children in their calculations,
+        giving a more practical indication of how much capacity is used
+        up on the pool.
+        """
+        if self.health == "FAULTED":
+            raise ZPoolFaultedError("Can not determine capacity of zpool: %s" \
+                                    "because it is in a FAULTED state" \
+                                    % (self.name))
+
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", \
+               "used,available", self.name]
+        outdata,errdata = util.run_command(cmd)
+        _used,_available = outdata.rstrip().split('\n')
+        used = float(_used)
+        available = float(_available) 
+        return 100.0 * used/(used + available)
+
+    def get_available_size(self):
+        """
+        How much unused space is available for use on this Zpool.
+        Answer in bytes.
+        """
+        # zpool(1) doesn't report available space in
+        # units suitable for calulations but zfs(1)
+        # can so use it to find the value for the
+        # filesystem matching the pool.
+        # The root filesystem of the pool is simply
+        # the pool name.
+        poolfs = Filesystem(self.name)
+        avail = poolfs.get_available_size()
+        return avail
+
+    def get_used_size(self):
+        """
+        How much space is in use on this Zpool.
+        Answer in bytes
+        """
+        # Same as ZPool.get_available_size(): zpool(1)
+        # doesn't generate suitable out put so use
+        # zfs(1) on the toplevel filesystem
+        if self.health == "FAULTED":
+            raise ZPoolFaultedError("Can not determine used size of zpool: %s" \
+                                    "because it is in a FAULTED state" \
+                                    % (self.name))
+        poolfs = Filesystem(self.name)
+        used = poolfs.get_used_size()
+        return used
+
+    def list_filesystems(self):
+        """
+        Return a list of filesystems on this Zpool.
+        List is sorted by name.
+        """
+        if self.__filesystems == None:
+            result = []
+            # Provides pre-sorted filesystem list
+            for fsname,fsmountpoint in self.__datasets.list_filesystems():
+                if re.match(self.name, fsname):
+                    result.append([fsname, fsmountpoint])
+            self.__filesystems = result
+        return self.__filesystems
+
+    def list_volumes(self):
+        """
+        Return a list of volumes (zvol) on this Zpool
+        List is sorted by name
+        """
+        if self.__volumes == None:
+            result = []
+            regexpattern = "^%s" % self.name
+            patternobj = re.compile(regexpattern)
+            for volname in self.__datasets.list_volumes():
+                patternmatchobj = re.match(patternobj, volname)
+                if patternmatchobj != None:
+                    result.append(volname)
+            result.sort()
+            self.__volumes = result
+        return self.__volumes
+
+    def list_auto_snapshot_sets(self, tag = None):
+        """
+        Returns a list of zfs filesystems and volumes tagged with
+        the "com.sun:auto-snapshot" property set to "true", either
+        set locally or inherited. Snapshots are excluded from the
+        returned result. Results are not sorted.
+
+        Keyword Arguments:
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        result = []
+        allsets = self.__datasets.list_auto_snapshot_sets(tag)
+        if len(allsets) == 0:
+            return result
+
+        regexpattern = "^%s" % self.name
+        patternobj = re.compile(regexpattern)
+        for datasetname in allsets:
+            patternmatchobj = re.match(patternobj, datasetname)
+            if patternmatchobj != None:
+                result.append(datasetname)
+        return result
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+           
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)   
+        """
+        # If there isn't a list of snapshots for this dataset
+        # already, create it now and store it in order to save
+        # time later for potential future invocations.
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            self.__snapshots = None
+        Datasets.snapshotslock.release()
+        if self.__snapshots == None:
+            result = []
+            regexpattern = "^%s.*@"  % self.name
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__datasets.list_snapshots():
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    result.append([snapname, snaptime])
+            # Results already sorted by creation time
+            self.__snapshots = result
+        if pattern == None:
+            return self.__snapshots
+        else:
+            snapshots = []
+            regexpattern = "^%s.*@.*%s" % (self.name, pattern)
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append([snapname, snaptime])
+            return snapshots
+
+    def __str__(self):
+        return_string = "ZPool name: " + self.name
+        return_string = return_string + "\n\tHealth: " + self.health
+        try:
+            return_string = return_string + \
+                            "\n\tUsed: " + \
+                            str(self.get_used_size()/BYTESPERMB) + "Mb"
+            return_string = return_string + \
+                            "\n\tAvailable: " + \
+                            str(self.get_available_size()/BYTESPERMB) + "Mb"
+            return_string = return_string + \
+                            "\n\tCapacity: " + \
+                            str(self.get_capacity()) + "%"
+        except ZPoolFaultedError:
+            pass
+        return return_string
+
+
+class ReadableDataset:
+    """
+    Base class for Filesystem, Volume and Snapshot classes
+    Provides methods for read only operations common to all.
+    """
+    def __init__(self, name, creation = None):
+        self.name = name
+        self.__creationTime = creation
+        self.datasets = Datasets()
+       self.__used_size = None
+
+    def __str__(self):
+        return_string = "ReadableDataset name: " + self.name + "\n"
+        return return_string
+
+    def get_creation_time(self):
+        if self.__creationTime == None:
+            cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "creation",
+                   self.name]
+            outdata,errdata = util.run_command(cmd)
+            self.__creationTime = long(outdata.rstrip())
+        return self.__creationTime
+
+    def exists(self):
+        """
+        Returns True if the dataset is still existent on the system.
+        False otherwise
+        """
+        # Test existance of the dataset by checking the output of a 
+        # simple zfs get command on the snapshot
+        cmd = [ZFSCMD, "get", "-H", "-o", "name", "type", self.name]
+        try:
+            p = subprocess.Popen(cmd,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE,
+                                 close_fds=True)
+            outdata,errdata = p.communicate()
+            err = p.wait()
+        except OSError, message:
+            raise RuntimeError, "%s subprocess error:\n %s" % \
+                            (command, str(message))
+        if err != 0:
+            # Doesn't exist
+            return False
+
+        result = outdata.rstrip()
+        if result == self.name:
+            return True
+        else:
+            return False
+
+    def get_used_size(self):
+       #print "fix get_used_size"
+       return 0
+       if self.__used_size == None:
+           cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "used", self.name]
+           outdata,errdata = util.run_command(cmd)
+           self.__used_size = long(outdata.rstrip())
+        return self.__used_size
+
+    def get_user_property(self, prop, local=False):
+        if local == True:
+            cmd = [ZFSCMD, "get", "-s", "local", "-H", "-o", "value", prop, self.name]
+        else:
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", prop, self.name]
+        outdata,errdata = util.run_command(cmd)
+        return outdata.rstrip()
+
+    def set_user_property(self, prop, value):
+        cmd = [PFCMD, ZFSCMD, "set", "%s=%s" % (prop, value), self.name]
+        outdata,errdata = util.run_command(cmd)
+    
+    def unset_user_property(self, prop):
+        cmd = [PFCMD, ZFSCMD, "inherit", prop, self.name]
+        outdata,errdata = util.run_command(cmd)
+
+class Snapshot(ReadableDataset):
+    """
+    ZFS Snapshot object class.
+    Provides information and operations specfic to ZFS snapshots
+    """    
+    def __init__(self, name, creation = None):
+        """
+        Keyword arguments:
+        name -- Name of the ZFS snapshot
+        creation -- Creation time of the snapshot if known (Default None)
+        """
+        ReadableDataset.__init__(self, name, creation)
+        self.fsname, self.snaplabel = self.__split_snapshot_name()
+        self.poolname = self.__get_pool_name()
+
+    def __get_pool_name(self):
+        name = self.fsname.split("/", 1)
+        return name[0]
+
+    def __split_snapshot_name(self):
+        name = self.name.split("@", 1)
+        # Make sure this is really a snapshot and not a
+        # filesystem otherwise a filesystem could get 
+        # destroyed instead of a snapshot. That would be
+        # really really bad.
+        if name[0] == self.name:
+            raise SnapshotError("\'%s\' is not a valid snapshot name" \
+                                % (self.name))
+        return name[0],name[1]
+
+    def get_referenced_size(self):
+        """
+        How much unique storage space is used by this snapshot.
+        Answer in bytes
+        """
+        cmd = [ZFSCMD, "get", "-H", "-p", \
+               "-o", "value", "referenced", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def list_children(self):
+        """Returns a recursive list of child snapshots of this snapshot"""
+        cmd = [ZFSCMD,
+               "list", "-t", "snapshot", "-H", "-r", "-o", "name",
+               self.fsname]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if re.search("@%s" % (self.snaplabel), line) and \
+                line != self.name:
+                    result.append(line)
+        return result
+
+    def has_clones(self):
+        """Returns True if the snapshot has any dependent clones"""
+        cmd = [ZFSCMD, "list", "-H", "-o", "origin,name"]
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            details = line.rstrip().split()
+            if details[0] == self.name and \
+                details[1] != '-':
+                return True
+        return False
+
+    def destroy_snapshot(self, deferred=True):
+        """
+        Permanently remove this snapshot from the filesystem
+        Performs deferred destruction by default.
+        """
+       print "destroy_snapshot %s" % self.name
+       return
+        # Be sure it genuninely exists before trying to destroy it
+        if self.exists() == False:
+            return
+        if deferred == False:
+            cmd = [PFCMD, ZFSCMD, "destroy", self.name]
+        else:
+            cmd = [PFCMD, ZFSCMD, "destroy", "-d", self.name]
+
+        outdata,errdata = util.run_command(cmd)
+        # Clear the global snapshot cache so that a rescan will be
+        # triggered on the next call to Datasets.list_snapshots()
+        self.datasets.refresh_snapshots()
+
+    def hold(self, tag):
+        """
+        Place a hold on the snapshot with the specified "tag" string.
+        """
+        # FIXME - fails if hold is already held
+        # Be sure it genuninely exists before trying to place a hold
+        if self.exists() == False:
+            return
+
+        cmd = [PFCMD, ZFSCMD, "hold", tag, self.name]
+        outdata,errdata = util.run_command(cmd)
+
+    def holds(self):
+        """
+        Returns a list of user hold tags for this snapshot
+        """
+        cmd = [ZFSCMD, "holds", self.name]
+        results = []
+        outdata,errdata = util.run_command(cmd)
+
+        for line in outdata.rstrip().split('\n'):
+            if len(line) == 0:
+                continue
+            # The first line heading columns are  NAME TAG TIMESTAMP
+            # Filter that line out.
+            line = line.split()
+            if (line[0] != "NAME" and line[1] != "TAG"):
+                results.append(line[1])
+        return results
+
+    def release(self, tag,):
+        """
+        Release the hold on the snapshot with the specified "tag" string.
+        """
+        # FIXME raises exception if no hold exists.
+        # Be sure it genuninely exists before trying to destroy it
+        if self.exists() == False:
+            return
+
+        cmd = [PFCMD, ZFSCMD, "release", tag, self.name]
+
+        outdata,errdata = util.run_command(cmd)
+        # Releasing the snapshot might cause it get automatically
+        # deleted by zfs.
+        # Clear the global snapshot cache so that a rescan will be
+        # triggered on the next call to Datasets.list_snapshots()
+        self.datasets.refresh_snapshots()
+
+
+    def __str__(self):
+        return_string = "Snapshot name: " + self.name
+        return_string = return_string + "\n\tCreation time: " \
+                        + str(self.get_creation_time())
+        return_string = return_string + "\n\tUsed Size: " \
+                        + str(self.get_used_size())
+        return_string = return_string + "\n\tReferenced Size: " \
+                        + str(self.get_referenced_size())
+        return return_string
+
+
+class ReadWritableDataset(ReadableDataset):
+    """
+    Base class for ZFS filesystems and volumes.
+    Provides methods for operations and properties
+    common to both filesystems and volumes.
+    """
+    def __init__(self, name, creation = None):
+        ReadableDataset.__init__(self, name, creation)
+        self.__snapshots = None
+
+    def __str__(self):
+        return_string = "ReadWritableDataset name: " + self.name + "\n"
+        return return_string
+
+    def get_auto_snap(self, schedule = None):
+        if schedule:
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", \
+               "com.sun:auto-snapshot", self.name]
+        cmd = [ZFSCMD, "get", "-H", "-o", "value", \
+               "com.sun:auto-snapshot", self.name]
+        outdata,errdata = util.run_command(cmd)
+        if outdata.rstrip() == "true":
+            return True
+        else:
+            return False
+
+    def get_available_size(self):
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "available", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def create_snapshot(self, snaplabel, recursive = False):
+        """
+        Create a snapshot for the ReadWritable dataset using the supplied
+        snapshot label.
+
+        Keyword Arguments:
+        snaplabel:
+            A string to use as the snapshot label.
+            The bit that comes after the "@" part of the snapshot
+            name.
+        recursive:
+            Recursively snapshot childfren of this dataset.
+            Default = False
+        """
+        cmd = [PFCMD, ZFSCMD, "snapshot"]
+        if recursive == True:
+            cmd.append("-r")
+        cmd.append("%s@%s" % (self.name, snaplabel))
+        outdata,errdata = util.run_command(cmd)
+        self.datasets.refresh_snapshots()
+
+    def list_children(self):
+        
+        # Note, if more dataset types ever come around they will
+        # need to be added to the filsystem,volume args below.
+        # Not for the forseeable future though.
+        cmd = [ZFSCMD, "list", "-H", "-r", "-t", "filesystem,volume",
+               "-o", "name", self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if line.rstrip() != self.name:
+                result.append(line.rstrip())
+        return result
+
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+           
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)   
+        """
+        # If there isn't a list of snapshots for this dataset
+        # already, create it now and store it in order to save
+        # time later for potential future invocations.
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            self.__snapshots = None
+        Datasets.snapshotslock.release()
+        if self.__snapshots == None:
+            result = []
+            regexpattern = "^%s@" % self.name
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.datasets.list_snapshots():
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    result.append([snapname, snaptime])
+            # Results already sorted by creation time
+            self.__snapshots = result
+        if pattern == None:
+            return self.__snapshots
+        else:
+            snapshots = []
+            regexpattern = "^%s@.*%s" % (self.name, pattern)
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append(snapname)
+            return snapshots
+
+    def set_auto_snap(self, include, inherit = False):
+        if inherit == True:
+            self.unset_user_property("com.sun:auto-snapshot")
+        else:
+            if include == True:
+                value = "true"
+            else:
+                value = "false"
+            self.set_user_property("com.sun:auto-snapshot", value)
+
+        return
+
+
+class Filesystem(ReadWritableDataset):
+    """ZFS Filesystem class"""
+    def __init__(self, name, mountpoint = None):
+        ReadWritableDataset.__init__(self, name)
+        self.__mountpoint = mountpoint
+
+    def __str__(self):
+        return_string = "Filesystem name: " + self.name + \
+                        "\n\tMountpoint: " + self.get_mountpoint() + \
+                        "\n\tMounted: " + str(self.is_mounted()) + \
+                        "\n\tAuto snap: " + str(self.get_auto_snap())
+        return return_string
+
+    def get_mountpoint(self):
+        if (self.__mountpoint == None):
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", "mountpoint", \
+                   self.name]
+            outdata,errdata = util.run_command(cmd)
+            result = outdata.rstrip()
+            self.__mountpoint = result
+        return self.__mountpoint
+
+    def is_mounted(self):
+        cmd = [ZFSCMD, "get", "-H", "-o", "value", "mounted", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        if result == "yes":
+            return True
+        else:
+            return False
+
+    def list_children(self):
+        cmd = [ZFSCMD, "list", "-H", "-r", "-t", "filesystem", "-o", "name",
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if line.rstrip() != self.name:
+                result.append(line.rstrip())
+        return result
+
+
+class Volume(ReadWritableDataset):
+    """
+    ZFS Volume Class
+    This is basically just a stub and does nothing
+    unique from ReadWritableDataset parent class.
+    """
+    def __init__(self, name):
+        ReadWritableDataset.__init__(self, name)
+
+    def __str__(self):
+        return_string = "Volume name: " + self.name + "\n"
+        return return_string
+
+
+class ZFSError(Exception):
+    """Generic base class for ZPoolFaultedError and SnapshotError
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __str__(self):
+        return repr(self.msg)
+
+
+class ZPoolFaultedError(ZFSError):
+    """Exception raised for queries made against ZPools that
+       are in a FAULTED state
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        ZFSError.__init__(self, msg)
+
+
+class SnapshotError(ZFSError):
+    """Exception raised for invalid snapshot names provided to
+       Snapshot() constructor.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        ZFSError.__init__(self, msg)
+
+
+def list_zpools():
+    """Returns a list of all zpools on the system"""
+    result = []
+    cmd = [ZPOOLCMD, "list", "-H", "-o", "name"]
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        result.append(line.rstrip())
+    return result
+
+
+if __name__ == "__main__":
+    for zpool in list_zpools():
+        pool = ZPool(zpool)
+        print pool
+        for filesys,mountpoint in pool.list_filesystems():
+            fs = Filesystem(filesys, mountpoint)
+            print fs
+            print "\tSnapshots:"
+            for snapshot, snaptime in fs.list_snapshots():
+                snap = Snapshot(snapshot, snaptime)
+                print "\t\t" + snap.name
+
+        for volname in pool.list_volumes():
+            vol = Volume(volname)
+            print vol
+            print "\tSnapshots:"
+            for snapshot, snaptime in vol.list_snapshots():
+                snap = Snapshot(snapshot, snaptime)
+                print "\t\t" + snap.name
+
+
diff --git a/usr/share/time-slider/lib/time_slider/zfs.py~ b/usr/share/time-slider/lib/time_slider/zfs.py~
new file mode 100755 (executable)
index 0000000..b35e58d
--- /dev/null
@@ -0,0 +1,1049 @@
+#!/usr/bin/python2.6
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+import subprocess
+import re
+import threading
+from bisect import insort, bisect_left, bisect_right
+
+import util
+
+BYTESPERMB = 1048576
+
+# Commonly used command paths
+PFCMD = "/usr/bin/pfexec"
+ZFSCMD = "/usr/sbin/zfs"
+ZPOOLCMD = "/usr/sbin/zpool"
+
+
+class Datasets(Exception):
+    """
+    Container class for all zfs datasets. Maintains a centralised
+    list of datasets (generated on demand) and accessor methods. 
+    Also allows clients to notify when a refresh might be necessary.
+    """
+    # Class wide instead of per-instance in order to avoid duplication
+    filesystems = None
+    volumes = None
+    snapshots = None
+    
+    # Mutex locks to prevent concurrent writes to above class wide
+    # dataset lists.
+    _filesystemslock = threading.Lock()
+    _volumeslock = threading.Lock()
+    snapshotslock = threading.Lock()
+
+    def create_auto_snapshot_set(self, label, tag = None):
+        """
+        Create a complete set of snapshots as if this were
+        for a standard zfs-auto-snapshot operation.
+        
+        Keyword arguments:
+        label:
+            A label to apply to the snapshot name. Cannot be None.
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" for will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        everything = []
+        included = []
+        excluded = []
+        single = []
+        recursive = []
+        finalrecursive = []
+
+        # Get auto-snap property in two passes. First with the schedule
+        # specific tag override value, then with the general property value
+        cmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+               "-o", "name,com.sun:auto-snapshot", "-s", "name"]
+        if tag:
+            overrideprop = "com.sun:auto-snapshot:" + tag
+            scmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+                    "-o", "name," + overrideprop, "-s", "name"]
+            outdata,errdata = util.run_command(scmd)
+            for line in outdata.rstrip().split('\n'):
+                line = line.split()
+                # Skip over unset values. 
+                if line[1] == "-":
+                    continue
+                # Add to everything list. This is used later
+                # for identifying parents/children of a given
+                # filesystem or volume.
+                everything.append(line[0])
+                if line[1] == "true":
+                    included.append(line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+        # Now use the general property. If no value
+        # was set in the first pass, we set it here.
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            line = line.split()
+            idx = bisect_right(everything, line[0])
+            if len(everything) == 0 or \
+               everything[idx-1] != line[0]:           
+                # Dataset is neither included nor excluded so far
+                if line[1] == "-":
+                    continue
+                everything.insert(idx, line[0])
+                if line[1] == "true":
+                    included.insert(0, line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+
+        # Now figure out what can be recursively snapshotted and what
+        # must be singly snapshotted. Single snapshot restrictions apply
+        # to those datasets who have a child in the excluded list.
+        # 'included' is sorted in reverse alphabetical order. 
+        for datasetname in included:
+            excludedchild = False
+            idx = bisect_right(everything, datasetname)
+            children = [name for name in everything[idx:] if \
+                        name.find(datasetname) == 0]
+            for child in children:
+                idx = bisect_left(excluded, child)
+                if idx < len(excluded) and excluded[idx] == child:
+                    excludedchild = True
+                    single.append(datasetname)
+                    break
+            if excludedchild == False:
+                # We want recursive list sorted in alphabetical order
+                # so insert instead of append to the list.
+                recursive.insert(0, datasetname)
+
+        for datasetname in recursive:
+            parts = datasetname.rsplit('/', 1)
+            parent = parts[0]
+            if parent == datasetname:
+                # Root filesystem of the Zpool, so
+                # this can't be inherited and must be
+                # set locally.
+                finalrecursive.append(datasetname)
+                continue
+            idx = bisect_right(recursive, parent)
+            if len(recursive) > 0 and \
+               recursive[idx-1] == parent:
+                # Parent already marked for recursive snapshot: so skip
+                continue
+            else:
+                finalrecursive.append(datasetname)
+
+        for name in finalrecursive:
+            dataset = ReadWritableDataset(name)
+            dataset.create_snapshot(label, True)
+        for name in single:
+            dataset = ReadWritableDataset(name)
+            dataset.create_snapshot(label, False)
+
+    def list_auto_snapshot_sets(self, tag = None):
+        """
+        Returns a list of zfs filesystems and volumes tagged with
+        the "com.sun:auto-snapshot" property set to "true", either
+        set locally or inherited. Snapshots are excluded from the
+        returned result.
+
+        Keyword Arguments:
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        #Get auto-snap property in two passes. First with the global
+        #value, then overriding with the label/schedule specific value
+
+        included = []
+        excluded = []
+
+        cmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+               "-o", "name,com.sun:auto-snapshot", "-s", "name"]
+        if tag:
+            overrideprop = "com.sun:auto-snapshot:" + tag
+            scmd = [ZFSCMD, "list", "-H", "-t", "filesystem,volume",
+                    "-o", "name," + overrideprop, "-s", "name"]
+            outdata,errdata = util.run_command(scmd)
+            for line in outdata.rstrip().split('\n'):
+                line = line.split()
+                if line[1] == "true":
+                    included.append(line[0])
+                elif line[1] == "false":
+                    excluded.append(line[0])
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            line = line.split()
+            # Only set values that aren't already set. Don't override
+            try:
+                included.index(line[0])
+                continue
+            except ValueError:
+                try:
+                    excluded.index(line[0])
+                    continue
+                except ValueError:
+                    # Dataset is not listed in either list.
+                    if line[1] == "true":
+                        included.append(line[0])
+        return included
+
+    def list_filesystems(self, pattern = None):
+        """
+        List pattern matching filesystems sorted by name.
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        filesystems = []
+        # Need to first ensure no other thread is trying to
+        # build this list at the same time.
+        Datasets._filesystemslock.acquire()
+        if Datasets.filesystems == None:
+            Datasets.filesystems = []
+            cmd = [ZFSCMD, "list", "-H", "-t", "filesystem", \
+                   "-o", "name,mountpoint", "-s", "name"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err = p.wait()
+            except OSError, message:
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets._filesystemslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for line in outdata.rstrip().split('\n'):
+                line = line.rstrip().split()
+                Datasets.filesystems.append([line[0], line[1]])
+        Datasets._filesystemslock.release()
+
+        if pattern == None:
+            filesystems = Datasets.filesystems[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*%s.*" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for fsname,fsmountpoint in Datasets.filesystems:
+                patternmatchobj = re.match(patternobj, fsname)
+                if patternmatchobj != None:
+                    filesystems.append(fsname, fsmountpoint)
+        return filesystems
+
+    def list_volumes(self, pattern = None):
+        """
+        List pattern matching volumes sorted by name.
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        volumes = []
+        Datasets._volumeslock.acquire()
+        if Datasets.volumes == None:
+            Datasets.volumes = []
+            cmd = [ZFSCMD, "list", "-H", "-t", "volume", \
+                   "-o", "name", "-s", "name"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err = p.wait()
+            except OSError, message:
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets._volumeslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for line in outdata.rstrip().split('\n'):
+                Datasets.volumes.append(line.rstrip())
+        Datasets._volumeslock.release()
+
+        if pattern == None:
+            volumes = Datasets.volumes[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*%s.*" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for volname in Datasets.volumes:
+                patternmatchobj = re.match(patternobj, volname)
+                if patternmatchobj != None:
+                    volumes.append(volname)
+        return volumes
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+        
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)
+        """
+        snapshots = []
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            Datasets.snapshots = []
+            snaps = []
+            cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value,name", "creation"]
+            try:
+                p = subprocess.Popen(cmd,
+                                     stdout=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     close_fds=True)
+                outdata,errdata = p.communicate()
+                err= p.wait()
+            except OSError, message:
+                Datasets.snapshotslock.release()
+                raise RuntimeError, "%s subprocess error:\n %s" % \
+                                    (cmd, str(message))
+            if err != 0:
+                Datasets.snapshotslock.release()
+                raise RuntimeError, '%s failed with exit code %d\n%s' % \
+                                    (str(cmd), err, errdata)
+            for dataset in outdata.rstrip().split('\n'):
+                if re.search("@", dataset):
+                    insort(snaps, dataset.split())
+            for snap in snaps:
+                Datasets.snapshots.append([snap[1], long(snap[0])])
+        if pattern == None:
+            snapshots = Datasets.snapshots[:]
+        else:
+            # Regular expression pattern to match "pattern" parameter.
+            regexpattern = ".*@.*%s" % pattern
+            patternobj = re.compile(regexpattern)
+
+            for snapname,snaptime in Datasets.snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append([snapname, snaptime])
+        Datasets.snapshotslock.release()
+        return snapshots
+
+    def list_cloned_snapshots(self):
+        """
+        Returns a list of snapshots that have cloned filesystems
+        dependent on them.
+        Snapshots with cloned filesystems can not be destroyed
+        unless dependent cloned filesystems are first destroyed.
+        """
+        cmd = [ZFSCMD, "list", "-H", "-o", "origin"]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            details = line.rstrip()
+            if details != "-":
+                try:
+                    result.index(details)
+                except ValueError:
+                    result.append(details)
+        return result
+
+    def list_held_snapshots(self):
+        """
+        Returns a list of snapshots that have a "userrefs"
+        property value of greater than 0. Resul list is
+        sorted in order of creation time. Oldest listed first.
+        """
+        cmd = [ZFSCMD, "list", "-H",
+               "-t", "snapshot",
+               "-s", "creation",
+               "-o", "userrefs,name"]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            details = line.split()
+            if details[0] != "0":
+                result.append(details[1])
+        return result
+
+    def refresh_snapshots(self):
+        """
+        Should be called when snapshots have been created or deleted
+        and a rescan should be performed. Rescan gets deferred until
+        next invocation of zfs.Dataset.list_snapshots()
+        """
+        # FIXME in future.
+        # This is a little sub-optimal because we should be able to modify
+        # the snapshot list in place in some situations and regenerate the 
+        # snapshot list without calling out to zfs(1m). But on the
+        # pro side, we will pick up any new snapshots since the last
+        # scan that we would be otherwise unaware of.
+        Datasets.snapshotslock.acquire()
+        Datasets.snapshots = None
+        Datasets.snapshotslock.release()
+
+
+class ZPool:
+    """
+    Base class for ZFS storage pool objects
+    """
+    def __init__(self, name):
+        self.name = name
+        self.health = self.__get_health()
+        self.__datasets = Datasets()
+        self.__filesystems = None
+        self.__volumes = None
+        self.__snapshots = None
+
+    def __get_health(self):
+        """
+        Returns pool health status: 'ONLINE', 'DEGRADED' or 'FAULTED'
+        """
+        cmd = [ZPOOLCMD, "list", "-H", "-o", "health", self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        return result
+
+    def get_capacity(self):
+        """
+        Returns the percentage of total pool storage in use.
+        Calculated based on the "used" and "available" properties
+        of the pool's top-level filesystem because the values account
+        for reservations and quotas of children in their calculations,
+        giving a more practical indication of how much capacity is used
+        up on the pool.
+        """
+        if self.health == "FAULTED":
+            raise ZPoolFaultedError("Can not determine capacity of zpool: %s" \
+                                    "because it is in a FAULTED state" \
+                                    % (self.name))
+
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", \
+               "used,available", self.name]
+        outdata,errdata = util.run_command(cmd)
+        _used,_available = outdata.rstrip().split('\n')
+        used = float(_used)
+        available = float(_available) 
+        return 100.0 * used/(used + available)
+
+    def get_available_size(self):
+        """
+        How much unused space is available for use on this Zpool.
+        Answer in bytes.
+        """
+        # zpool(1) doesn't report available space in
+        # units suitable for calulations but zfs(1)
+        # can so use it to find the value for the
+        # filesystem matching the pool.
+        # The root filesystem of the pool is simply
+        # the pool name.
+        poolfs = Filesystem(self.name)
+        avail = poolfs.get_available_size()
+        return avail
+
+    def get_used_size(self):
+        """
+        How much space is in use on this Zpool.
+        Answer in bytes
+        """
+        # Same as ZPool.get_available_size(): zpool(1)
+        # doesn't generate suitable out put so use
+        # zfs(1) on the toplevel filesystem
+        if self.health == "FAULTED":
+            raise ZPoolFaultedError("Can not determine used size of zpool: %s" \
+                                    "because it is in a FAULTED state" \
+                                    % (self.name))
+        poolfs = Filesystem(self.name)
+        used = poolfs.get_used_size()
+        return used
+
+    def list_filesystems(self):
+        """
+        Return a list of filesystems on this Zpool.
+        List is sorted by name.
+        """
+        if self.__filesystems == None:
+            result = []
+            # Provides pre-sorted filesystem list
+            for fsname,fsmountpoint in self.__datasets.list_filesystems():
+                if re.match(self.name, fsname):
+                    result.append([fsname, fsmountpoint])
+            self.__filesystems = result
+        return self.__filesystems
+
+    def list_volumes(self):
+        """
+        Return a list of volumes (zvol) on this Zpool
+        List is sorted by name
+        """
+        if self.__volumes == None:
+            result = []
+            regexpattern = "^%s" % self.name
+            patternobj = re.compile(regexpattern)
+            for volname in self.__datasets.list_volumes():
+                patternmatchobj = re.match(patternobj, volname)
+                if patternmatchobj != None:
+                    result.append(volname)
+            result.sort()
+            self.__volumes = result
+        return self.__volumes
+
+    def list_auto_snapshot_sets(self, tag = None):
+        """
+        Returns a list of zfs filesystems and volumes tagged with
+        the "com.sun:auto-snapshot" property set to "true", either
+        set locally or inherited. Snapshots are excluded from the
+        returned result. Results are not sorted.
+
+        Keyword Arguments:
+        tag:
+            A string indicating one of the standard auto-snapshot schedules
+            tags to check (eg. "frequent" will map to the tag:
+            com.sun:auto-snapshot:frequent). If specified as a zfs property
+            on a zfs dataset, the property corresponding to the tag will 
+            override the wildcard property: "com.sun:auto-snapshot"
+            Default value = None
+        """
+        result = []
+        allsets = self.__datasets.list_auto_snapshot_sets(tag)
+        if len(allsets) == 0:
+            return result
+
+        regexpattern = "^%s" % self.name
+        patternobj = re.compile(regexpattern)
+        for datasetname in allsets:
+            patternmatchobj = re.match(patternobj, datasetname)
+            if patternmatchobj != None:
+                result.append(datasetname)
+        return result
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+           
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)   
+        """
+        # If there isn't a list of snapshots for this dataset
+        # already, create it now and store it in order to save
+        # time later for potential future invocations.
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            self.__snapshots = None
+        Datasets.snapshotslock.release()
+        if self.__snapshots == None:
+            result = []
+            regexpattern = "^%s.*@"  % self.name
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__datasets.list_snapshots():
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    result.append([snapname, snaptime])
+            # Results already sorted by creation time
+            self.__snapshots = result
+        if pattern == None:
+            return self.__snapshots
+        else:
+            snapshots = []
+            regexpattern = "^%s.*@.*%s" % (self.name, pattern)
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append([snapname, snaptime])
+            return snapshots
+
+    def __str__(self):
+        return_string = "ZPool name: " + self.name
+        return_string = return_string + "\n\tHealth: " + self.health
+        try:
+            return_string = return_string + \
+                            "\n\tUsed: " + \
+                            str(self.get_used_size()/BYTESPERMB) + "Mb"
+            return_string = return_string + \
+                            "\n\tAvailable: " + \
+                            str(self.get_available_size()/BYTESPERMB) + "Mb"
+            return_string = return_string + \
+                            "\n\tCapacity: " + \
+                            str(self.get_capacity()) + "%"
+        except ZPoolFaultedError:
+            pass
+        return return_string
+
+
+class ReadableDataset:
+    """
+    Base class for Filesystem, Volume and Snapshot classes
+    Provides methods for read only operations common to all.
+    """
+    def __init__(self, name, creation = None):
+        self.name = name
+        self.__creationTime = creation
+        self.datasets = Datasets()
+
+    def __str__(self):
+        return_string = "ReadableDataset name: " + self.name + "\n"
+        return return_string
+
+    def get_creation_time(self):
+        if self.__creationTime == None:
+            cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "creation",
+                   self.name]
+            outdata,errdata = util.run_command(cmd)
+            self.__creationTime = long(outdata.rstrip())
+        return self.__creationTime
+
+    def exists(self):
+        """
+        Returns True if the dataset is still existent on the system.
+        False otherwise
+        """
+        # Test existance of the dataset by checking the output of a 
+        # simple zfs get command on the snapshot
+        cmd = [ZFSCMD, "get", "-H", "-o", "name", "type", self.name]
+        try:
+            p = subprocess.Popen(cmd,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE,
+                                 close_fds=True)
+            outdata,errdata = p.communicate()
+            err = p.wait()
+        except OSError, message:
+            raise RuntimeError, "%s subprocess error:\n %s" % \
+                            (command, str(message))
+        if err != 0:
+            # Doesn't exist
+            return False
+
+        result = outdata.rstrip()
+        if result == self.name:
+            return True
+        else:
+            return False
+
+    def get_used_size(self):
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "used", self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def get_user_property(self, prop, local=False):
+        if local == True:
+            cmd = [ZFSCMD, "get", "-s", "local", "-H", "-o", "value", prop, self.name]
+        else:
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", prop, self.name]
+        outdata,errdata = util.run_command(cmd)
+        return outdata.rstrip()
+
+    def set_user_property(self, prop, value):
+        cmd = [PFCMD, ZFSCMD, "set", "%s=%s" % (prop, value), self.name]
+        outdata,errdata = util.run_command(cmd)
+    
+    def unset_user_property(self, prop):
+        cmd = [PFCMD, ZFSCMD, "inherit", prop, self.name]
+        outdata,errdata = util.run_command(cmd)
+
+class Snapshot(ReadableDataset):
+    """
+    ZFS Snapshot object class.
+    Provides information and operations specfic to ZFS snapshots
+    """    
+    def __init__(self, name, creation = None):
+        """
+        Keyword arguments:
+        name -- Name of the ZFS snapshot
+        creation -- Creation time of the snapshot if known (Default None)
+        """
+        ReadableDataset.__init__(self, name, creation)
+        self.fsname, self.snaplabel = self.__split_snapshot_name()
+        self.poolname = self.__get_pool_name()
+
+    def __get_pool_name(self):
+        name = self.fsname.split("/", 1)
+        return name[0]
+
+    def __split_snapshot_name(self):
+        name = self.name.split("@", 1)
+        # Make sure this is really a snapshot and not a
+        # filesystem otherwise a filesystem could get 
+        # destroyed instead of a snapshot. That would be
+        # really really bad.
+        if name[0] == self.name:
+            raise SnapshotError("\'%s\' is not a valid snapshot name" \
+                                % (self.name))
+        return name[0],name[1]
+
+    def get_referenced_size(self):
+        """
+        How much unique storage space is used by this snapshot.
+        Answer in bytes
+        """
+        cmd = [ZFSCMD, "get", "-H", "-p", \
+               "-o", "value", "referenced", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def list_children(self):
+        """Returns a recursive list of child snapshots of this snapshot"""
+        cmd = [ZFSCMD,
+               "list", "-t", "snapshot", "-H", "-r", "-o", "name",
+               self.fsname]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if re.search("@%s" % (self.snaplabel), line) and \
+                line != self.name:
+                    result.append(line)
+        return result
+
+    def has_clones(self):
+        """Returns True if the snapshot has any dependent clones"""
+        cmd = [ZFSCMD, "list", "-H", "-o", "origin,name"]
+        outdata,errdata = util.run_command(cmd)
+        for line in outdata.rstrip().split('\n'):
+            details = line.rstrip().split()
+            if details[0] == self.name and \
+                details[1] != '-':
+                return True
+        return False
+
+    def destroy(self, deferred=True):
+        """
+        Permanently remove this snapshot from the filesystem
+        Performs deferred destruction by default.
+        """
+        # Be sure it genuninely exists before trying to destroy it
+        if self.exists() == False:
+            return
+        if deferred == False:
+            cmd = [PFCMD, ZFSCMD, "destroy", self.name]
+        else:
+            cmd = [PFCMD, ZFSCMD, "destroy", "-d", self.name]
+
+        outdata,errdata = util.run_command(cmd)
+        # Clear the global snapshot cache so that a rescan will be
+        # triggered on the next call to Datasets.list_snapshots()
+        self.datasets.refresh_snapshots()
+
+    def hold(self, tag):
+        """
+        Place a hold on the snapshot with the specified "tag" string.
+        """
+        # FIXME - fails if hold is already held
+        # Be sure it genuninely exists before trying to place a hold
+        if self.exists() == False:
+            return
+
+        cmd = [PFCMD, ZFSCMD, "hold", tag, self.name]
+        outdata,errdata = util.run_command(cmd)
+
+    def holds(self):
+        """
+        Returns a list of user hold tags for this snapshot
+        """
+        cmd = [ZFSCMD, "holds", self.name]
+        results = []
+        outdata,errdata = util.run_command(cmd)
+
+        for line in outdata.rstrip().split('\n'):
+            if len(line) == 0:
+                continue
+            # The first line heading columns are  NAME TAG TIMESTAMP
+            # Filter that line out.
+            line = line.split()
+            if (line[0] != "NAME" and line[1] != "TAG"):
+                results.append(line[1])
+        return results
+
+    def release(self, tag,):
+        """
+        Release the hold on the snapshot with the specified "tag" string.
+        """
+        # FIXME raises exception if no hold exists.
+        # Be sure it genuninely exists before trying to destroy it
+        if self.exists() == False:
+            return
+
+        cmd = [PFCMD, ZFSCMD, "release", tag, self.name]
+
+        outdata,errdata = util.run_command(cmd)
+        # Releasing the snapshot might cause it get automatically
+        # deleted by zfs.
+        # Clear the global snapshot cache so that a rescan will be
+        # triggered on the next call to Datasets.list_snapshots()
+        self.datasets.refresh_snapshots()
+
+
+    def __str__(self):
+        return_string = "Snapshot name: " + self.name
+        return_string = return_string + "\n\tCreation time: " \
+                        + str(self.get_creation_time())
+        return_string = return_string + "\n\tUsed Size: " \
+                        + str(self.get_used_size())
+        return_string = return_string + "\n\tReferenced Size: " \
+                        + str(self.get_referenced_size())
+        return return_string
+
+
+class ReadWritableDataset(ReadableDataset):
+    """
+    Base class for ZFS filesystems and volumes.
+    Provides methods for operations and properties
+    common to both filesystems and volumes.
+    """
+    def __init__(self, name, creation = None):
+        ReadableDataset.__init__(self, name, creation)
+        self.__snapshots = None
+
+    def __str__(self):
+        return_string = "ReadWritableDataset name: " + self.name + "\n"
+        return return_string
+
+    def get_auto_snap(self, schedule = None):
+        if schedule:
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", \
+               "com.sun:auto-snapshot", self.name]
+        cmd = [ZFSCMD, "get", "-H", "-o", "value", \
+               "com.sun:auto-snapshot", self.name]
+        outdata,errdata = util.run_command(cmd)
+        if outdata.rstrip() == "true":
+            return True
+        else:
+            return False
+
+    def get_available_size(self):
+        cmd = [ZFSCMD, "get", "-H", "-p", "-o", "value", "available", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        return long(outdata.rstrip())
+
+    def create_snapshot(self, snaplabel, recursive = False):
+        """
+        Create a snapshot for the ReadWritable dataset using the supplied
+        snapshot label.
+
+        Keyword Arguments:
+        snaplabel:
+            A string to use as the snapshot label.
+            The bit that comes after the "@" part of the snapshot
+            name.
+        recursive:
+            Recursively snapshot childfren of this dataset.
+            Default = False
+        """
+        cmd = [PFCMD, ZFSCMD, "snapshot"]
+        if recursive == True:
+            cmd.append("-r")
+        cmd.append("%s@%s" % (self.name, snaplabel))
+        outdata,errdata = util.run_command(cmd, False)
+       if errdata:
+         print errdata
+        self.datasets.refresh_snapshots()
+
+    def list_children(self):
+        
+        # Note, if more dataset types ever come around they will
+        # need to be added to the filsystem,volume args below.
+        # Not for the forseeable future though.
+        cmd = [ZFSCMD, "list", "-H", "-r", "-t", "filesystem,volume",
+               "-o", "name", self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if line.rstrip() != self.name:
+                result.append(line.rstrip())
+        return result
+
+
+    def list_snapshots(self, pattern = None):
+        """
+        List pattern matching snapshots sorted by creation date.
+        Oldest listed first
+           
+        Keyword arguments:
+        pattern -- Filter according to pattern (default None)   
+        """
+        # If there isn't a list of snapshots for this dataset
+        # already, create it now and store it in order to save
+        # time later for potential future invocations.
+        Datasets.snapshotslock.acquire()
+        if Datasets.snapshots == None:
+            self.__snapshots = None
+        Datasets.snapshotslock.release()
+        if self.__snapshots == None:
+            result = []
+            regexpattern = "^%s@" % self.name
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.datasets.list_snapshots():
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    result.append([snapname, snaptime])
+            # Results already sorted by creation time
+            self.__snapshots = result
+        if pattern == None:
+            return self.__snapshots
+        else:
+            snapshots = []
+            regexpattern = "^%s@.*%s" % (self.name, pattern)
+            patternobj = re.compile(regexpattern)
+            for snapname,snaptime in self.__snapshots:
+                patternmatchobj = re.match(patternobj, snapname)
+                if patternmatchobj != None:
+                    snapshots.append(snapname)
+            return snapshots
+
+    def set_auto_snap(self, include, inherit = False):
+        if inherit == True:
+            self.unset_user_property("com.sun:auto-snapshot")
+        else:
+            if include == True:
+                value = "true"
+            else:
+                value = "false"
+            self.set_user_property("com.sun:auto-snapshot", value)
+
+        return
+
+
+class Filesystem(ReadWritableDataset):
+    """ZFS Filesystem class"""
+    def __init__(self, name, mountpoint = None):
+        ReadWritableDataset.__init__(self, name)
+        self.__mountpoint = mountpoint
+
+    def __str__(self):
+        return_string = "Filesystem name: " + self.name + \
+                        "\n\tMountpoint: " + self.get_mountpoint() + \
+                        "\n\tMounted: " + str(self.is_mounted()) + \
+                        "\n\tAuto snap: " + str(self.get_auto_snap())
+        return return_string
+
+    def get_mountpoint(self):
+        if (self.__mountpoint == None):
+            cmd = [ZFSCMD, "get", "-H", "-o", "value", "mountpoint", \
+                   self.name]
+            outdata,errdata = util.run_command(cmd)
+            result = outdata.rstrip()
+            self.__mountpoint = result
+        return self.__mountpoint
+
+    def is_mounted(self):
+        cmd = [ZFSCMD, "get", "-H", "-o", "value", "mounted", \
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = outdata.rstrip()
+        if result == "yes":
+            return True
+        else:
+            return False
+
+    def list_children(self):
+        cmd = [ZFSCMD, "list", "-H", "-r", "-t", "filesystem", "-o", "name",
+               self.name]
+        outdata,errdata = util.run_command(cmd)
+        result = []
+        for line in outdata.rstrip().split('\n'):
+            if line.rstrip() != self.name:
+                result.append(line.rstrip())
+        return result
+
+
+class Volume(ReadWritableDataset):
+    """
+    ZFS Volume Class
+    This is basically just a stub and does nothing
+    unique from ReadWritableDataset parent class.
+    """
+    def __init__(self, name):
+        ReadWritableDataset.__init__(self, name)
+
+    def __str__(self):
+        return_string = "Volume name: " + self.name + "\n"
+        return return_string
+
+
+class ZFSError(Exception):
+    """Generic base class for ZPoolFaultedError and SnapshotError
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __str__(self):
+        return repr(self.msg)
+
+
+class ZPoolFaultedError(ZFSError):
+    """Exception raised for queries made against ZPools that
+       are in a FAULTED state
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        ZFSError.__init__(self, msg)
+
+
+class SnapshotError(ZFSError):
+    """Exception raised for invalid snapshot names provided to
+       Snapshot() constructor.
+
+    Attributes:
+        msg -- explanation of the error
+    """
+    def __init__(self, msg):
+        ZFSError.__init__(self, msg)
+
+
+def list_zpools():
+    """Returns a list of all zpools on the system"""
+    result = []
+    cmd = [ZPOOLCMD, "list", "-H", "-o", "name"]
+    outdata,errdata = util.run_command(cmd)
+    for line in outdata.rstrip().split('\n'):
+        result.append(line.rstrip())
+    return result
+
+
+if __name__ == "__main__":
+    for zpool in list_zpools():
+        pool = ZPool(zpool)
+        print pool
+        for filesys,mountpoint in pool.list_filesystems():
+            fs = Filesystem(filesys, mountpoint)
+            print fs
+            print "\tSnapshots:"
+            for snapshot, snaptime in fs.list_snapshots():
+                snap = Snapshot(snapshot, snaptime)
+                print "\t\t" + snap.name
+
+        for volname in pool.list_volumes():
+            vol = Volume(volname)
+            print vol
+            print "\tSnapshots:"
+            for snapshot, snaptime in vol.list_snapshots():
+                snap = Snapshot(snapshot, snaptime)
+                print "\t\t" + snap.name
+
diff --git a/var/svc/manifest/application/time-slider-plugin.xml b/var/svc/manifest/application/time-slider-plugin.xml
new file mode 100644 (file)
index 0000000..5e98b02
--- /dev/null
@@ -0,0 +1,256 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.0 only
+ (the "License").  You may not use this file except in compliance
+ with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+-->
+
+<service_bundle type='manifest' name='SUNWgnome-time-slider'>
+
+<service
+       name='application/time-slider/plugin'
+       type='service'
+       version='0.2.96'>
+
+       <!-- we need time-slider  -->
+       <dependency
+               name='time-slider'
+               grouping='require_all'
+               restart_on='refresh'
+               type='service'>
+               <service_fmri value='svc:/application/time-slider' />
+       </dependency>
+
+       <!--
+           These are bare bones, basic plugin methods. More
+           complex plugin instances should define their own
+           specifically tailored start/stop/refresh methods.
+       -->
+       <exec_method
+               type='method'
+               name='start'
+               exec='/lib/svc/method/time-slider-plugin start'
+               timeout_seconds='10'>
+    </exec_method>
+
+       <exec_method
+               type='method'
+               name='stop'
+               exec=':true'
+               timeout_seconds='10'>
+       </exec_method>
+
+       <property_group name='startd' type='framework'>
+               <propval name='duration' type='astring' value='transient' />
+       </property_group>
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+                       value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+                       value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+
+       <!-- The properties we expect that any plugin instance will define:
+
+       trigger_command: A fully expanded command path plus all required arguments for
+                invocation of the plugin's trigger command. The purpose of
+                trigger_command is for notification when time-sliderd has created a
+                set of scheduled snapshots. The plugin can opt to take action immediately
+                or defer further actions until some later stage.
+
+       verbose: Send extra, verbose output to standard error and syslog for
+             analytical and debugging purposes if set to "true"
+    trigger_on: A comma seperated list of auto-snapshot SMF service instances
+                upon which to execute the command specified by plugin/command.
+                The keyword "all" serves as a wildcard value matching all
+                enabled auto-snapshot SMF instances, or as an example, a value
+                of "hourly,daily" would trigger the plugin for snapshot events
+                corresponding to the following SMF service instances:
+                svc://system/filesystem/zfs/auto-snapshot:hourly
+                svc://system/filesystem/zfs/auto-snapsoht:daily
+        -->
+
+       <property_group name="plugin" type="application">
+               <propval name="trigger_command" type="astring"
+                       value="Not Set" override="true"/>
+               <propval name="verbose" type="boolean"
+                       value="false" override="true"/>
+               <propval name="trigger_on" type="astring"
+                       value="hourly,daily,weekly,monthly" override="true"/>
+       </property_group>
+
+
+       <!-- We now define a plugin instance: "zfs-send"
+            to perform "zfs(1) send" based backups--> 
+
+       <!-- This instance sends full or if possible, incremental
+            snapshot streams of the newly created snapshots.
+            Incremental streams are determined by the existance of the
+            zfs property:
+            "org.opensolaris:time-slider-plugin:zfs-send".
+
+            The value of this property represents the snapshot label
+            after the "@" of the previously sent snapshot and is set on
+            each filesystem or volume that was previously backed up using
+            the zfs-send plugin instance.
+            To force a full send of the snapshot stream, this property
+            needs to be unset using "zfs(1) inherit"
+
+            In order to avoid deletion of the previously backed up snapshot
+            necessary for sending incremental snapshot streams, the zfs-send
+            plugin instance places a "zfs(1) hold" on each backed up snapshot
+            using the following tag:
+            
+            "org.opensolaris:time-slider-plugin:zfs-send"
+            
+            Before attempting to commence a subsequent snapshot backup, a 
+            hold is placed on the new snapshot using the above tag.
+            When the subsequent backup completes successfully, the hold on the
+            previous snapshot is released.
+
+                If a snapshot backup, either incremental or full fails for any reason,
+                the hold on the effected snapshots is not released. The administrator
+                will need to release these holds once the backup problem is fixed. 
+       -->
+
+       <instance name='zfs-send' enabled='false' >
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name="plugin" type="application">
+               <propval name="command"
+                       type="astring" value="/usr/lib/time-slider/plugins/zfssend/zfssend" override="true"/>
+       </property_group>
+
+       <!-- Specify the command used to receive the snapshot stream.
+            The command will be executed via. pfexec(1).
+            As an example:
+            "/usr/sbin/zfs receive -F -u -d backuppool"
+            would receive snapshots streams locally to "backupool", overwriting
+            any pre-existing clashing fileystems on homepool, would not attempt to
+            mount the fileystem. See zfs(1) for more details
+       -->
+
+       <property_group name="receive" type="application">
+               <propval name="command"
+                       type="astring" value="" override="true"/>
+       </property_group>
+       </instance>
+
+
+       <instance name='rsync' enabled='false' >
+
+       <exec_method
+               type='method'
+               name='start'
+               exec='/lib/svc/method/time-slider-rsync start'
+               timeout_seconds='10'>
+    </exec_method>
+
+       <exec_method
+               type='method'
+               name='stop'
+               exec='/lib/svc/method/time-slider-rsync stop'
+               timeout_seconds='10'>
+       </exec_method>
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name="plugin" type="application">
+               <propval name="trigger_command"
+                       type="astring" value="/usr/lib/time-slider/plugins/rsync/rsync-trigger" override="true"/>
+       </property_group>
+
+       <property_group name="rsync" type="application">
+               <propval name="target_dir"
+                       type="astring" value="" override="true"/>
+               <propval name="target_key"
+                       type="astring" value='' override="true"/>
+        <!-- Backups matching a schedule in this list will not be
+             expired according to the standard auto-snapshot retention
+             rules, and will instead be archived indefinitely on
+             target_dir until it becomes necessary to delete them in
+             order to recover space on target_dir.
+        -->
+        <propval name="archived_schedules"
+                       type="astring" value="weekly,monthly" override="true"/>
+        <!-- Percentage of file system utilisation at which point
+             this plugin will start deleting indefinitely archived
+             backups in order to avoid the filesystem filling up
+             completely. Backups get deleted in reverse chronological
+             order. ie. oldest first until capacity falls back below
+             cleanup_threshold's value, or there is only 1 remaining
+             backup per fileystem remaining on the device, at which
+             point it gives up.
+        -->
+               <propval name="cleanup_threshold"
+                       type="integer" value="95" override="true"/>
+        <!-- If set to true, instruct rsync to produce extra verbose
+                output using rsync's "-vv" command line option. Note that
+                this is independent of the generic <plugin/verbose> 
+                property, which governs verbosity of the plugin itself
+                and not specifically rsync.
+        -->
+               <propval name="verbose"
+                       type="boolean" value="false" override="true"/>
+       </property_group>
+       </instance>
+
+       <stability value='Unstable' />
+
+       <template>
+               <common_name>
+                       <loctext xml:lang='C'>Time Slider Plugin Framework</loctext>
+               </common_name>
+               <description>
+                       <loctext xml:lang='C'>
+This service provides a mechanism for defining plugin actions for Time Slider
+
+In order to use this service, you must enable the time-slider service plus at least one auto-snapshot
+instance per set of automatic snapshots you want to take in addition to one or more Time Slider plugin
+instnace.
+When enabled, the time-slider service will execute the command defined by the plugin's SMF property
+"plugin/command" after it creates snapshot(s) according to an enabled auto-snapshot instance.
+
+Time Slider provides the following environment variables for consumption by the plugin's defined command:
+AUTOSNAP_LABEL: The last component of the snapshot(s) name(s) (the part after the @)
+AUTOSNAP_FMRI: The full SMF FMRI of the auto-snapshot instance corresponding to AUTOSNAP_LABEL
+PLUGIN_FMRI: The full SMF FMRI of the plugin instance associated with the invocation of the plugin command
+                       </loctext>
+               </description>
+       </template>
+</service>
+</service_bundle>
diff --git a/var/svc/manifest/application/time-slider.xml b/var/svc/manifest/application/time-slider.xml
new file mode 100644 (file)
index 0000000..1178d6f
--- /dev/null
@@ -0,0 +1,163 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+    CDDL HEADER START
+
+    The contents of this file are subject to the terms of the
+    Common Development and Distribution License (the "License").
+    You may not use this file except in compliance with the License.
+
+    You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+    or http://www.opensolaris.org/os/licensing.
+    See the License for the specific language governing permissions
+    and limitations under the License.
+
+    CDDL HEADER END
+
+    Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+    Use is subject to license terms.
+
+    NOTE:  This service manifest is not editable; its contents will
+    be overwritten by package or patch operations, including
+    operating system upgrade.  Make customizations in a different
+    file.
+-->
+
+<service_bundle type='manifest' name='SUNWgnome-time-slider'>
+
+<service
+       name='application/time-slider'
+       type='service'
+       version='0.2.95'>
+
+       <!-- This is the time-slider snapshot management service
+            which is a simple monitor and configuration synchr-
+            oniser for:
+            svc:/system/filesystem/zfs/auto-snapshot:<schedule>
+            instances. It combines these services to provide a
+            useful range of snapshots for a stand alone system.
+       -->
+
+       <create_default_instance enabled='false' />
+
+       <single_instance />
+
+       <!-- we need to be multi-user  -->
+       <dependency
+               name='multi-user'
+               grouping='require_all'
+               restart_on='none'
+               type='service'>
+               <service_fmri value='svc:/milestone/multi-user' />
+       </dependency>
+
+    <!-- These are the service instances that specify
+         snapshot taking parameters
+
+       <dependency
+               name='auto-snapshot-svcs'
+               type='service'
+               grouping='optional_all'
+               restart_on='refresh'>
+               <service_fmri value='svc:/system/filesystem/zfs/auto-snapshot:frequent' />
+               <service_fmri value='svc:/system/filesystem/zfs/auto-snapshot:hourly' />
+               <service_fmri value='svc:/system/filesystem/zfs/auto-snapshot:daily' />
+               <service_fmri value='svc:/system/filesystem/zfs/auto-snapshot:weekly' />
+               <service_fmri value='svc:/system/filesystem/zfs/auto-snapshot:monthly' />
+       </dependency>
+    -->
+       <exec_method
+               type='method'
+               name='start'
+               exec='/lib/svc/method/time-slider start'
+               timeout_seconds='60'>
+               <method_context>
+                       <method_credential user='zfssnap' group='daemon' />
+               </method_context>
+       </exec_method>
+
+       <exec_method
+               type='method'
+               name='stop'
+               exec=':kill'
+               timeout_seconds='60'>
+               <method_context>
+                       <method_credential user='zfssnap' group='daemon' />
+               </method_context>
+       </exec_method>
+
+       <exec_method
+               type='method'
+               name='refresh'
+               exec=':kill -HUP'
+               timeout_seconds='60'>
+               <method_context>
+                       <method_credential user='zfssnap' group='daemon' />
+               </method_context>
+       </exec_method>
+
+       <property_group name='startd' type='framework'>
+               <propval name='duration' type='astring'
+                       value='contract' />
+       </property_group>
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+                       value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+                       value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name='daemon' type='application'>
+               <propval name='verbose' type='boolean' value='false'
+                  override='true'/>
+               <propval name='value_authorization' type='astring'
+                       value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name='zfs' type='application'>
+               <propval name='custom-selection' type='boolean' value='false'
+            override='true'/>
+        <propval name='keep-empties' type='boolean' value='false'
+            override='true'/>
+        <!--
+        sep:    Set to '_' by default, this is the character used to
+        separate datestamps used in snapshot names.
+        -->
+        <propval name='sep' type='astring' value='_'
+            override='true'/>
+               <propval name='value_authorization' type='astring'
+                       value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name='zpool' type='application'>
+           <propval name='remedial-cleanup' type='boolean' value='true'
+               override='true'/>
+               <propval name='warning-level' type='integer' value='80'
+            override='true'/>
+               <propval name='critical-level' type='integer' value='90'
+            override='true'/>
+               <propval name='emergency-level' type='integer' value='95'
+            override='true'/>
+               <propval name='value_authorization' type='astring'
+                       value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+       
+       <stability value='Unstable' />
+
+       <template>
+               <common_name>
+                       <loctext xml:lang='C'>GNOME Desktop Snapshot Management Service
+                               </loctext>
+               </common_name>
+
+               <documentation>
+                       <manpage
+                               title='zfs'
+                               section='1M'
+                               manpath='/usr/share/man' />
+               </documentation>
+       </template>
+</service>
+
+</service_bundle>
diff --git a/var/svc/manifest/system/filesystem/auto-snapshot.xml b/var/svc/manifest/system/filesystem/auto-snapshot.xml
new file mode 100644 (file)
index 0000000..01e0591
--- /dev/null
@@ -0,0 +1,262 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.0 only
+ (the "License").  You may not use this file except in compliance
+ with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+-->
+
+<service_bundle type='manifest' name='SUNWtime-slider'>
+
+<service
+       name='system/filesystem/zfs/auto-snapshot'
+       type='service'
+       version='0.2.96'>
+
+       <!-- we need time-slider  -->
+       <dependency
+               name='time-slider'
+               grouping='require_all'
+               restart_on='refresh'
+               type='service'>
+               <service_fmri value='svc:/application/time-slider' />
+       </dependency>
+
+        <exec_method
+                type='method'
+                name='start'
+                exec=':true'
+                timeout_seconds='10'>
+        </exec_method>
+
+        <exec_method
+                type='method'
+                name='stop'
+                exec=':true'
+                timeout_seconds='10'>
+        </exec_method>
+
+        <exec_method
+                type='method'
+                name='refresh'
+                exec=':true'
+                timeout_seconds='10'>
+        </exec_method>
+
+       <property_group name='startd' type='framework'>
+               <propval name='duration' type='astring' value='transient' />
+       </property_group>
+
+        <property_group name='general' type='framework'>
+            <propval name='action_authorization' type='astring'
+                value='solaris.smf.manage.zfs-auto-snapshot' />
+            <propval name='value_authorization' type='astring'
+                value='solaris.smf.manage.zfs-auto-snapshot' />
+        </property_group>
+
+
+    <!-- The properties we expect that any instance will define:
+
+       interval : minutes | hours | days | months
+
+       period : How many (m,h,d,m) to wait between snapshots
+
+       keep : How many snapshots we should keep, otherwise, we
+               delete the oldest when we hit this threshold
+        -->
+
+       <property_group name="zfs" type="application">
+         <propval name="interval" type="astring" value="Not set" override="true"/>
+         <propval name="keep" type="astring" value="all" override="true"/>
+       </property_group>
+
+
+       <!-- We now define a set of default instances to take frequent,
+            hourly, daily, weekly and monthly snapshots --> 
+
+
+       <!-- This instance recursively snapshots all
+            filesystems marked with the ZFS User Property 
+            com.sun:auto-snapshot:frequent=true every
+            15 minutes, and keeps 3 of these snapshots into the past.
+       -->
+
+       <instance name='frequent' enabled='false' >
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name="zfs" type="application">
+
+         <propval name="interval" type="astring" value="minutes"
+                  override="true"/>
+         <propval name="period" type="astring" value="15"
+                  override="true"/>
+         <propval name="keep" type="astring" value="3"
+                  override="true"/>
+
+       </property_group>
+
+       </instance>
+
+       <!-- This instance recursively snapshots all
+            filesystems marked with the ZFS User Property 
+            com.sun:auto-snapshot:hourly=true every
+            hour, and keeps 23 of these snapshots into the past.
+       -->
+
+       <instance name='hourly' enabled='false' >
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name="zfs" type="application">
+
+         <propval name="interval" type="astring" value="hours"
+                  override="true"/>
+         <propval name="period" type="astring" value="1"
+                  override="true"/>
+         <propval name="keep" type="astring" value="23"
+                  override="true"/>
+
+       </property_group>
+
+       </instance>
+
+
+       <!-- This instance recursively snapshots all
+            filesystems marked with the ZFS User Property 
+            com.sun:auto-snapshot:daily=true every
+            day, and keeps 6 of these snapshots into the past.
+       -->
+
+       <instance name='daily' enabled='false' >
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name="zfs" type="application">
+
+         <propval name="interval" type="astring" value="days"
+                  override="true"/>
+         <propval name="period" type="astring" value="1"
+                  override="true"/>
+         <propval name="keep" type="astring" value="6"
+                  override="true"/>
+
+       </property_group>
+
+       </instance>
+
+       <!-- This instance recursively snapshots all
+            filesystems marked with the ZFS User Property 
+            com.sun:auto-snapshot:weekly=true every
+            7 days, and keeps 4 of these snapshots into the past.
+       -->
+
+       <instance name='weekly' enabled='false' >
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name="zfs" type="application">
+
+         <propval name="interval" type="astring" value="days"
+                  override="true"/>
+         <propval name="period" type="astring" value="7"
+                  override="true"/>
+         <propval name="keep" type="astring" value="4"
+                  override="true"/>
+
+       </property_group>
+
+       </instance>
+
+
+       <!-- This instance recursively snapshots all
+            filesystems marked with the ZFS User Property 
+            com.sun:auto-snapshot:monthly=true every
+            month, and keeps 12 of these snapshots into the past.
+       -->
+
+       <instance name='monthly' enabled='false' >
+
+       <property_group name='general' type='framework'>
+               <propval name='action_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+               <propval name='value_authorization' type='astring'
+               value='solaris.smf.manage.zfs-auto-snapshot' />
+       </property_group>
+
+       <property_group name="zfs" type="application">
+
+         <propval name="interval" type="astring" value="months"
+                  override="true"/>
+         <propval name="period" type="astring" value="1"
+                  override="true"/>
+         <propval name="keep" type="astring" value="12"
+                  override="true"/>
+
+       </property_group>
+
+       </instance>
+
+       <stability value='Unstable' />
+
+       <template>
+               <common_name>
+                       <loctext xml:lang='C'>ZFS automatic snapshots</loctext>
+               </common_name>
+               <description>
+                       <loctext xml:lang='C'>
+This service provides system configuration for taking automatic snapshots of ZFS
+filesystems.
+
+In order to use this service, you must enable the time-slider service plus at least one auto-snapshot
+instance per set of automatic snapshots you want to take.
+The time-slider service will manage the creation and destruction of snapshots according to the definitions
+of each auto-snapshot service instance.
+
+On stopping the service, time-slider will cease to take snapshots for the specific instance.
+                       </loctext>
+               </description>
+       </template>
+</service>
+</service_bundle>