Blame SOURCES/is_true.patch

241f4b
--- /usr/share/rear/lib/global-functions.sh	2015-09-03 15:43:01.000000000 +0200
241f4b
+++ /usr/share/rear/lib/global-functions.sh	2017-01-06 12:02:52.000000000 +0100
241f4b
@@ -2,27 +2,14 @@
241f4b
 #
241f4b
 # global functions for Relax-and-Recover
241f4b
 #
241f4b
-#    Relax-and-Recover is free software; you can redistribute it and/or modify
241f4b
-#    it under the terms of the GNU General Public License as published by
241f4b
-#    the Free Software Foundation; either version 2 of the License, or
241f4b
-#    (at your option) any later version.
241f4b
-
241f4b
-#    Relax-and-Recover is distributed in the hope that it will be useful,
241f4b
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
241f4b
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
241f4b
-#    GNU General Public License for more details.
241f4b
-
241f4b
-#    You should have received a copy of the GNU General Public License
241f4b
-#    along with Relax-and-Recover; if not, write to the Free Software
241f4b
-#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
241f4b
-#
241f4b
-#
241f4b
+# This file is part of Relax-and-Recover, licensed under the GNU General
241f4b
+# Public License. Refer to the included COPYING for full text of license.
241f4b
 
241f4b
 function read_and_strip_file () {
241f4b
 # extracts content from config files. In other words: strips the comments and new lines
241f4b
-	if test -s "$1" ; then
241f4b
-		sed -e '/^[[:space:]]/d;/^$/d;/^#/d' "$1"
241f4b
-	fi
241f4b
+    if test -s "$1" ; then
241f4b
+        sed -e '/^[[:space:]]/d;/^$/d;/^#/d' "$1"
241f4b
+    fi
241f4b
 }
241f4b
 
241f4b
 function is_numeric () {
241f4b
@@ -34,27 +21,143 @@
241f4b
     fi
241f4b
 }
241f4b
 
241f4b
+# two explicit functions to be able to test explicitly for true and false (see issue #625)
241f4b
+# because "tertium non datur" (cf. https://en.wikipedia.org/wiki/Law_of_excluded_middle)
241f4b
+# does not hold for variables because variables could be unset or have empty value
241f4b
+# and to test if a variable is true or false its value is tested by that functions
241f4b
+# but the variable may not have a real value (i.e. be unset or have empty value):
241f4b
+
241f4b
+function is_true () {
241f4b
+    # the argument is usually the value of a variable which needs to be tested
241f4b
+    # only if there is explicitly a 'true' value then is_true returns true
241f4b
+    # so that an unset variable or an empty value is not true:
241f4b
+    case "$1" in
241f4b
+        ([tT] | [yY] | [yY][eE][sS] | [tT][rR][uU][eE] | 1)
241f4b
+        return 0 ;;
241f4b
+    esac
241f4b
+    return 1
241f4b
+}
241f4b
+
241f4b
+function is_false () {
241f4b
+    # the argument is usually the value of a variable which needs to be tested
241f4b
+    # only if there is explicitly a 'false' value then is_false returns true
241f4b
+    # so that an unset variable or an empty value is not false
241f4b
+    # caution: for unset or empty variables is_false is false
241f4b
+    case "$1" in
241f4b
+        ([fF] | [nN] | [nN][oO] | [fF][aA][lL][sS][eE] | 0)
241f4b
+        return 0 ;;
241f4b
+    esac
241f4b
+    return 1
241f4b
+}
241f4b
+
241f4b
 ######
241f4b
 ### Functions for dealing with URLs
241f4b
 ######
