Try to fetch missing packages from hugovil.com
[hvlinux.git] / functions / fpkg
index 8781366..ee290c5 100644 (file)
@@ -3,21 +3,33 @@
 source ../config/urls
 source ../functions/gztobz2
 
-LFS_PKG_BASE="$(dirname $(pwd))/packages"
-LFS_PKG_DIR="${LFS_PKG_BASE}/${LFS_STAGE}"
-LFS_LOG_DIR="${LFS}/var/log/hvlinux-install/${LFS_STAGE}"
-LFS_LOG_FILE="${LFS_LOG_DIR}/pkg-update.log"
-WGET_LOG_FILE="${LFS_LOG_DIR}/pkg-wget.log"
+# Ownership of downloaded files
+FPKG_USER="root"
+FPKG_GROUP="users"
 
-WGETCMD="wget --directory-prefix=${LFS_PKG_DIR} --timeout=15 --tries=3 -nc --continue --no-check-certificate --no-verbose --output-file=${WGET_LOG_FILE}"
+# Test if the given file extension correspond to a compressed archive
+# Arg. #1: File extension
+is_extension_archive()
+{
+    if [ ${#} -ne 1 ]; then
+       echo "${FUNCNAME}(), wrong number of arguments: ${*}"
+       return 1
+    fi
+
+    local EXT=${1}
 
-LFS_PATCHES_LIST=${LFS_PKG_DIR}/patches-list-lfs.html
-BLFS_PATCHES_LIST=${LFS_PKG_DIR}/patches-list-blfs.html
-CLFS_PATCHES_LIST=${LFS_PKG_DIR}/patches-list-clfs.html
-HV_PATCHES_LIST=${LFS_PKG_DIR}/patches-list-hv.html
+    for k in "gz" "tgz" "Z" "zip" "xz" "bz2"; do
+        if [ "x${EXT}" = "x${k}" ]; then
+            return 0
+        fi
+    done
+
+    return 1
+}
 
 # Test if the given file extension correspond to a tar/gzip archive
-is_archive_tar_gzip()
+# Arg. #1: File extension
+is_extension_tar_gzip()
 {
     if [ ${#} -ne 1 ]; then
        echo "${FUNCNAME}(), wrong number of arguments: ${*}"
@@ -35,19 +47,132 @@ is_archive_tar_gzip()
     return 1
 }
 
+# Test if the given file is an archive file
+# Arg. #1: File name
+is_archive()
+{
+    if [ ${#} -ne 1 ]; then
+       echo "${FUNCNAME}(), wrong number of arguments: ${*}"
+       return 1
+    fi
+
+    local F=${1}
+
+    if file ${F} | grep -q --ignore-case -e "compressed data" -e "Zip archive data"; then
+        return 0;
+    else
+        return 1
+    fi
+}
+
+# Remove any partially downloaded file.
+# Arg. #1: Partial file name without partial extension (.part).
+remove_partial_file()
+{
+    rm -f ${1}.part
+}
+
+# Download a file, and making sure it is valid (at least it's header!)
+# Arg. #1: Source URL.
+# Arg. #2: Source filename (on server)
+# Arg. #3: Output directory (optional). Default = LFS_PKG_DIR
+#
+# Return: 0 : success
+#         1 : wget error
+#         2 : File not found or not an archive (if file extension was archive type)
+wget_wrapper()
+{
+    if [ ${#} -lt 2 ]; then
+       echo "${FUNCNAME}(), wrong number of arguments: ${*}"
+       return 1
+    fi
+
+    local URL=${1}
+    local SOURCE=${2}
+    local DESTDIR=${LFS_PKG_DIR}
+    local wget_status
+
+    if [ ${#} -eq 3 ]; then
+        DESTDIR=${3}
+    fi
+
+    remove_partial_file ${DESTDIR}/${SOURCE}
+
+    local STRING="Fetching ${SOURCE}"
+    if [ "x${FTYPE}" = "x${FTYPE_PATCH}" ]; then
+        STRING="${STRING} from ${URL}"
+    fi
+
+    rcmd "${STRING}" ${WGETCMD} ${URL}/${SOURCE} \
+        --output-document=${DESTDIR}/${SOURCE}.part
+    wget_status=$?
+
+    chown ${FPKG_USER}:${FPKG_GROUP} ${DESTDIR}/${SOURCE}.part
+    chmod 664 ${DESTDIR}/${SOURCE}.part
+
+    # Append log to global log file
+    cat ${WGET_LOG_FILE} >> ${LFS_LOG_FILE}
+
+    # Total failure if it was a connection timeout.
+    if grep -q "failed: Connection timed out" ${WGET_LOG_FILE}; then
+        echo "Error, wget reported: Connection timed out"
+        return 1
+    fi
+
+    # Partial failure if file was not found.
+    if detect_file_not_found; then
+        remove_partial_file ${DESTDIR}/${SOURCE}
+        return 2
+    fi
+
+    if [ ${wget_status} -ne 0 ]; then
+        echo "Error: wget returned error status ${wget_status}" >> \
+            ${LFS_LOG_FILE}
+        remove_partial_file ${DESTDIR}/${SOURCE}
+        return 1
+    fi
+
+    local FEXT=${SOURCE##*.}
+    if is_extension_archive "${FEXT}"; then
+        # Just to be sure, test if downloaded file is really an archive:
+        if ! is_archive ${DESTDIR}/${SOURCE}.part; then
+            # Partial failure if file is invalid.
+            echo "Error: failed archive test" >> ${LFS_LOG_FILE}
+            remove_partial_file ${DESTDIR}/${SOURCE}
+            return 2
+        fi
+    fi
+
+    # Rename temporary file to final name
+    mv ${DESTDIR}/${SOURCE}{.part,}
+    chown ${FPKG_USER}:${FPKG_GROUP} ${DESTDIR}/${SOURCE}
+    chmod 664 ${DESTDIR}/${SOURCE}
+
+    return 0
+}
+
 # Arg. #1: URL for patches repository.
 # Arg. #2: Destination filename.
 static_fetch_patches_list()
 {
+    local wget_status
+
     PATCHES_URL=${1}
     PATCHES_LIST_FILENAME=${2}
 
-    ${WGETCMD} "${PATCHES_URL}/" &&
+    # Appending a slash (/) will download the directory content as a file named
+    # index.html
+    ${WGETCMD} "${PATCHES_URL}/"
+    wget_status=$?
 
     # Append log to global log file
-    cat ${WGET_LOG_FILE} >> ${LFS_LOG_FILE} &&
+    cat ${WGET_LOG_FILE} >> ${LFS_LOG_FILE}
 
-    mv ${LFS_PKG_DIR}/index.html ${PATCHES_LIST_FILENAME}
+    if [ ${wget_status} -eq 0 ]; then
+        mv ${LFS_PKG_DIR}/index.html ${PATCHES_LIST_FILENAME}
+    else
+        return 1
+    fi
 }
 
 # Arg. #1: If "test" is specified, set TEST_INTEGRITY to 1
@@ -61,14 +186,24 @@ update_packages_init()
     # downloading other packages
     export RCMD_NO_EXIT=1
 
-    # First create log directory if it does not exists.
-    if [ ! -d ${LFS_LOG_DIR} ]; then
-       install -m755 -d ${LFS_LOG_DIR} || exit 1
-    fi
+    init_log_file_update
+
+    export LFS_PATCHES_LIST=${LFS_PKG_DIR}/patches/list-lfs.html
+    export BLFS_PATCHES_LIST=${LFS_PKG_DIR}/patches/list-blfs.html
+    export CLFS_PATCHES_LIST=${LFS_PKG_DIR}/patches/list-clfs.html
+    export WGET_LOG_FILE="${LFS_LOG_DIR}/pkg-wget.log"
+    export WGETCMD="wget --directory-prefix=${LFS_PKG_DIR} --timeout=15 --tries=3 -nc --continue --no-check-certificate --no-verbose --output-file=${WGET_LOG_FILE}"
 
     # Then create destination directory if it does not exists.
     if [ ! -d ${LFS_PKG_DIR} ]; then
-       install -v -m755 -d ${LFS_PKG_DIR} 1> ${LFS_LOG_FILE} 2>&1 || exit 1
+       install -v -m775 -o ${FPKG_USER} -g ${FPKG_GROUP} \
+            -d ${LFS_PKG_DIR} 1> ${LFS_LOG_FILE} 2>&1 || exit 1
+    fi
+
+    # Create patches destination directory if it does not exists.
+    if [ ! -d ${LFS_PATCHES_DIR} ]; then
+       install -v -m775 -o ${FPKG_USER} -g ${FPKG_GROUP} \
+            -d ${LFS_PATCHES_DIR} 1> ${LFS_LOG_FILE} 2>&1 || exit 1
     fi
 
     if [ -n "${TEST_INTEGRITY}" ]; then
@@ -81,28 +216,26 @@ update_packages_init()
        return 1
     fi
 
-    if [ -n "${USE_LFS_PATCHES}" ]; then
-        # Getting list of all patches from LFS server.
-        rcmd "Fetching LFS patches list" static_fetch_patches_list ${LFS_PATCHES_URL} ${LFS_PATCHES_LIST}
-    fi
+    # Temporary deactivate error checking.
+    set +e
 
-    if [ -n "${USE_BLFS_PATCHES}" ]; then
-        # Getting list of all patches from BLFS server.
-        rcmd "Fetching BLFS patches list" static_fetch_patches_list ${BLFS_PATCHES_URL} ${BLFS_PATCHES_LIST}
-    fi
+    # Getting list of all patches from LFS server.
+    rcmd "Fetching LFS  patches list" static_fetch_patches_list \
+        ${LFS_PATCHES_URL} ${LFS_PATCHES_LIST}
 
-    if [ -n "${USE_CLFS_PATCHES}" ]; then
-        # Getting list of all patches from CLFS server.
-        rcmd "Fetching CLFS patches list" static_fetch_patches_list ${CLFS_PATCHES_URL} ${CLFS_PATCHES_LIST}
-    fi
+    # Getting list of all patches from BLFS server.
+    rcmd "Fetching BLFS patches list" static_fetch_patches_list \
+        ${BLFS_PATCHES_URL} ${BLFS_PATCHES_LIST}
 
-    if [ -n "${USE_HV_PATCHES}" ]; then
-        # Getting list of all patches from hugovil.com server.
-        rcmd "Fetching hugovil.com patches list" static_fetch_patches_list ${HV_PATCHES_URL} ${HV_PATCHES_LIST}
-    fi
+    # Getting list of all patches from CLFS server.
+    rcmd "Fetching CLFS patches list" static_fetch_patches_list \
+        ${CLFS_PATCHES_URL} ${CLFS_PATCHES_LIST}
+
+    # Reactivate error checking.
+    set -e
 }
 
-# Get patch package if it is not in the repository
+# Get patch for package if it is not in the repository
 # Arg. #1: Package name and version
 # Arg. #2: Patches list file (HTML)
 # Arg. #3: Patches URL
@@ -112,17 +245,33 @@ static_checkpatch()
     local PATCHES_LIST=${2}
     local PATCHES_URL=${3}
 
+    # Make sure patch list file exists
+    if [ ! -f ${PATCHES_LIST} ]; then
+        return
+    fi
+
     # Remplace les "+" par "%2B"
     local PACK_URL=$(echo $PACK | sed s!\+!%2B!g)
 
-    local PATCHES_FOUND=$(cat ${PATCHES_LIST} | grep "${PACK_URL}-" | sed "s/.*\(${PACK_URL}-.*\.patch\).*/\1/")
+    # Patches list formats (patches-list-*.html):
+    #   LFS:     a href="name.patch"
+    #   hugovil: a href="dir/subdir/subdir/name.patch"
+    # We must search for a patch beginning with either a slash or a " to avoid
+    # the possibility of having another package name within a patch name:
+    #   if patch = Mesalib-8.0.4-llvm-3.1-fixes-1.patch
+    #   then we could erroneously try to download patch "llvm-3.1-fixes-1.patch"
+    local PATCHES_FOUND=$(cat ${PATCHES_LIST} | \
+        egrep "\"${PACK_URL}-|/${PACK_URL}-" | \
+        egrep ".patch\"" | \
+        sed "s/.*\(${PACK_URL}-.*\.patch\)\".*/\1/")
+
     if [ -n "${PATCHES_FOUND}" ]; then
        for p in ${PATCHES_FOUND}; do
             # Remplace les "%2B" par "+"
             PATCH_NAME=$(echo ${p} | sed s!%2B!\+!g)
 
-           if [ ! -f ${LFS_PKG_DIR}/${PATCH_NAME} ]; then
-               rcmd "Fetching ${PATCH_NAME} from ${PATCHES_URL}" ${WGETCMD} ${PATCHES_URL}/${p}
+           if [ ! -f ${LFS_PATCHES_DIR}/${PATCH_NAME} ]; then
+                wget_wrapper ${PATCHES_URL} ${PATCH_NAME} ${LFS_PATCHES_DIR}
            fi
        done
     fi
@@ -140,25 +289,14 @@ static_getpatch()
        return 1
     fi
 
-    if [ -n "${USE_LFS_PATCHES}" ]; then
-        # Checking if patch is available from LFS.
-        static_checkpatch ${PACK} ${LFS_PATCHES_LIST} ${LFS_PATCHES_URL}
-    fi
-
-    if [ -n "${USE_BLFS_PATCHES}" ]; then
-        # Checking if patch is available from BLFS.
-        static_checkpatch ${PACK} ${BLFS_PATCHES_LIST} ${BLFS_PATCHES_URL}
-    fi
+    # Checking if patch is available from LFS.
+    static_checkpatch ${PACK} ${LFS_PATCHES_LIST} ${LFS_PATCHES_URL}
 
-    if [ -n "${USE_CLFS_PATCHES}" ]; then
-        # Checking if patch is available from CLFS.
-        static_checkpatch ${PACK} ${CLFS_PATCHES_LIST} ${CLFS_PATCHES_URL}
-    fi
+    # Checking if patch is available from BLFS.
+    static_checkpatch ${PACK} ${BLFS_PATCHES_LIST} ${BLFS_PATCHES_URL}
 
-    if [ -n "${USE_HV_PATCHES}" ]; then
-        # Checking if patch is available from hugovil.com.
-        static_checkpatch ${PACK} ${HV_PATCHES_LIST} ${HV_PATCHES_URL}
-    fi
+    # Checking if patch is available from CLFS.
+    static_checkpatch ${PACK} ${CLFS_PATCHES_LIST} ${CLFS_PATCHES_URL}
 }
 
 detect_file_not_found()
@@ -170,7 +308,7 @@ detect_file_not_found()
         #echo "404 NOTFOUND"
         return 0
     fi
-    
+
     return 1
 }
 
@@ -200,52 +338,50 @@ static_getpkg()
         PREFERRED_EXT="${DEFAULT_ARCH_EXT_LIST}"
     fi
 
-    for arch_ext in ${PREFERRED_EXT}; do
-        # Don't take any chance: remove any partially downloaded file.
-        # If we arrive here, it means the final destination file was not found
-        # so we can safely remove any file prior to trying to download it.
-        rm -f ${LFS_PKG_DIR}/${PACK}.${arch_ext}
+    wget_wrapper_status=
+    url_list="${URL}"
 
-        rcmd "Fetching ${PACK}.${arch_ext}" \
-            ${WGETCMD} ${URL}/${PACK}.${arch_ext}
-        wget_status=$?
+    if [ x"${URL}" != x"${HV_PACKAGES_URL}" ]; then
+        url_list+=" ${HV_PACKAGES_URL}"
+    fi
 
-        # Append log to global log file
-        cat ${WGET_LOG_FILE} >> ${LFS_LOG_FILE}
+    for url in ${url_list}; do
+        for arch_ext in ${PREFERRED_EXT}; do
+            wget_wrapper ${url} ${PACK}.${arch_ext}
+            wget_wrapper_status=$?
 
-        # Failure: if it was a connection timeout, don't try for other file
-        # extensions.
-        if grep -q "failed: Connection timed out" ${WGET_LOG_FILE}; then
-            echo "Error, wget reported: Connection timed out"
-            return 1
-        fi
+            #if [ ${wget_wrapper_status} -eq 1 ]; then
+            #    return 1;
+            #fi
 
-        if detect_file_not_found; then
-            # Try next archive extension if file was not found.
-            continue;
-        fi
+            if [ ${wget_wrapper_status} -eq 0 ]; then
+                break;
+            fi
+        done
 
-        if [ ${wget_status} -ne 0 ]; then
-            return 1
+        if [ ${wget_wrapper_status} -eq 0 ]; then
+            break;
         fi
+    done
 
-        # If we are here, it means the file was successfully downloaded.
-        FINAL_EXT=${arch_ext}
+    # Failure or file not found
+    if [ ${wget_wrapper_status} -gt 0 ]; then
+        return 1;
+    fi
 
-        # Convert to bzip2 format if requested and if it is a tar/gz archive
-        if [ -n "${PREFER_BZIP2_ARCHIVE}" ]; then
-            if is_archive_tar_gzip "${arch_ext}" ; then
-                rcmd "Converting ${PACK}.${arch_ext} to bzip2 format" \
-                    gztobz2 ${LFS_PKG_DIR}/${PACK}.${arch_ext}
-                FINAL_EXT="tar.bz2"
-            fi
-        fi
+    # If we are here, it means the file was successfully downloaded.
+    FINAL_EXT=${arch_ext}
 
-        return $?
-    done
+    # Convert to bzip2 format if requested and if it is a tar/gz archive
+    if [ -n "${PREFER_BZIP2_ARCHIVE}" ]; then
+        if is_extension_tar_gzip "${arch_ext}" ; then
+            rcmd "Converting ${PACK}.${arch_ext} to bzip2 format" \
+                 gztobz2 ${LFS_PKG_DIR}/${PACK}.${arch_ext}
+            FINAL_EXT="tar.bz2"
+        fi
+    fi
 
-    # Failure or file not found
-    return 1
+    return 0
 }
 
 # Test integrity of archive
@@ -272,10 +408,14 @@ test_archive_integrity()
 
     if [ "x${EXT}" = "xtar.bz2" ]; then
         TESTCMD="bzip2 -t"
-    elif is_archive_tar_gzip "${EXT}"; then
+    elif is_extension_tar_gzip "${EXT}"; then
         TESTCMD="gunzip -t"
+    elif [ "x${EXT}" = "xtar.xz" ]; then
+        TESTCMD="unxz -t"
+    elif [ "x${EXT}" = "xzip" ]; then
+        TESTCMD="unzip -t"
     else
-        # Can only test gzip and bzip2 archives
+        # Can only test gzip, bzip2, xz and zip archives.
         return 0
     fi
 
@@ -300,7 +440,14 @@ test_archive_integrity()
 #            pm (Perl module via CPAN)
 #            fd (freedesktop.org)
 #   -o     Option specific to mode
-#   -s     Subdirectory on server
+#   -s DIR Subdirectory on server
+#   -v NUM Subdirectory on server is equal to package version. If -s option is specified, then
+#          append version number to value of -s argument:
+#            NUM=  Full version number
+#            NUM=1 First number of package version
+#            NUM=2 First two numbers of package version
+#          Ex: fpkg -s "v" -v 2 mypkg-1.2.3 http://mypkg.com would fetch from url:
+#                  http://mypkg.com/v1.2/mypkg-1.2.3.tar.bz2
 #   -w     First erase destination file if it exists (except in test mode)
 fpkg()
 {
@@ -312,9 +459,11 @@ fpkg()
     local MODE_OPT=""
     local SRC_DIR=""
     local FD_SUBDIR_FINAL=""
+    local VARG=""
+    unset VOPTION
     unset ERASE_FIRST
 
-    while getopts "d:e:f:m:o:s:w" flag ;do
+    while getopts "d:e:f:m:o:s:v:w" flag ;do
         case ${flag} in
            d)
                 # Fetch directory (where to put file)
@@ -337,6 +486,10 @@ fpkg()
            s)
                SRC_DIR=${OPTARG}
                 ;;
+            v)
+                VOPTION="y"
+                VARG=${OPTARG}
+                ;;
             w)
                 ERASE_FIRST="y"
                ;;
@@ -364,6 +517,29 @@ fpkg()
         local URL=${2}
     fi
 
+    if [ -n "${VOPTION}" ]; then
+        # Append version number to SRC_DIR (if specified)
+        case ${VARG} in
+            0)
+                # Full version number
+                SRC_DIR+="$(get_pkg_ver ${PACK})"
+                ;;
+           1)
+                SRC_DIR+="$(get_pkg_ver1 ${PACK})"
+                ;;
+            2)
+                SRC_DIR+="$(get_pkg_ver2 ${PACK})"
+                ;;
+            3)
+                SRC_DIR+="$(get_pkg_ver3 ${PACK})"
+                ;;
+            *)
+                echo "${FUNCNAME}(), invalid -v argument: ${VARG}"
+               return 1
+                ;;
+        esac
+    fi
+
     if [ -n "${MODE}" ]; then
         case ${MODE} in
            gnu)
