#! /bin/sh # Midnight Commander - ISO9660 VFS for MC # based on lslR by Tomas Novak <tnovak@ipex.cz> April 2000 # # Copyright (C) 2000, 2003 # The Free Software Foundation, Inc. # # Written by: # Michael Shigorin <mike@altlinux.org>, # Grigory Milev <week@altlinux.org>, # Kachalov Anton <mouse@linux.ru.net>, 2003 # Victor Ananjevsky <ananasik@gmail.com>, 2013 # slava zanko <slavazanko@gmail.com>, 2013 # slowpeek <slowpeek@users.noreply.github.com>, 2024 # # This file is part of the Midnight Commander. # # The Midnight Commander 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 3 of the License, # or (at your option) any later version. # # The Midnight Commander 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, see <http://www.gnu.org/licenses/>. #*** include section (source functions, for example) ******************* #*** file scope functions ********************************************** XORRISO=$(command -v xorriso 2>/dev/null) # This snippet is used to undo xorriso's Text_shellsafe(). Pseudocode for the # function: # # Text_shellsafe( s) { # return q(') replace(q('), q('"'"'), s) q(') # } # # Xorriso_ls() uses two formats for pathes: # - generic: Text_shellsafe(path) # - symlink: Text_shellsafe(link) q( -> ) Text_shellsafe(target) # # References in xorriso sources: # - iso_tree.c:Xorriso_ls() # - text_io.c:Xorriso_esc_filepath() # - misc_funct.c:Text_shellsafe() awk_xorriso_unesc=$(cat <<'EOF' { # Start of the path part i = index($0, "'") s = substr($0, i) # The path part with the wrapping quotes removed s = substr(s, 2, length(s)-2) if (substr($0, 1, 1) == "l") { s1=s if (gsub("->", "", s1) > 1) { # Ambiguity: either the link or its target contains q(->) in # addition to the link/target delimiter next } j = index(s, "' -> '") # link -> target with the wrapping quotes removed from both s = substr(s, 1, j-1) " -> " substr(s, j+6) } else if (index(s, "->")) { # Ambiguity: not a symlink, but there is q(->) next } gsub("'\"'\"'", "'", s) print substr($0, 1, i-1) s } EOF ) xorriso_list() ( if test -z "$XORRISO"; then return 1 fi temp_ls=$(mktemp "${MC_TMPDIR:-/tmp}"/mc-iso9660.XXXXXX) || return 1 # $XORRISO must be unquoted here to hook into the testing framework $XORRISO -abort_on FATAL -dev stdio:"$1" -find / -exec lsdl 2>/dev/null >"$temp_ls" r=$? if [ "$r" != 0 ]; then rm -f "$temp_ls" return "$r" fi # The first line is /, skip it sed 1,1d "$temp_ls" | # disk_ops.c:Xorriso_format_ls_l() prints the boot catalog file as of # type "e". Make it a generic file sed 's,^e,-,' | @AWK@ "$awk_xorriso_unesc" rm -f "$temp_ls" ) xorriso_copyout() { if test -z "$XORRISO"; then return 1 fi $XORRISO -dev stdio:"$1" -osirrox on -extract "$2" "$3" >/dev/null 2>&1 } xorriso_copyin() { if test -z "$XORRISO"; then return 1 fi $XORRISO -dev stdio:"$1" -cpr "$3" "$2" >/dev/null 2>&1 } xorriso_mkdir() { if test -z "$XORRISO"; then return 1 fi $XORRISO -dev stdio:"$1" -mkdir "$2" >/dev/null 2>&1 } xorriso_rmdir() { if test -z "$XORRISO"; then return 1 fi $XORRISO -dev stdio:"$1" -rmdir "$2" >/dev/null 2>&1 } xorriso_rm() { if test -z "$XORRISO"; then return 1 fi $XORRISO -dev stdio:"$1" -rm "$2" >/dev/null 2>&1 } # tested to comply with isoinfo 2.0's output test_iso () { ISOINFO=$(command -v isoinfo 2>/dev/null) if test -z "$ISOINFO"; then echo "isoinfo not found" >&2 return 1 fi CHARSET=$(locale charmap 2>/dev/null) if test -z "$CHARSET"; then CHARSET=$(locale 2>/dev/null | grep LC_CTYPE | sed -n -e 's/.*\.\(.*\)"$/\1/p') fi if test -n "$CHARSET"; then CHARSET=$(echo "$CHARSET" | tr '[A-Z]' '[a-z]' | sed -e 's/^iso-/iso/') $ISOINFO -j $CHARSET -i /dev/null 2>&1 | grep "Iconv not yet supported\|Unknown charset" >/dev/null && CHARSET= fi if test -n "$CHARSET"; then JOLIET_OPT="-j $CHARSET -J" else JOLIET_OPT="-J" fi ISOINFO_D_I="$($ISOINFO -d -i "$1" 2>/dev/null)" ISOINFO="$ISOINFO -R" echo "$ISOINFO_D_I" | grep "UCS level 1\|NO Joliet" > /dev/null || ISOINFO="$ISOINFO $JOLIET_OPT" if [ $(echo "$ISOINFO_D_I" | grep "Joliet with UCS level 3 found" | wc -l) = 1 \ -a $(echo "$ISOINFO_D_I" | grep "NO Rock Ridge" | wc -l) = 1 ] ; then SEMICOLON="YES" fi } mcisofs_list () ( # left as a reminder to implement compressed image support =) case "$1" in *.lz) MYCAT="lzip -dc";; *.lz4) MYCAT="lz4 -dc";; *.lzma) MYCAT="lzma -dc";; *.lzo) MYCAT="lzop -dc";; *.xz) MYCAT="xz -dc";; *.zst) MYCAT="zstd -dc";; *.bz2) MYCAT="bzip2 -dc";; *.gz) MYCAT="gzip -dc";; *.z) MYCAT="gzip -dc";; *.Z) MYCAT="gzip -dc";; *) MYCAT="cat";; esac lsl=$($ISOINFO -l -i "$1" 2>/dev/null) r=$? test $r -gt 0 && return $r echo "$lsl" | @AWK@ -v SEMICOLON=$SEMICOLON ' BEGIN { dir=""; # Pattern to match 8 first fields. rx = "[^ ]+[ ]+"; rx = "^" rx rx rx rx rx rx rx rx; irx = "^\\[ *-?[0-9]* *[0-9]+\\] +"; } /^$/ { next } /^d---------/ { next } /^Directory listing of [^ ].*$/ { dir=substr($0, 23); next; } { $11 != "" } { name=$0 sub(rx, "", name) attr=substr($0, 1, length($0)-length(name)) # strip inodes and extra dir entries; fix perms sub(irx, "", name) sub("^---------- 0 0 0", "-r--r--r-- 1 0 0 ", attr) sub(" $", "", name) # for Joliet UCS level 3 if (SEMICOLON == "YES") sub(";1$", "", name); ## sub(";[0-9]+$", "", name) ## would break copyout # skip . and .. if (name == ".") next; if (name == "..") next; printf "%s%s%s\n", attr, dir, name }' ) mcisofs_copyout () { if [ "x$SEMICOLON" = "xYES" ]; then $ISOINFO -i "$1" -x "/$2;1" 2>/dev/null > "$3" else $ISOINFO -i "$1" -x "/$2" 2>/dev/null > "$3" fi } #*** main code ********************************************************* LC_ALL=C cmd="$1" shift case "$cmd" in list) if [ -n "${MC_TEST_EXTFS_LIST_CMD:-}" ]; then case "${MC_TEST_EXTFS_ISO9660_TOOL}" in xorriso) XORRISO="$MC_TEST_EXTFS_LIST_CMD" xorriso_list "$@" || exit 1 ;; *) exit 1 ;; esac exit 0 fi xorriso_list "$@" || { test_iso "$@" || exit 1 mcisofs_list "$@" || exit 1 } exit 0 ;; rm) xorriso_rm "$@" || { exit 1 } exit 0 ;; rmdir) xorriso_rmdir "$@" || { exit 1 } exit 0 ;; mkdir) xorriso_mkdir "$@" || { exit 1 } exit 0 ;; copyin) xorriso_copyin "$@" || { exit 1 } exit 0 ;; copyout) xorriso_copyout "$@" || { test_iso "$@" || exit 1 mcisofs_copyout "$@" || exit 1 } exit 0 ;; esac exit 1