Hello,

Perhaps this might be useful, or interesting to somebody else, or could provide
the basis of something much better. Then again, it might be utterly useless. :)

A few weeks ago, I wrote a patch that allows you to delete files in a bacula
storage directory via bconsole. I couldn't just use 'rm' because the files
that I wanted to delete were on a remote machine.

The patch probably goes against all sorts of bacula conventions, as it doesn't
- for example - bother trying to read the volume to see whether it really is
the volume that you think it is. It'll just go ahead and try to delete whatever
is there, even if you've asked it to delete something that the director doesn't
know about.

I wrote this for bacula-2.5.28-b1, so may need a little tweaking to apply
cleanly to newer versions since then.
You'll need to patch both the storage daemon and the director.

To use it, you can type something like this on bconsole:
unlink storage="Remote1" volume="backup-0234"

It uses the 'unlink()' system call on the storage daemon, which may only work
on unix/linux machines.

Graham
Index: WORK/src/dird/ua_cmds.c
===================================================================
RCS file: /cvs/netpilot/GPL/bacula-2.5.28-b1/WORK/src/dird/ua_cmds.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- WORK/src/dird/ua_cmds.c	5 Jan 2009 17:03:05 -0000	1.2
+++ WORK/src/dird/ua_cmds.c	11 Feb 2009 12:19:49 -0000	1.3
@@ -72,6 +72,7 @@
 extern int show_cmd(UAContext *ua, const char *cmd);
 extern int sqlquerycmd(UAContext *ua, const char *cmd);
 extern int status_cmd(UAContext *ua, const char *cmd);
+extern int unlink_cmd(UAContext *ua, const char *cmd);
 extern int update_cmd(UAContext *ua, const char *cmd);
 
 /* Forward referenced functions */
@@ -148,6 +149,7 @@
  { NT_("trace"),      trace_cmd,     _("turn on/off trace to file"),                  true},
  { NT_("unmount"),    unmount_cmd,   _("unmount <storage-name>"),                     false},
  { NT_("umount"),     unmount_cmd,   _("umount <storage-name> for old-time Unix guys"),false},
+ { NT_("unlink"),     unlink_cmd,    _("unlink a file"),                               false},
  { NT_("update"),     update_cmd,    _("update Volume, Pool or slots"),               true},
  { NT_("use"),        use_cmd,       _("use catalog xxx"),                            false},
  { NT_("var"),        var_cmd,       _("does variable expansion"),                    false},
Index: WORK/src/dird/ua_label.c
===================================================================
RCS file: /cvs/netpilot/GPL/bacula-2.5.28-b1/WORK/src/dird/ua_label.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- WORK/src/dird/ua_label.c	5 Jan 2009 16:06:53 -0000	1.1
+++ WORK/src/dird/ua_label.c	11 Feb 2009 12:19:49 -0000	1.2
@@ -58,6 +58,60 @@
 static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive);
 static int get_num_slots_from_SD(UAContext *ua);
 
+static bool send_unlink_request(UAContext *ua, char *volume, int drive)
+{
+   BSOCK *sd;
+   char cmd[256]="";
+   char dev_name[MAX_NAME_LENGTH];
+
+   if (!(sd=open_sd_bsock(ua))) {
+      return false;
+   }
+   bstrncpy(dev_name, ua->jcr->wstore->dev_name(), sizeof(dev_name));
+   bash_spaces(dev_name);
+   bash_spaces(volume);
+   snprintf(cmd, sizeof(cmd), "unlink %s volume=%s drive=%d",
+	dev_name, volume, drive);
+   sd->fsend(cmd);
+   ua->send_msg(_("Sending unlink command: '%s'\n"), cmd);
+   while (sd->recv() >= 0) {
+      ua->send_msg("%s", sd->msg);
+   }
+   unbash_spaces(dev_name);
+   unbash_spaces(volume);
+   close_sd_bsock(ua);
+   return true;
+}
+
+int unlink_cmd(UAContext *ua, const char *cmd)
+{
+   int i;
+   int drive;
+   USTORE store;
+   char volume[256]="";
+
+   if (!open_client_db(ua)) {
+      return 1;
+   }
+
+   store.store = get_storage_resource(ua, true/*use default*/);
+   if (!store.store) {
+      return 1;
+   }
+   pm_strcpy(store.store_source, _("command line"));
+   set_wstorage(ua->jcr, &store);
+   drive = get_storage_drive(ua, store.store);
+
+   /* Check for volume=NewVolume */
+   i = find_arg_with_value(ua, "volume");
+   if (i >= 0) {
+      snprintf(volume, sizeof(volume), "%s", ua->argv[i]);
+   }
+
+   send_unlink_request(ua, volume, drive);
+
+   return 1;
+}
 
 /*
  * Label a tape
Index: WORK/src/stored/dev.h
===================================================================
RCS file: /cvs/netpilot/GPL/bacula-2.5.28-b1/WORK/src/stored/dev.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- WORK/src/stored/dev.h	5 Jan 2009 16:07:01 -0000	1.1
+++ WORK/src/stored/dev.h	11 Feb 2009 12:19:49 -0000	1.2
@@ -415,6 +415,7 @@
    void lock_door();             /* in dev.c */
    void unlock_door();           /* in dev.c */
    int32_t get_os_tape_file();   /* in dev.c */
