/
usr
/
share
/
backup-manager
/
Upload File
HOME
# Copyright � 2005-2016 The Backup Manager Authors # # See the AUTHORS file for details. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # # CD/DVD discs burning features # function bm_safe_unmount { device="$1" debug "bm_safe_unmount($device)" realdevice=$(ls -l $device | awk '{print $10}') if [[ -n "$realdevice" ]]; then device="$realdevice" fi for m in `grep $device /etc/mtab 2>/dev/null| awk '{print $2}'` do info "Device \"/dev/\$device\" is mounted on \"\$m\", unmounting it." umount $m 2>/dev/null sleep 1 done } # This will get all the md5 sums of the day, # mount the BM_BURNING_DEVICE on /tmp/device and check # that the files are correct with md5 tests. function check_cdrom_md5_sums() { debug "check_cdrom_md5_sums()" has_error=0 if [[ -z $BM_BURNING_DEVICE ]]; then error "MD5 checkup is only performed on disks. Please set the BM_BURNING_DEVICE in \$conffile" fi # first create the mount point mount_point="$(mktemp -d ${BM_TEMP_DIR}/bm-mnt.XXXXXX)" if [[ ! -d $mount_point ]]; then error "The mount point \$mount_point is not there." fi # if MD5FILE does not exist, there are no md5 sums to compare anyway if [[ ! -f $MD5FILE ]]; then error "Missing md5 sums database ($MD5FILE); cannot check md5 sums." fi # unmount if needed bm_safe_unmount $BM_BURNING_DEVICE # mount the device in /tmp/ info "Mounting \$BM_BURNING_DEVICE on \$mount_point." mount $BM_BURNING_DEVICE $mount_point >& /dev/null export HAS_MOUNTED=1 # now we can check the md5 sums. for file in $mount_point/*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]* do base_file=$(basename $file) date_of_file=$(get_date_from_file $file) prefix_of_file=$(get_prefix_from_file $file) # Do not check the md5 sums of indexes. if [[ "$prefix_of_file" = "index" ]]; then continue fi str=$(echo_translated "Checking MD5 sum for \$base_file:") # try to read the previously saved md5 hash in the database md5hash_trust=$(get_md5sum_from_file ${base_file} $MD5FILE) # If the MD5 hash was not found, do not generate it; instead # issue a warning that the burned archive cannot be verified if [[ -z "$md5hash_trust" ]]; then warning "Cannot verify correct burning of $base_file; did not found md5 sum in database" continue fi # now calculate burnt archive's md5 sum and compare with database md5hash_cdrom=$(get_md5sum $file) || md5hash_cdrom="undefined" case $md5hash_cdrom in $md5hash_trust) echo_translated "\$str ok." ;; undefined) echo_translated "\$str failed (read error)." has_error=1 ;; *) echo_translated "\$str failed (MD5 hash mismatch)." has_error=1 ;; esac done if [[ $has_error = 1 ]]; then warning "Errors encountered during MD5 checks." fi # remove the mount point umount $BM_BURNING_DEVICE || error "Unable to unmount the mount point \$mount_point" rmdir $mount_point || error "Unable to remove the mount point \$mount_point" } # this will try to burn the generated archives to the disc # choosed in the configuration. # Obviously, we will use mkisofs for generating the iso and # cdrecord for burning CD, growisofs for the DVD. # Note that we pipe the iso image directly to cdrecord # in this way, we prevent the use of precious disk place. # # Two cases are possible: # - non-interactive mode: will try to burn data on a single disc # - interactive mode : will ask for next disc if needed. function burn_files() { debug "burn_files()" if [[ "$BM_BURNING_METHOD" = "none" ]] || [[ -z "$BM_BURNING_METHOD" ]]; then info "No burning method used." return 0 fi # Choose which mode to use (interactive or not) # according to the standard input if tty -s ; then debug "tty detected, using the interactive mode" burn_files_interactive else debug "no tty detected, non-interactive mode" burn_files_non_interactive fi } function find_what_to_burn() { source="$1" debug "find_what_to_burn($source)" what_to_burn="" nb_file=$(ls -l $source 2>/dev/null | wc -l) if [[ $nb_file -gt 0 ]]; then info "Number of files to burn: \$nb_file." else error "Nothing to burn for the \$BM__BURNING_DATE, try the '--burn <date>' switch." fi for file in $source do if [[ ! -L $file ]]; then what_to_burn="$what_to_burn $file" fi done } # This has to do something without any interactive input. function burn_files_non_interactive() { debug "burn_files_non_interactive()" # find what to burn according to the size... what_to_burn="" size=$(size_of_path "$BM_REPOSITORY_ROOT") # We can't burn the whole repository, using only today's archives if [[ $size -gt $BM_BURNING_MAXSIZE ]] || [[ -n "${BM__BURNING_DATE}" ]]; then if [[ -z "$BM__BURNING_DATE" ]]; then BM__BURNING_DATE="$TODAY" fi BM__BURNING_DATE="$TODAY" info "Burning archives of \$BM__BURNING_DATE." size=$(size_of_path "${BM_REPOSITORY_ROOT}/*${BM__BURNING_DATE}*") # does not fit neither, cannot burn anything. if [[ $size -gt $BM_BURNING_MAXSIZE ]]; then error "Cannot burn archives of the \$BM__BURNING_DATE, too big: \${size}M, must fit in \$BM_BURNING_MAXSIZE" fi find_what_to_burn "${BM_REPOSITORY_ROOT}/*${BM__BURNING_DATE}*" else BM__BURNING_DATE="$TODAY" find_what_to_burn "${BM_REPOSITORY_ROOT}/*" fi burn_session "$what_to_burn" } # This will be used only in interactive mode, then we can burn # the whole repository safely: user will change disc when needed (hopefully). # (anyway, we rely on this assertion, this should be documented). function burn_files_interactive() { debug "burn_files_interactive()" purge_indexes if [[ ! -z "${BM__BURNING_DATE}" ]] ; then info "Burning archives of \$BM__BURNING_DATE." find_what_to_burn "${BM_REPOSITORY_ROOT}/*${BM__BURNING_DATE}*" size=$(size_of_path "${BM_REPOSITORY_ROOT}/*${BM__BURNING_DATE}*") else info "Burning the whole archives." BM__BURNING_DATE="$TODAY" find_what_to_burn "${BM_REPOSITORY_ROOT}/*" size=$(size_of_path "${BM_REPOSITORY_ROOT}") fi info "Trying to burn \$BM_REPOSITORY_ROOT (\$size MB) in interactive mode. You will be prompted to enter insert a disc when needed" burn_multiples_media "$what_to_burn" } # This will burn $what_to_burn on a single session # It must fit in a medium function burn_session() { what_to_burn="$1" session_number="$2" number_of_indexes="$3" debug "burn_session($what_to_burn, $session_number, $number_of_indexes)" # Since version 0.7.5 disc-image can be non-joliet. # This is handled by $BM_BURNING_ISO_FLAGS, let's default that # variable for backward compat. if [[ -z "$BM_BURNING_ISO_FLAGS" ]]; then BM_BURNING_ISO_FLAGS="-R -J" fi if [[ -z "$session_number" ]] || [[ $session_number = 1 ]]; then title="Backups of ${BM__BURNING_DATE}" else title="Backups of ${BM__BURNING_DATE} - $session_number/$number_of_indexes" fi # Let's unmount the device first bm_safe_unmount $BM_BURNING_DEVICE # get a log file in a secure path logfile="$(mktemp ${BM_TEMP_DIR}/bm-burning.log.XXXXXX)" info "Redirecting burning logs into \$logfile" # set the cdrecord command devforced="" if [[ -n "$BM_BURNING_DEVFORCED" ]]; then info "Forcing dev=\${BM_BURNING_DEVFORCED} for cdrecord commands." devforced="dev=${BM_BURNING_DEVFORCED}" fi # burning the iso with the user choosen method case "$BM_BURNING_METHOD" in "DVD") if [[ ! -x $growisofs ]]; then error "DVD+R(W) burning requires \$growisofs, aborting." fi info "Exporting archives to the DVD+R(W) disc in \$BM_BURNING_DEVICE." debug "$growisofs -use-the-force-luke=tty -Z ${BM_BURNING_DEVICE} ${BM_BURNING_ISO_FLAGS} -V \"${title}\" ${what_to_burn} >> ${logfile}" tail_logfile $logfile $growisofs -use-the-force-luke=tty -Z ${BM_BURNING_DEVICE} ${BM_BURNING_ISO_FLAGS} -V "${title}" ${what_to_burn} >> ${logfile} 2>&1 || error "failed, check \$logfile" ;; "DVD-RW") if [[ ! -x $growisofs ]]; then error "DVD-R(W) burning requires \$growisofs, aborting." fi if [[ ! -x $dvdrwformat ]]; then error "DVD-R(W) burning requires \$dvdrwformat, aborting." fi info "Blanking the DVD-R(W) disc in \$BM_BURNING_DEVICE" debug "$dvdrwformat -blank $BM_BURNING_DEVICE > $logfile" tail_logfile $logfile $dvdrwformat -blank $BM_BURNING_DEVICE > $logfile 2>&1 || error "Unable to blank the DVD-R(W) disc (check \$logfile)." info "Exporting archives to the DVD-R(W) disc in \$BM_BURNING_DEVICE." debug "$growisofs -use-the-force-luke=tty -Z ${BM_BURNING_DEVICE} ${BM_BURNING_ISO_FLAGS} -V \"${title}\" ${what_to_burn} >> ${logfile}" $growisofs -use-the-force-luke=tty -Z ${BM_BURNING_DEVICE} ${BM_BURNING_ISO_FLAGS} -V "${title}" ${what_to_burn} >> ${logfile} 2>&1 || error "failed, check \$logfile" ;; "CDRW") if [[ ! -x $cdrecord ]]; then error "CD-R(W) burning requires \$cdrecord, aborting." fi info "Blanking the CDRW in \$BM_BURNING_DEVICE." debug "${cdrecord} -tao $devforced blank=fast > ${logfile}" tail_logfile $logfile ${cdrecord} -tao $devforced blank=fast > ${logfile} 2>&1 || error "failed, check \$logfile" info "Burning data to \$BM_BURNING_DEVICE." debug "${mkisofs} -V \"${title}\" -q ${BM_BURNING_ISO_FLAGS} ${what_to_burn} | ${cdrecord} -tao $devforced - > ${logfile}" ${mkisofs} -V "${title}" -q ${BM_BURNING_ISO_FLAGS} ${what_to_burn} | \ ${cdrecord} -tao $devforced - > ${logfile} 2>&1 || error "failed, check \$logfile" ;; "CDR") if [[ ! -x $cdrecord ]]; then error "CD-R(W) burning requires \$cdrecord, aborting." fi info "Burning data to \$BM_BURNING_DEVICE." debug "${mkisofs} -V \"${title}\" -q ${BM_BURNING_ISO_FLAGS} ${what_to_burn} | ${cdrecord} -tao $devforced - > ${logfile}" tail_logfile $logfile ${mkisofs} -V "${title}" -q ${BM_BURNING_ISO_FLAGS} ${what_to_burn} | \ ${cdrecord} -tao $devforced - > ${logfile} 2>&1 || error "failed, check \$logfile" ;; "none"|"NONE") info "Nothing to burn." ;; *) error "The requested burning method is not supported, check BM_BURNING_METHOD in \$conffile" ;; esac # Cleaning the logile, everything was fine at this point. rm -f $logfile # checking the files in the CDR if wanted if [[ $BM_BURNING_CHKMD5 = true ]]; then check_cdrom_md5_sums fi } function purge_indexes() { debug "purge_indexes()" index_prefix=$(get_index_prefix) rm -f ${index_prefix}* } function get_index_prefix() { debug "get_index_prefix()" index_prefix="$BM_REPOSITORY_ROOT/index-${BM__BURNING_DATE}" echo "$index_prefix" } # Parse "$target" and build index files. Put as many files in index as possible # according to BM_BURNING_MAXSIZE. # indexes are not included here, should be added by hand after that processing. function __build_indexes_from_target() { target="$1" debug "__build_indexes_from_target ($target)" indexes="" medium_index="" index_number=1 number_of_indexes=1 index_prefix=$(get_index_prefix) index_session="$index_prefix-$index_number" # Sorting by filetypes target=$(ls -v $target) # Write the indexes files in order to have one index file by medium. # When a medium is full, we create a new one. for file in ${target} do if [[ ! -f $file ]]; then continue fi size_of_file=$(size_of_path "$file") if [[ $size_of_file -gt $BM_BURNING_MAXSIZE ]] ; then warning "Not burning \$file because it does not fit in the disk." continue fi # Addd file to the index file. medium_possible_index="$medium_index $file" size_of_possible_index=$(size_of_path "$medium_possible_index") if [[ $size_of_possible_index -gt $BM_BURNING_MAXSIZE ]] ; then indexes="$indexes $index_session" number_of_indexes=$(($number_of_indexes +1)) index_number=$(($index_number + 1)) index_session="$index_prefix-$index_number" echo "$file" > $index_session medium_index="$file" medium_possible_index="" else echo "$file" >> $index_session medium_index="$medium_possible_index" fi done indexes="$indexes $index_session" } function __insert_new_medium() { debug "__insert_new_medium()" bm_pause "$(translate "Please insert a new disk in \$BM_BURNING_DEVICE")" } function __burn_session_from_file() { index_file="$1" session_number="$2" number_of_indexes="$3" debug "__burn_session_from_file ($index_file, $session_number, $number_of_indexes)" if [[ ! -e "$index_file" ]]; then error "No such index file: \"\$index_file\"." fi what_to_burn_session="" for file_to_burn in $(cat "$index_file") do what_to_burn_session="$what_to_burn_session $file_to_burn" done what_to_burn="$what_to_burn_session" burn_session "$what_to_burn_session" "$session_number" "$number_of_indexes" } function __append_index_paths_in_indexes() { debug "__append_index_paths_in_indexes()" prefix=$(get_index_prefix) for index_file in $prefix* do for index_path in $prefix* do echo "$index_path" >> $index_file done done } function burn_multiples_media() { target="$1" debug "burn_multiples_media ($target)" # first purge existing indexs purge_indexes # put in $indexes a list of files that contain # archives to put on each medium. __build_indexes_from_target "$target" # Display the number of medias required by the burning systemp. if [[ $number_of_indexes -eq 1 ]]; then info "The burning process will need one disk." else info "The burning process will need \$number_of_indexes disks." fi # Now that all indexes are built, list them so we can find # them all in the media. __append_index_paths_in_indexes # foreach index, build its content on a media, interactively session_number=0 for index in $indexes do session_number=$(($session_number + 1)) info "Burning content of \$index" __insert_new_medium __burn_session_from_file "$index" "$session_number" "$number_of_indexes" done # Remove all the index files. rm -f $indexes }