241f4b
+# URL is the most common form of URI
241f4b
+# see https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
241f4b
+# where a generic URI is of the form
241f4b
+# scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
241f4b
+# e.g. for BACKUP_URL=sshfs://user@host/G/rear/
241f4b
+# url_scheme = 'sshfs' , url_host = 'user@host' , url_hostname = 'host' , url_username = 'user' , url_path = '/G/rear/'
241f4b
+# e.g. for BACKUP_URL=usb:///dev/sdb1
241f4b
+# url_scheme = 'usb' , url_host = '' , url_hostname = '' , url_username = '' , url_path = '/dev/sdb1'
241f4b
+# FIXME: the ulr_* functions are not safe against special characters
241f4b
+# for example they break when the password contains spaces
241f4b
+# but on the other hand permitted characters for values in a URI
241f4b
+# are ASCII letters, digits, dot, hyphen, underscore, and tilde
241f4b
+# and any other character must be percent-encoded (in particular the
241f4b
+# characters : / ? # [ ] @ are reserved as delimiters of URI components
241f4b
+# and must be percent-encoded when used in the value of a URI component)
241f4b
+# so that what is missing is support for percent-encoded characters
241f4b
+# but user-friendly support for percent-encoded characters is not possible
241f4b
+# cf. http://bugzilla.opensuse.org/show_bug.cgi?id=561626#c7
241f4b
 
