summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorSven Hartge <Sven Hartge sven@svenhartge.de>2018-08-09 09:26:31 +0200
committerSven Hartge <Sven Hartge sven@svenhartge.de>2018-08-09 09:26:31 +0200
commit80bafa66a1f92981132922c65a103b14e2b016ad (patch)
tree73beef9812889e4b664211325439c3972544221c /scripts
parent038694b727cf1cc2222d3054e85828d7af27e320 (diff)
New upstream version 9.2.0
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/Makefile.in4
-rw-r--r--scripts/bacula-ctl-sd.in3
-rwxr-xr-xscripts/bacula.in2
-rw-r--r--scripts/dvd-handler.in515
-rw-r--r--scripts/dvd-simulator.in476
5 files changed, 5 insertions, 995 deletions
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index 4eb2478a..40ad3e67 100755
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -50,9 +50,9 @@ install: installdirs
$(INSTALL_SCRIPT) mtx-changer $(DESTDIR)$(scriptdir)/mtx-changer
@if test -f ${DESTDIR}${scriptdir}/mtx-changer.conf; then \
echo " ==> Installing mtx-changer.conf to mtx-changer.conf.new"; \
- $(INSTALL_SCRIPT) mtx-changer.conf $(DESTDIR)$(scriptdir)/mtx-changer.conf.new; \
+ $(INSTALL_DATA) mtx-changer.conf $(DESTDIR)$(scriptdir)/mtx-changer.conf.new; \
else \
- $(INSTALL_SCRIPT) mtx-changer.conf $(DESTDIR)$(scriptdir)/mtx-changer.conf; \
+ $(INSTALL_DATA) mtx-changer.conf $(DESTDIR)$(scriptdir)/mtx-changer.conf; \
fi
@if test -f ${DESTDIR}${scriptdir}/disk-changer; then \
echo " ==> Saving existing disk-changer to disk-changer.old"; \
diff --git a/scripts/bacula-ctl-sd.in b/scripts/bacula-ctl-sd.in
index f545cd63..2c247967 100644
--- a/scripts/bacula-ctl-sd.in
+++ b/scripts/bacula-ctl-sd.in
@@ -2,7 +2,7 @@
#
# Bacula(R) - The Network Backup Solution
#
-# Copyright (C) 2000-2016 Kern Sibbald
+# Copyright (C) 2000-2018 Kern Sibbald
#
# The original author of Bacula is Kern Sibbald, with contributions
# from many others, a complete list can be found in the file AUTHORS.
@@ -225,6 +225,7 @@ case "$1" in
OPTIONS="${OPTIONS} -g ${SD_GROUP}"
fi
+ ulimit -l unlimited > /dev/null 2> /dev/null || true
if [ "x${VALGRIND_SD}" = "x1" ]; then
valgrind --leak-check=full ${BACSDBIN}/bacula-sd $2 $3 ${OPTIONS} -v -c ${BACSDCFG}/bacula-sd.conf
else
diff --git a/scripts/bacula.in b/scripts/bacula.in
index cadfa655..acefe0dc 100755
--- a/scripts/bacula.in
+++ b/scripts/bacula.in
@@ -2,7 +2,7 @@
#
# Bacula(R) - The Network Backup Solution
#
-# Copyright (C) 2000-2016 Kern Sibbald
+# Copyright (C) 2000-2018 Kern Sibbald
#
# The original author of Bacula is Kern Sibbald, with contributions
# from many others, a complete list can be found in the file AUTHORS.
diff --git a/scripts/dvd-handler.in b/scripts/dvd-handler.in
deleted file mode 100644
index 2d2bcf15..00000000
--- a/scripts/dvd-handler.in
+++ /dev/null
@@ -1,515 +0,0 @@
-#!@PYTHON@
-#
-# Bacula(R) - The Network Backup Solution
-#
-# Copyright (C) 2000-2016 Kern Sibbald
-#
-# The original author of Bacula is Kern Sibbald, with contributions
-# from many others, a complete list can be found in the file AUTHORS.
-#
-# You may use this file and others of this release according to the
-# license defined in the LICENSE file, which includes the Affero General
-# Public License, v3.0 ("AGPLv3") and some additional permissions and
-# terms pursuant to its AGPLv3 Section 7.
-#
-# This notice must be preserved when any source code is
-# conveyed and/or propagated.
-#
-# Bacula(R) is a registered trademark of Kern Sibbald.
-#
-# Check the free space available on a writable DVD
-# Should always exit with 0 status, otherwise it indicates a serious error.
-# (wrong number of arguments, Python exception...)
-#
-# called: dvd-handler <dvd-device-name> operation args
-#
-# operations used by Bacula:
-#
-# free (no arguments)
-# Scan the device and report the available space. It returns:
-# Prints on the first output line the free space available in bytes.
-# If an error occurs, prints a negative number (-errno), followed,
-# on the second line, by an error message.
-#
-# write op filename
-# Write a part file to disk.
-# This operation needs two additional arguments.
-# The first (op) indicates to
-# 0 -- append
-# 1 -- first write to a blank disk
-# 2 -- blank or truncate a disk
-#
-# The second is the filename to write
-#
-# operations available but not used by Bacula:
-#
-# test Scan the device and report the information found.
-# This operation needs no further arguments.
-# prepare Prepare a DVD+/-RW for being used by Bacula.
-# Note: This is only useful if you already have some
-# non-Bacula data on a medium, and you want to use
-# it with Bacula. Don't run this on blank media, it
-# is useless.
-#
-#
-# $Id$
-#
-
-import popen2
-import os
-import os.path
-import errno
-import sys
-import re
-import signal
-import time
-import array
-
-class disk:
-# Configurable values:
-
- dvdrwmediainfo = "@DVDRWMEDIAINFO@"
- growcmd = "@GROWISOFS@"
- dvdrwformat = "@DVDRWFORMAT@"
- dd = "@DD@"
- margin = 10485760 # 10 mb security margin
-
- # Comment the following line if you want the tray to be reloaded
- # when writing ends.
- growcmd += " -use-the-force-luke=notray"
-
-# end of configurable values
-
-###############################################################################
-#
-# This class represents DVD disk informations.
-# When instantiated, it needs a device name.
-# Status information about the device and the disk loaded is collected only when
-# asked for (for example dvd-freespace doesn't need to know the media type, and
-# dvd-writepart doesn't not always need to know the free space).
-#
-# The following methods are implemented:
-# __init__ we need that...
-# __repr__ this seems to be a good idea to have.
-# Quite minimalistic implementation, though.
-# __str__ For casts to string. Return the current disk information
-# is_empty Returns TRUE if the disk is empty, blank... this needs more
-# work, especially concerning non-RW media and blank vs. no
-# filesystem considerations. Here, we should also look for
-# other filesystems - probably we don't want to silently
-# overwrite UDF or ext2 or anything not mentioned in fstab...
-# (NB: I don't think it is a problem)
-# free Returns the available free space.
-# write Writes one part file to disk, either starting a new file
-# system on disk, or appending to it.
-# This method should also prepare a blank disk so that a
-# certain part of the disk is used to allow detection of a
-# used disk by all / more disk drives.
-# prepare Blank the device
-#
-###############################################################################
- def __init__(self, devicename):
- self.device = devicename
- self.disktype = "none"
- self.diskmode = "none"
- self.diskstatus = "none"
- self.hardwaredevice = "none"
- self.pid = 0
- self.next_session = -1
- self.capacity = -1
-
- self.freespace_collected = 0
- self.mediumtype_collected = 0
-
- self.growcmd += " -quiet"
-
- if self.is4gbsupported():
- self.growcmd += " -use-the-force-luke=4gms"
-
- self.growparams = " -A 'Bacula Data' -input-charset=default -iso-level 3 -pad " + \
- "-p 'dvd-handler / growisofs' -sysid 'BACULADATA' -R"
-
- return
-
- def __repr__(self):
- return "disk(" + self.device + ") # This is an instance of class disk"
-
- def __str__(self):
- if not self.freespace_collected:
- self.collect_freespace();
- if not self.mediumtype_collected:
- self.collect_mediumtype();
-
- self.me = "Class disk, initialized with device '" + self.device + "'\n"
- self.me += "type = '" + self.disktype + "' mode='" + self.diskmode + "' status = '" + self.diskstatus + "'\n"
- self.me += " next_session = " + str(self.next_session) + " capacity = " + str(self.capacity) + "\n"
- self.me += "Hardware device is '" + self.hardwaredevice + "'\n"
- self.me += "growcmd = '" + self.growcmd + "'\ngrowparams = '" + self.growparams + "'\n"
- return self.me
-
- ## Check if we want to allow growisofs to cross the 4gb boundary
- def is4gbsupported(self):
- processi = popen2.Popen4("uname -s -r")
- status = processi.wait()
- if not os.WIFEXITED(status):
- return 1
- if os.WEXITSTATUS(status) != 0:
- return 1
- strres = processi.fromchild.readline()[0:-1]
- version = re.search(r"Linux (\d+)\.(\d+)\.(\d+)", strres)
- if not version: # Non-Linux: allow
- return 1
-
- if (int(version.group(1)) > 2) or (int(version.group(2)) > 6) or ((int(version.group(1)) == 2) and (int(version.group(2)) == 6) and (int(version.group(3)) >= 8)):
- return 1
- else:
- return 0
-
- def collect_freespace(self): # Collects current free space
- self.cmd = self.growcmd + " -F " + self.device
- processi = popen2.Popen4(self.cmd)
- status = processi.wait()
- if not os.WIFEXITED(status):
- raise DVDError(0, "growisofs process did not exit correctly.")
- result = processi.fromchild.read()
- if os.WEXITSTATUS(status) != 0:
- if (os.WEXITSTATUS(status) & 0x7F) == errno.ENOSPC:
- # Kludge to force dvd-handler to return a free space of 0
- self.next_session = 1
- self.capacity = 1
- self.freespace_collected = 1
- return
- else:
- raise DVDError(os.WEXITSTATUS(status), "growisofs returned with an error " + result + ". Please check your are using a patched version of dvd+rw-tools.")
- next_sess = re.search(r"\snext_session=(\d+)\s", result, re.MULTILINE)
- capa = re.search(r"\scapacity=(\d+)\s", result, re.MULTILINE)
-
- if next_sess and capa:
- self.next_session = long(next_sess.group(1))
- self.capacity = long(capa.group(1))
-
- # testing cheat (emulate 4GB boundary at 100MB)
- #if self.next_session > 100000000:
- # self.capacity = self.next_session
- else:
- raise DVDError(0, "Cannot get next_session and capacity from growisofs.\nReturned: " + result)
-
- self.freespace_collected = 1
- return
-
- def collect_mediumtype(self): # Collects current medium type
- self.lasterror = ""
- cmd = self.dvdrwmediainfo + " " + self.device
- processi = popen2.Popen4(cmd)
- status = processi.wait()
- if not os.WIFEXITED(status):
- raise DVDError(0, self.dvdrwmediainfo + " process did not exit correctly.")
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(0, "Cannot get media info from " + self.dvdrwmediainfo)
- return
- result = processi.fromchild.read()
-
- hardware = re.search(r"INQUIRY:\s+(.*)\n", result, re.MULTILINE)
- mediatype = re.search(r"\sMounted Media:\s+([0-9A-F]{2})h, (\S*)\s", result, re.MULTILINE)
- mediamode = re.search(r"\sMounted Media:\s+[0-9A-F]{2}h, \S* (.*)\n", result, re.MULTILINE)
- status = re.search(r"\sDisc status:\s+(.*)\n", result, re.MULTILINE)
-
- if hardware:
- self.hardwaredevice = hardware.group(1)
-
- if mediatype:
- self.disktype = mediatype.group(2)
- else:
- raise DVDError(0, "Media type not found in " + self.dvdrwmediainfo + " output")
-
- if self.disktype == "DVD-RW":
- if mediamode:
- self.diskmode = mediamode.group(1)
- else:
- raise DVDError(0, "Media mode not found for DVD-RW in " + self.dvdrwmediainfo + " output")
-
- if status:
- self.diskstatus = status.group(1)
- else:
- raise DVDError(0, "Disc status not found in " + self.dvdrwmediainfo + " output")
-
-
- self.mediumtype_collected = 1
- return
-
- def is_empty(self):
- if not self.freespace_collected:
- self.collect_freespace();
-
- return 0 == self.next_session
-
- def is_RW(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return "DVD-RW" == self.disktype or "DVD+RW" == self.disktype or "DVD-RAM" == self.disktype
-
- def is_plus_RW(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return "DVD+RW" == self.disktype
-
- def is_minus_RW(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return "DVD-RW" == self.disktype
-
- def is_restricted_overwrite(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return self.diskmode == "Restricted Overwrite"
-
- def is_blank(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
-
- return self.diskstatus == "blank"
-
- def free(self):
- if not self.freespace_collected:
- self.collect_freespace();
-
- fr = self.capacity-self.next_session-self.margin
- if fr < 0:
- return 0
- else:
- return fr
-
- def term_handler(self, signum, frame):
- print 'dvd-handler: Signal term_handler called with signal', signum
- if self.pid != 0:
- print "dvd-handler: Sending SIGTERM to pid", self.pid
- os.kill(self.pid, signal.SIGTERM)
- time.sleep(10)
- print "dvd-handler: Sending SIGKILL to pid", self.pid
- os.kill(self.pid, signal.SIGKILL)
- sys.exit(1)
-
- def write(self, newvol, partfile):
- # Blank DVD+RW when there is no data on it
- if newvol and self.is_plus_RW() and self.is_blank():
- print "DVD+RW looks brand-new, blank it to fix some DVD-writers bugs."
- self.blank()
- print "Done, now writing the part file."
-
- if newvol and self.is_minus_RW() and (not self.is_restricted_overwrite()):
- print "DVD-RW is in " + self.diskmode + " mode, reformating it to Restricted Overwrite"
- self.reformat_minus_RW()
- print "Done, now writing the part file."
-
- cmd = self.growcmd + self.growparams
- if newvol:
- # Ignore any existing iso9660 filesystem - used for truncate
- if newvol == 2:
- cmd += " -use-the-force-luke=tty"
- cmd += " -Z "
- else:
- cmd += " -M "
- cmd += self.device + " " + str(partfile)
- print "Running " + cmd
- oldsig = signal.signal(signal.SIGTERM, self.term_handler)
- proc = popen2.Popen4(cmd)
- self.pid = proc.pid
- status = proc.poll()
- while status == -1:
- line = proc.fromchild.readline()
- while len(line) > 0:
- print line,
- line = proc.fromchild.readline()
- time.sleep(1)
- status = proc.poll()
- self.pid = 0
- print
- signal.signal(signal.SIGTERM, oldsig)
- if not os.WIFEXITED(status):
- raise DVDError(0, cmd + " process did not exit correctly, signal/status " + str(status))
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
-
- def prepare(self):
- if not self.is_RW():
- raise DVDError(0, "I won't prepare a non-rewritable medium")
-
- # Blank DVD+RW when there is no data on it
- if self.is_plus_RW() and self.is_blank():
- print "DVD+RW looks brand-new, blank it to fix some DVD-writers bugs."
- self.blank()
- return # It has been completely blanked: Medium is ready to be used by Bacula
-
- if self.is_minus_RW() and (not self.is_restricted_overwrite()):
- print "DVD-RW is in " + self.diskmode + " mode, reformating it to Restricted Overwrite"
- self.reformat_minus_RW()
- return # Reformated: Medium is ready to be used by Bacula
-
- # TODO: Check if /dev/fd/0 and /dev/zero exists, otherwise, run self.blank()
- if not os.path.exists("/dev/fd/0") or not os.path.exists("/dev/zero"):
- print "/dev/fd/0 or /dev/zero doesn't exist, blank the medium completely."
- self.blank()
- return
-
- cmd = self.dd + " if=/dev/zero bs=1024 count=512 | " + self.growcmd + " -Z " + self.device + "=/dev/fd/0"
- print "Running " + cmd
- oldsig = signal.signal(signal.SIGTERM, self.term_handler)
- proc = popen2.Popen4(cmd)
- self.pid = proc.pid
- status = proc.poll()
- while status == -1:
- line = proc.fromchild.readline()
- while len(line) > 0:
- print line,
- line = proc.fromchild.readline()
- time.sleep(1)
- status = proc.poll()
- self.pid = 0
- print
- signal.signal(signal.SIGTERM, oldsig)
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
-
- def blank(self):
- cmd = self.growcmd + " -Z " + self.device + "=/dev/zero"
- print "Running " + cmd
- oldsig = signal.signal(signal.SIGTERM, self.term_handler)
- proc = popen2.Popen4(cmd)
- self.pid = proc.pid
- status = proc.poll()
- while status == -1:
- line = proc.fromchild.readline()
- while len(line) > 0:
- print line,
- line = proc.fromchild.readline()
- time.sleep(1)
- status = proc.poll()
- self.pid = 0
- print
- signal.signal(signal.SIGTERM, oldsig)
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
-
- def reformat_minus_RW(self):
- cmd = self.dvdrwformat + " -force " + self.device
- print "Running " + cmd
- oldsig = signal.signal(signal.SIGTERM, self.term_handler)
- proc = popen2.Popen4(cmd)
- self.pid = proc.pid
- status = proc.poll()
- while status == -1:
- line = proc.fromchild.readline()
- while len(line) > 0:
- print line,
- line = proc.fromchild.readline()
- time.sleep(1)
- status = proc.poll()
- self.pid = 0
- print
- signal.signal(signal.SIGTERM, oldsig)
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
-
-# class disk ends here.
-
-class DVDError(Exception):
- def __init__(self, errno, value):
- self.errno = errno
- self.value = value
- if self.value[-1] == '\n':
- self.value = self.value[0:-1]
- def __str__(self):
- return str(self.value) + " || errno = " + str(self.errno) + " (" + os.strerror(self.errno & 0x7F) + ")"
-
-def usage():
- print "Wrong number of arguments."
- print """
-Usage:
-
-dvd-handler DEVICE test
-dvd-handler DEVICE free
-dvd-handler DEVICE write APPEND FILE
-dvd-handler DEVICE prepare
-
-where DEVICE is a device name like /dev/sr0 or /dev/dvd.
-
-Operations:
-test Scan the device and report the information found.
- This operation needs no further arguments.
-free Scan the device and report the available space.
-write Write a part file to disk.
- This operation needs two additional arguments.
- The first indicates to append (0), restart the
- disk (1) or restart existing disk (2). The second
- is the file to write.
-prepare Prepare a DVD+/-RW for being used by Bacula.
- Note: This is only useful if you already have some
- non-Bacula data on a medium, and you want to use
- it with Bacula. Don't run this on blank media, it
- is useless.
-"""
- sys.exit(1)
-
-if len(sys.argv) < 3:
- usage()
-
-dvd = disk(sys.argv[1])
-
-if "free" == sys.argv[2]:
- if len(sys.argv) == 3:
- try:
- free = dvd.free()
- except DVDError, e:
- if e.errno != 0:
- print -e.errno
- else:
- print errno.EPIPE
- print str(e)
- else:
- print free
- print "No Error reported."
- else:
- print "Wrong number of arguments for free operation. Wanted 3 got", len(sys.argv)
- usage()
-elif "prepare" == sys.argv[2]:
- if len(sys.argv) == 3:
- try:
- dvd.prepare()
- except DVDError, e:
- print "Error while preparing medium: ", str(e)
- if e.errno != 0:
- sys.exit(e.errno & 0x7F)
- else:
- sys.exit(errno.EPIPE)
- else:
- print "Medium prepared successfully."
- else:
- print "Wrong number of arguments for prepare operation. Wanted 3 got", len(sys.argv)
- usage()
-elif "test" == sys.argv[2]:
- try:
- print str(dvd)
- print "Blank disk: " + str(dvd.is_blank()) + " ReWritable disk: " + str(dvd.is_RW())
- print "Free space: " + str(dvd.free())
- except DVDError, e:
- print "Error while getting informations: ", str(e)
-elif "write" == sys.argv[2]:
- if len(sys.argv) == 5:
- try:
- dvd.write(long(sys.argv[3]), sys.argv[4])
- except DVDError, e:
- print "Error while writing part file: ", str(e)
- if e.errno != 0:
- sys.exit(e.errno & 0x7F)
- else:
- sys.exit(errno.EPIPE)
- else:
- print "Part file " + sys.argv[4] + " successfully written to disk."
- else:
- print "Wrong number of arguments for write operation. Wanted 5 got", len(sys.argv)
- usage()
- sys.exit(1)
-else:
- print "No operation - use test, free, prepare or write."
- print "THIS MIGHT BE A CASE OF DEBUGGING BACULA OR AN ERROR!"
-sys.exit(0)
diff --git a/scripts/dvd-simulator.in b/scripts/dvd-simulator.in
deleted file mode 100644
index 75bc5d2d..00000000
--- a/scripts/dvd-simulator.in
+++ /dev/null
@@ -1,476 +0,0 @@
-#!@PYTHON@
-#
-# Bacula(R) - The Network Backup Solution
-#
-# Copyright (C) 2000-2016 Kern Sibbald
-#
-# The original author of Bacula is Kern Sibbald, with contributions
-# from many others, a complete list can be found in the file AUTHORS.
-#
-# You may use this file and others of this release according to the
-# license defined in the LICENSE file, which includes the Affero General
-# Public License, v3.0 ("AGPLv3") and some additional permissions and
-# terms pursuant to its AGPLv3 Section 7.
-#
-# This notice must be preserved when any source code is
-# conveyed and/or propagated.
-#
-# Bacula(R) is a registered trademark of Kern Sibbald.
-#
-# Modified version of dvd-handler used to simulate reading/writing
-# to a DVD but using disk storage. This is a pretty crude implementation
-# and a lot of the old code is still here and just sort of blunders
-# along.
-#
-# called: dvd-simulator <dvd-device-name> operation args
-#
-# operations used by Bacula:
-#
-# free (no arguments)
-# Scan the device and report the available space.
-#
-# write op filename
-# Write a part file to disk.
-# This operation needs two additional arguments.
-# The first (op) indicates to
-# 0 -- append
-# 1 -- first write to a blank disk
-# 2 -- blank or truncate a disk
-#
-# The second is the filename to write
-#
-# operations available but not used by Bacula:
-#
-# test Scan the device and report the information found.
-# This operation needs no further arguments.
-# prepare Prepare a DVD+/-RW for being used by Bacula.
-# Note: This is only useful if you already have some
-# non-Bacula data on a medium, and you want to use
-# it with Bacula. Don't run this on blank media, it
-# is useless.
-#
-#
-# in case of operation ``free'' returns:
-# Prints on the first output line the free space available in bytes.
-# If an error occurs, prints a negative number (-errno), followed,
-# on the second line, by an error message.
-#
-
-import popen2
-import os
-import os.path
-import shutil
-import errno
-import sys
-import re
-import signal
-import time
-import array
-
-class disk:
-# Configurable values:
-
- dvdrwmediainfo = "@DVDRWMEDIAINFO@"
- growcmd = "@GROWISOFS@"
- dvdrwformat = "@DVDRWFORMAT@"
- dd = "@DD@"
- margin = 10485760 # 10 mb security margin
-
- # Comment the following line if you want the tray to be reloaded
- # when writing ends.
- growcmd += " -use-the-force-luke=notray"
-
-# end of configurable values
-
-###############################################################################
-#
-# This class represents DVD disk informations.
-# When instantiated, it needs a device name.
-# Status information about the device and the disk loaded is collected only when
-# asked for (for example dvd-freespace doesn't need to know the media type, and
-# dvd-writepart doesn't not always need to know the free space).
-#
-# The following methods are implemented:
-# __init__ we need that...
-# __repr__ this seems to be a good idea to have.
-# Quite minimalistic implementation, though.
-# __str__ For casts to string. Return the current disk information
-# is_empty Returns TRUE if the disk is empty, blank... this needs more
-# work, especially concerning non-RW media and blank vs. no
-# filesystem considerations. Here, we should also look for
-# other filesystems - probably we don't want to silently
-# overwrite UDF or ext2 or anything not mentioned in fstab...
-# (NB: I don't think it is a problem)
-# free Returns the available free space.
-# write Writes one part file to disk, either starting a new file
-# system on disk, or appending to it.
-# This method should also prepare a blank disk so that a
-# certain part of the disk is used to allow detection of a
-# used disk by all / more disk drives.
-# blank Blank the device
-#
-###############################################################################
- def __init__(self, devicename):
- self.device = devicename
- self.disktype = "none"
- self.diskmode = "none"
- self.diskstatus = "none"
- self.hardwaredevice = "none"
- self.pid = 0
- self.next_session = -1
- self.capacity = -1
- self.maxcapacity = 4000000000
-
- self.freespace_collected = 0
- self.mediumtype_collected = 0
-
- self.growcmd += " -quiet"
-
- if self.is4gbsupported():
- self.growcmd += " -use-the-force-luke=4gms"
-
- self.growparams = " -A 'Bacula Data' -input-charset=default -iso-level 3 -pad " + \
- "-p 'dvd-handler / growisofs' -sysid 'BACULADATA' -R"
-
- return
-
- def __repr__(self):
- return "disk(" + self.device + ") # This is an instance of class disk"
-
- def __str__(self):
- if not self.freespace_collected:
- self.collect_freespace();
- if not self.mediumtype_collected:
- self.collect_mediumtype();
-
- self.me = "Class disk, initialized with device '" + self.device + "'\n"
- self.me += "type = '" + self.disktype + "' mode='" + self.diskmode + "' status = '" + self.diskstatus + "'\n"
- self.me += " next_session = " + str(self.next_session) + " capacity = " + str(self.capacity) + "\n"
- self.me += "Hardware device is '" + self.hardwaredevice + "'\n"
- self.me += "growcmd = '" + self.growcmd + "'\ngrowparams = '" + self.growparams + "'\n"
- return self.me
-
- ## Check if we want to allow growisofs to cross the 4gb boundary
- def is4gbsupported(self):
- processi = popen2.Popen4("uname -s -r")
- status = processi.wait()
- if not os.WIFEXITED(status):
- return 1
- if os.WEXITSTATUS(status) != 0:
- return 1
- strres = processi.fromchild.readline()[0:-1]
- version = re.search(r"Linux (\d+)\.(\d+)\.(\d+)", strres)
- if not version: # Non-Linux: allow
- return 1
-
- if (int(version.group(1)) > 2) or (int(version.group(2)) > 6) or ((int(version.group(1)) == 2) and (int(version.group(2)) == 6) and (int(version.group(3)) >= 8)):
- return 1
- else:
- return 0
-
- def collect_freespace(self): # Collects current free space
- self.next_session = 0
- self.capacity = 4000000000
- self.freespace_collected = 1
-
- cmd = "du -sb " + self.device
- processi = popen2.Popen4(cmd)
- status = processi.wait()
- if not os.WIFEXITED(status):
- return 1;
- if os.WEXITSTATUS(status) != 0:
- return 1;
- result = processi.fromchild.read()
-
- used = re.search(r"(\d+)\s", result, re.MULTILINE)
-
- self.capacity = self.maxcapacity - long(used.group(1))
- if self.capacity < 0:
- self.capacity = 0
-
- return 0
-
- def collect_mediumtype(self): # Collects current medium type
- self.lasterror = ""
- cmd = self.dvdrwmediainfo + " " + self.device
- processi = popen2.Popen4(cmd)
- status = processi.wait()
- if not os.WIFEXITED(status):
- raise DVDError(0, self.dvdrwmediainfo + " process did not exit correctly.")
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(0, "Cannot get media info from " + self.dvdrwmediainfo)
- return
- result = processi.fromchild.read()
-
- hardware = re.search(r"INQUIRY:\s+(.*)\n", result, re.MULTILINE)
- mediatype = re.search(r"\sMounted Media:\s+([0-9A-F]{2})h, (\S*)\s", result, re.MULTILINE)
- mediamode = re.search(r"\sMounted Media:\s+[0-9A-F]{2}h, \S* (.*)\n", result, re.MULTILINE)
- status = re.search(r"\sDisc status:\s+(.*)\n", result, re.MULTILINE)
-
- if hardware:
- self.hardwaredevice = hardware.group(1)
-
- if mediatype:
- self.disktype = mediatype.group(2)
- else:
- raise DVDError(0, "Media type not found in " + self.dvdrwmediainfo + " output")
-
- if self.disktype == "DVD-RW":
- if mediamode:
- self.diskmode = mediamode.group(1)
- else:
- raise DVDError(0, "Media mode not found for DVD-RW in " + self.dvdrwmediainfo + " output")
-
- if status:
- self.diskstatus = status.group(1)
- else:
- raise DVDError(0, "Disc status not found in " + self.dvdrwmediainfo + " output")
-
-
- self.mediumtype_collected = 1
- return
-
- def is_empty(self):
- if not self.freespace_collected:
- self.collect_freespace();
-
- return 0 == self.next_session
-
- def is_RW(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return "DVD-RW" == self.disktype or "DVD+RW" == self.disktype or "DVD-RAM" == self.disktype
-
- def is_plus_RW(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return "DVD+RW" == self.disktype
-
- def is_minus_RW(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return "DVD-RW" == self.disktype
-
- def is_restricted_overwrite(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
- return self.diskmode == "Restricted Overwrite"
-
- def is_blank(self):
- if not self.mediumtype_collected:
- self.collect_mediumtype();
-
- return self.diskstatus == "blank"
-
- def free(self):
- if not self.freespace_collected:
- self.collect_freespace();
-
- fr = self.capacity-self.next_session-self.margin
- if fr < 0:
- return 0
- else:
- return fr
-
- def term_handler(self, signum, frame):
- print 'dvd-handler: Signal term_handler called with signal', signum
- if self.pid != 0:
- print "dvd-handler: Sending SIGTERM to pid", self.pid
- os.kill(self.pid, signal.SIGTERM)
- time.sleep(10)
- print "dvd-handler: Sending SIGKILL to pid", self.pid
- os.kill(self.pid, signal.SIGKILL)
- sys.exit(1)
-
- def write(self, newvol, partfile):
- if newvol:
- print "Newvol", newvol
- print "Zap everything ..."
- os.system("rm -f "+self.device+"/*")
- print "cp", partfile, self.device
- shutil.copy(partfile,self.device)
-
- def prepare(self):
- if not self.is_RW():
- raise DVDError(0, "I won't prepare a non-rewritable medium")
-
- # Blank DVD+RW when there is no data on it
- if self.is_plus_RW() and self.is_blank():
- print "DVD+RW looks brand-new, blank it to fix some DVD-writers bugs."
- self.blank()
- return # It has been completely blanked: Medium is ready to be used by Bacula
-
- if self.is_minus_RW() and (not self.is_restricted_overwrite()):
- print "DVD-RW is in " + self.diskmode + " mode, reformating it to Restricted Overwrite"
- self.reformat_minus_RW()
- return # Reformated: Medium is ready to be used by Bacula
-
- # TODO: Check if /dev/fd/0 and /dev/zero exists, otherwise, run self.blank()
- if not os.path.exists("/dev/fd/0") or not os.path.exists("/dev/zero"):
- print "/dev/fd/0 or /dev/zero doesn't exist, blank the medium completely."
- self.blank()
- return
-
- cmd = self.dd + " if=/dev/zero bs=1024 count=512 | " + self.growcmd + " -Z " + self.device + "=/dev/fd/0"
- print "Running " + cmd
- oldsig = signal.signal(signal.SIGTERM, self.term_handler)
- proc = popen2.Popen4(cmd)
- self.pid = proc.pid
- status = proc.poll()
- while status == -1:
- line = proc.fromchild.readline()
- while len(line) > 0:
- print line,
- line = proc.fromchild.readline()
- time.sleep(1)
- status = proc.poll()
- self.pid = 0
- print
- signal.signal(signal.SIGTERM, oldsig)
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
-
- def blank(self):
- cmd = self.growcmd + " -Z " + self.device + "=/dev/zero"
- print "Running " + cmd
- oldsig = signal.signal(signal.SIGTERM, self.term_handler)
- proc = popen2.Popen4(cmd)
- self.pid = proc.pid
- status = proc.poll()
- while status == -1:
- line = proc.fromchild.readline()
- while len(line) > 0:
- print line,
- line = proc.fromchild.readline()
- time.sleep(1)
- status = proc.poll()
- self.pid = 0
- print
- signal.signal(signal.SIGTERM, oldsig)
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
-
- def reformat_minus_RW(self):
- cmd = self.dvdrwformat + " -force " + self.device
- print "Running " + cmd
- oldsig = signal.signal(signal.SIGTERM, self.term_handler)
- proc = popen2.Popen4(cmd)
- self.pid = proc.pid
- status = proc.poll()
- while status == -1:
- line = proc.fromchild.readline()
- while len(line) > 0:
- print line,
- line = proc.fromchild.readline()
- time.sleep(1)
- status = proc.poll()
- self.pid = 0
- print
- signal.signal(signal.SIGTERM, oldsig)
- if os.WEXITSTATUS(status) != 0:
- raise DVDError(os.WEXITSTATUS(status), cmd + " exited with status " + str(os.WEXITSTATUS(status)) + ", signal/status " + str(status))
-
-# class disk ends here.
-
-class DVDError(Exception):
- def __init__(self, errno, value):
- self.errno = errno
- self.value = value
- if self.value[-1] == '\n':
- self.value = self.value[0:-1]
- def __str__(self):
- return str(self.value) + " || errno = " + str(self.errno) + " (" + os.strerror(self.errno & 0x7F) + ")"
-
-def usage():
- print "Wrong number of arguments."
- print """
-Usage:
-
-dvd-handler DEVICE test
-dvd-handler DEVICE free
-dvd-handler DEVICE write APPEND FILE
-dvd-handler DEVICE blank
-
-where DEVICE is a device name like /dev/sr0 or /dev/dvd.
-
-Operations:
-test Scan the device and report the information found.
- This operation needs no further arguments.
-free Scan the device and report the available space.
-write Write a part file to disk.
- This operation needs two additional arguments.
- The first indicates to append (0), restart the
- disk (1) or restart existing disk (2). The second
- is the file to write.
-prepare Prepare a DVD+/-RW for being used by Bacula.
- Note: This is only useful if you already have some
- non-Bacula data on a medium, and you want to use
- it with Bacula. Don't run this on blank media, it
- is useless.
-"""
- sys.exit(1)
-
-if len(sys.argv) < 3:
- usage()
-
-dvd = disk(sys.argv[1])
-
-if "free" == sys.argv[2]:
- if len(sys.argv) == 3:
- try:
- free = dvd.free()
- except DVDError, e:
- if e.errno != 0:
- print -e.errno
- else:
- print errno.EPIPE
- print str(e)
- else:
- print free
- print "No Error reported."
- else:
- print "Wrong number of arguments for free operation. Wanted 3 got", len(sys.argv)
- print sys.argv[1], sys.argv[2], sys.argv[3]
- usage()
-elif "prepare" == sys.argv[2]:
- if len(sys.argv) == 3:
- try:
- dvd.prepare()
- except DVDError, e:
- print "Error while preparing medium: ", str(e)
- if e.errno != 0:
- sys.exit(e.errno & 0x7F)
- else:
- sys.exit(errno.EPIPE)
- else:
- print "Medium prepared successfully."
- else:
- print "Wrong number of arguments for prepare operation."
- usage()
-elif "test" == sys.argv[2]:
- try:
- print str(dvd)
- print "Blank disk: " + str(dvd.is_blank()) + " ReWritable disk: " + str(dvd.is_RW())
- print "Free space: " + str(dvd.free())
- except DVDError, e:
- print "Error while getting informations: ", str(e)
-elif "write" == sys.argv[2]:
- if len(sys.argv) == 5:
- try:
- dvd.write(long(sys.argv[3]), sys.argv[4])
- except DVDError, e:
- print "Error while writing part file: ", str(e)
- if e.errno != 0:
- sys.exit(e.errno & 0x7F)
- else:
- sys.exit(errno.EPIPE)
- else:
- print "Part file " + sys.argv[4] + " successfully written to disk."
- else:
- print "Wrong number of arguments for write operation."
- usage()
- sys.exit(1)
-else:
- print "No operation - use test, free, prepare or write."
- print "THIS MIGHT BE A CASE OF DEBUGGING BACULA OR AN ERROR!"
-sys.exit(0)