+   void unlink_vol(BSOCK *dir, const char *volume); /* in scan.c */
    bool scan_dir_for_volume(DCR *dcr); /* in scan.c */
    bool reposition(DCR *dcr, uint32_t rfile, uint32_t rblock); /* in dev.c */
    void clrerror(int func);      /* in dev.c */
Index: WORK/src/stored/dircmd.c
===================================================================
RCS file: /cvs/netpilot/GPL/bacula-2.5.28-b1/WORK/src/stored/dircmd.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- WORK/src/stored/dircmd.c	5 Jan 2009 16:07:01 -0000	1.1
+++ WORK/src/stored/dircmd.c	11 Feb 2009 12:19:49 -0000	1.2
@@ -79,6 +79,7 @@
 static bool release_cmd(JCR *jcr);
 static bool setdebug_cmd(JCR *jcr);
 static bool cancel_cmd(JCR *cjcr);
+static bool unlink_cmd(JCR *jcr);
 static bool mount_cmd(JCR *jcr);
 static bool unmount_cmd(JCR *jcr);
 static bool bootstrap_cmd(JCR *jcr);
@@ -108,6 +109,7 @@
    {"cancel",      cancel_cmd,      0},
    {".die",        die_cmd,         0},
    {"label",       label_cmd,       0},     /* label a tape */
+   {"unlink",	   unlink_cmd,         0},     /* delete a file */
    {"mount",       mount_cmd,       0},
    {"readlabel",   readlabel_cmd,   0},
    {"release",     release_cmd,     0},
@@ -627,6 +629,58 @@
    return dcr;
 }
 
+/*
+ * del command from Director
+ */
+static bool unlink_cmd(JCR *jcr)
+{
+   POOL_MEM devname;
+   BSOCK *dir = jcr->dir_bsock;
+   DEVICE *dev;
+   DCR *dcr;
+   int drive;
+   int slot = 0;
+   char volume[128]="";
+   char tmp[256]="";
+   // No idea why, but I cannot get sscanf to work directly on dir->msg. :(
+   snprintf(tmp, sizeof(tmp), "%s", dir->msg);
+
+   if(sscanf(tmp, "unlink %127s volume=%127s drive=%d",
+	devname.c_str(), volume, &drive)==3)
+   {
+      dcr = find_device(jcr, devname, drive);
+      if (dcr) {
+         dev = dcr->dev;
+         dev->dlock();                 /* Use P to avoid indefinite block */
+         Dmsg2(100, "unlink cmd blocked=%d must_unload=%d\n", dev->blocked(), 
+            dev->must_unload());
+         if(dev->blocked()==BST_NOT_BLOCKED) {
+            if (dev->is_autochanger() && slot > 0) {
+               try_autoload_device(jcr, dcr, slot, "");
+            }
+            if (dev->is_file()) {
+               dev->unlink_vol(dir, volume);
+            }
+	    else {
+               dir->fsend(_("3906 %s not a file device:.\n"),
+                  dev->print_name());
+	    }
+         }
+	 else {
+	       dir->fsend(_("3905 unlink command blocked %d\n"), dev->blocked());
+	 }
+         dev->dunlock();
+         free_dcr(dcr);
+      } else {
+         dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
+      }
+   } else {
+      pm_strcpy(jcr->errmsg, dir->msg);
+      dir->fsend(_("3909 Error scanning unlink command: %s\n"), jcr->errmsg);
+   }
+   dir->signal(BNET_EOD);
+   return true;
+}
 
 /*
  * Mount command from Director
Index: WORK/src/stored/scan.c
===================================================================
RCS file: /cvs/netpilot/GPL/bacula-2.5.28-b1/WORK/src/stored/scan.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- WORK/src/stored/scan.c	5 Jan 2009 16:07:01 -0000	1.1
+++ WORK/src/stored/scan.c	11 Feb 2009 12:19:49 -0000	1.2
@@ -42,6 +42,31 @@
 static bool is_volume_name_legal(char *name);
 
 
+void DEVICE::unlink_vol(BSOCK *dir, const char *volume)
+{
+   char *mount_point;
+   char fullpath[256]="";
+
+   if (device->mount_point) {
+      mount_point = device->mount_point;
+   } else {
+      mount_point = device->device_name;
+   }
+
+   snprintf(fullpath, sizeof(fullpath), "%s/%s", mount_point, volume);
+
+   if(!unlink(fullpath))
+   	dir->fsend(_("Deleting %s: OK\n"), fullpath);
+   else
+   {
+	berrno be;
+	dev_errno = errno;
+	dir->fsend(_("Deleting %s: error: %s\n"), fullpath, be.bstrerror());
+   }
+
+   return;
+}
+
 bool DEVICE::scan_dir_for_volume(DCR *dcr)
 {
    DIR* dp;
------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
Bacula-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bacula-devel

Reply via email to