241f4b
-url_scheme() {
241f4b
+function url_scheme() {
241f4b
     local url=$1
241f4b
+    # the scheme is the leading part up to '://'
241f4b
     local scheme=${url%%://*}
241f4b
     # rsync scheme does not have to start with rsync:// it can also be scp style
241f4b
+    # see the comments in usr/share/rear/prep/RSYNC/default/100_check_rsync.sh
241f4b
     echo $scheme | grep -q ":" && echo rsync || echo $scheme
241f4b
 }
241f4b
 
241f4b
-url_host() {
241f4b
+function url_host() {
241f4b
+    local url=$1
241f4b
+    local url_without_scheme=${url#*//}
241f4b
+    # the authority part is the part after the scheme (e.g. 'host' or 'user@host')
241f4b
+    # i.e. after 'scheme://' all up to but excluding the next '/'
241f4b
+    # which means it breaks if there is a username that contains a '/'
241f4b
+    # which should not happen because a POSIX-compliant username
241f4b
+    # should have only characters from the portable filename character set
241f4b
+    # which is ASCII letters, digits, dot, hyphen, and underscore
241f4b
+    # (a hostname must not contain a '/' see RFC 952 and RFC 1123)
241f4b
+    local authority_part=${url_without_scheme%%/*}
241f4b
+    # for backward compatibility the url_host function returns the whole authority part
241f4b
+    # see https://github.com/rear/rear/issues/856
241f4b
+    # to get only hostname or username use the url_hostname and url_username functions
241f4b
+    echo $authority_part
241f4b
+}
241f4b
+
241f4b
+function url_hostname() {
241f4b
     local url=$1
241f4b
-    local host=${url#*//}
241f4b
-    echo ${host%%/*}
241f4b
+    local url_without_scheme=${url#*//}
241f4b
+    local authority_part=${url_without_scheme%%/*}
241f4b
+    # if authority_part contains a '@' we assume the 'user@host' format and
241f4b
+    # then we remove the 'user@' part (i.e. all up to and including the last '@')
241f4b
+    # so that it also works when the username contains a '@'
241f4b
+    # like 'john@doe' in BACKUP_URL=sshfs://john@doe@host/G/rear/
241f4b
+    # (a hostname must not contain a '@' see RFC 952 and RFC 1123)
241f4b
+    local host_and_port=${authority_part##*@}
241f4b
+    # if host_and_port contains a ':' we assume the 'host:port' format and
241f4b
+    # then we remove the ':port' part (i.e. all from and including the last ':')
241f4b
+    # so that it even works when the hostname contains a ':' (in spite of RFC 952 and RFC 1123)
241f4b
+    echo ${host_and_port%:*}
241f4b
 }
241f4b
 
241f4b
-url_path() {
241f4b
+function url_username() {
241f4b
     local url=$1
241f4b
-    local path=${url#*//}
241f4b
-    echo /${path#*/}
241f4b
+    local url_without_scheme=${url#*//}
241f4b
+    local authority_part=${url_without_scheme%%/*}
241f4b
+    # authority_part must contain a '@' when a username is specified
241f4b
+    echo $authority_part | grep -q '@' || return 0
241f4b
+    # we remove the '@host' part (i.e. all from and including the last '@')
241f4b
+    # so that it also works when the username contains a '@'
241f4b
+    # like 'john@doe' in BACKUP_URL=sshfs://john@doe@host/G/rear/
241f4b
+    # (a hostname must not contain a '@' see RFC 952 and RFC 1123)
241f4b
+    local user_and_password=${authority_part%@*}
241f4b
+    # if user_and_password contains a ':' we assume the 'user:password' format and
241f4b
+    # then we remove the ':password' part (i.e. all from and including the first ':')
241f4b
+    # so that it works when the password contains a ':'
241f4b
+    # (a POSIX-compliant username should not contain a ':')
241f4b
+    echo $user_and_password | grep -q ':' && echo ${user_and_password%%:*} || echo $user_and_password
241f4b
+}
241f4b
+
241f4b
+function url_password() {
241f4b
+    local url=$1
241f4b
+    local url_without_scheme=${url#*//}
241f4b
+    local authority_part=${url_without_scheme%%/*}
241f4b
+    # authority_part must contain a '@' when a username is specified
241f4b
+    echo $authority_part | grep -q '@' || return 0
241f4b
+    # we remove the '@host' part (i.e. all from and including the last '@')
241f4b
+    # so that it also works when the username contains a '@'
241f4b
+    # like 'john@doe' in BACKUP_URL=sshfs://john@doe@host/G/rear/
241f4b
+    # (a hostname must not contain a '@' see RFC 952 and RFC 1123)
241f4b
+    local user_and_password=${authority_part%@*}
241f4b
+    # user_and_password must contain a ':' when a password is specified
241f4b
+    echo $user_and_password | grep -q ':' || return 0
241f4b
+    # we remove the 'user:' part (i.e. all up to and including the first ':')
241f4b
+    # so that it works when the password contains a ':'
241f4b
+    # (a POSIX-compliant username should not contain a ':')
241f4b
+    echo ${user_and_password#*:}
241f4b
+}
241f4b
+
241f4b
+function url_path() {
241f4b
+    local url=$1
241f4b
+    local url_without_scheme=${url#*//}
241f4b
+    # the path is all from and including the first '/' in url_without_scheme
241f4b
+    # i.e. the whole rest after the authority part so that
241f4b
+    # it may contain an optional trailing '?query' and '#fragment'
241f4b
+    echo /${url_without_scheme#*/}
241f4b
 }
241f4b
 
241f4b
 backup_path() {
241f4b
@@ -76,7 +179,7 @@
241f4b
                path="${TMP_DIR}/isofs${path}"
241f4b
            fi
241f4b
            ;;
241f4b
-       (*)     # nfs, cifs, usb, a.o. need a temporary mount-path 
241f4b
+       (*)     # nfs, cifs, usb, a.o. need a temporary mount-path
241f4b
            path="${BUILD_DIR}/outputfs/${NETFS_PREFIX}"
241f4b
            ;;
241f4b
     esac
241f4b
@@ -93,7 +196,7 @@
241f4b
        (file)  # type file needs a local path (must be mounted by user)
241f4b
            path="$path/${OUTPUT_PREFIX}"
241f4b
            ;;
241f4b
-       (*)     # nfs, cifs, usb, a.o. need a temporary mount-path 
241f4b
+       (*)     # nfs, cifs, usb, a.o. need a temporary mount-path
241f4b
            path="${BUILD_DIR}/outputfs/${OUTPUT_PREFIX}"
241f4b
            ;;
241f4b
     esac
241f4b
@@ -129,7 +232,8 @@
241f4b
             ;;
241f4b
         (cifs)
241f4b
             if [ x"$options" = x"$defaultoptions" ];then
241f4b
-                mount_cmd="mount $v -o $options,guest //$(url_host $url)$(url_path $url) $mountpoint"
241f4b
+                # defaultoptions contains noatime which is not valid for cifs (issue #752)
241f4b
+                mount_cmd="mount $v -o rw,guest //$(url_host $url)$(url_path $url) $mountpoint"
241f4b
             else
241f4b
                 mount_cmd="mount $v -o $options //$(url_host $url)$(url_path $url) $mountpoint"
241f4b
             fi
241f4b
@@ -137,19 +241,48 @@
241f4b
         (usb)
241f4b
             mount_cmd="mount $v -o $options $(url_path $url) $mountpoint"
241f4b
             ;;
241f4b
-	(sshfs)
241f4b
-	    mount_cmd="sshfs $(url_host $url):$(url_path $url) $mountpoint -o $options"
241f4b
+        (sshfs)
241f4b
+            local authority=$( url_host $url )
241f4b
+            test "$authority" || Error "Cannot run 'sshfs' because no authority '[user@]host' found in URL '$url'."
241f4b
+            local path=$( url_path $url )
241f4b
+            test "$path" || Error "Cannot run 'sshfs' because no path found in URL '$url'."
241f4b
+            # ensure the fuse kernel module is loaded because sshfs is based on FUSE
241f4b
+            lsmod | grep -q '^fuse' || modprobe $verbose fuse || Error "Cannot run 'sshfs' because 'fuse' kernel module is not loadable."
241f4b
+            mount_cmd="sshfs $authority:$path $mountpoint -o $options"
241f4b
+            ;;
241f4b
+        (ftpfs)
241f4b
+            local hostname=$( url_hostname $url )
241f4b
+            test "$hostname" || Error "Cannot run 'curlftpfs' because no hostname found in URL '$url'."
241f4b
+            local path=$( url_path $url )
241f4b
+            test "$path" || Error "Cannot run 'curlftpfs' because no path found in URL '$url'."
241f4b
+            local username=$( url_username $url )
241f4b
+            # ensure the fuse kernel module is loaded because ftpfs (via CurlFtpFS) is based on FUSE
241f4b
+            lsmod | grep -q '^fuse' || modprobe $verbose fuse || Error "Cannot run 'curlftpfs' because 'fuse' kernel module is not loadable."
241f4b
+            if test "$username" ; then
241f4b
+                local password=$( url_password $url )
241f4b
+                if test "$password" ; then
241f4b
+                    # single quoting is a must for the password
241f4b
+                    mount_cmd="curlftpfs $verbose -o user='$username:$password' ftp://$hostname$path $mountpoint"
241f4b
+                else
241f4b
+                    # also single quoting for the plain username so that it also works for non-POSIX-compliant usernames
241f4b
+                    # (a POSIX-compliant username should only contain ASCII letters, digits, dot, hyphen, and underscore)
241f4b
+                    mount_cmd="curlftpfs $verbose -o user='$username' ftp://$hostname$path $mountpoint"
241f4b
+                fi
241f4b
+            else
241f4b
+                mount_cmd="curlftpfs $verbose ftp://$hostname$path $mountpoint"
241f4b
+            fi
241f4b
+            ;;
241f4b
+        (davfs)
241f4b
+            mount_cmd="mount $v -t davfs http://$(url_host $url)$(url_path $url) $mountpoint"
241f4b
             ;;
241f4b
-	(davfs)
241f4b
-	    mount_cmd="mount $v -t davfs http://$(url_host $url)$(url_path $url) $mountpoint"
241f4b
-	    ;;
241f4b
         (*)
241f4b
             mount_cmd="mount $v -t $(url_scheme $url) -o $options $(url_host $url):$(url_path $url) $mountpoint"
241f4b
             ;;
241f4b
     esac
241f4b
 
241f4b
     Log "Mounting with '$mount_cmd'"
241f4b
-    $mount_cmd >&2
241f4b
+    # eval is required when mount_cmd contains single quoted stuff (e.g. see the above mount_cmd for curlftpfs)
241f4b
+    eval $mount_cmd >&2
241f4b
     StopIfError "Mount command '$mount_cmd' failed."
241f4b
 
241f4b
     AddExitTask "umount -f $v '$mountpoint' >&2"
241f4b
@@ -182,7 +315,7 @@
241f4b
             # and delete only the just used cache
241f4b
             #rm -rf /var/cache/davfs2/*<mountpoint-hash>*
241f4b
             rm -rf /var/cache/davfs2/*outputfs*
241f4b
-            
241f4b
+
241f4b
 	    ;;
241f4b
         (var)
241f4b
             local var=$(url_host $url)
241f4b
@@ -228,3 +361,4 @@
241f4b
     Log "Unmounting '$mountpoint' failed."
241f4b
     return 1
241f4b
 }
241f4b
+