@@ -374,7 +550,7 @@ fpkg()
                 fi
                 if [ -z "${FILE_EXT}" ]; then
                     # Default file extension is tar.gz
-                    FILE_EXT="tar.gz"
+                    FILE_EXT="tar.xz"
                 fi
                 ;;
             gnome)
@@ -383,7 +559,11 @@ fpkg()
                     # Default subdirectory on server
                    SRC_DIR=$(get_pkg_name ${PACK})
                 fi
-                SRC_DIR="${SRC_DIR}/$(get_pkg_ver_base ${PACK})"
+                SRC_DIR="${SRC_DIR}/$(get_pkg_ver2 ${PACK})"
+                                if [ -z "${FILE_EXT}" ]; then
+                    # Default file extension is xz
+                    FILE_EXT="tar.xz"
+                fi
                 ;;
             sf)
                 URL=${SOURCEFORGE_URL}
@@ -403,10 +583,6 @@ fpkg()
                    echo "${FUNCNAME}(), mode 'xorg' needs '-s' option"
                    return 1
                 fi
-                if [ -z "${DEST_DIR}" ]; then
-                    # Default fetch (write to) directory
-                    DEST_DIR=${LFS_PKG_DIR}/${SRC_DIR}
-                fi
                 ;;
            fd)
                 # Most common layout:
@@ -515,10 +691,15 @@ fpkg()
             rm ${DEST_FILE}
         fi
 
-        if [ !  -f ${DEST_FILE} ]; then
+        if [ ! -f ${DEST_FILE} ]; then
             # Fetch package
             set +e
             static_getpkg ${SRC_FILENAME} ${URL} ${FILE_EXT}
+            rc=$?
+
+            if [ ${rc} -ne 0 ]; then
+                return ${rc};
+            fi
             set -e
 
             # Move file if source filename is not equal to package name and/or
@@ -549,7 +730,7 @@ fpkg()
 
         # Rename any patch fetched (in fpkg call) and replace SOURCE by TARGET
         # in patch name.
-        local PATCHES_LIST="${LFS_PKG_DIR}/${SRC_FILENAME}-*.patch"
+        local PATCHES_LIST="${LFS_PATCHES_DIR}/${SRC_FILENAME}-*.patch"
         if ls ${PATCHES_LIST} 1> /dev/null 2>&1; then
             echo "CMD=${SRC_FILENAME} ${PACK} ${PATCHES_LIST}"
            rename ${SRC_FILENAME} ${PACK} ${PATCHES_LIST}