mirror of
https://github.com/RasppleII/a2cloud.git
synced 2024-12-21 22:29:24 +00:00
a3d67123cc
Replaced downloading scripts and files from a2cScriptURL with installation from the source tree. This obsoletes a2cScriptURL, so it's been removed. It made sense to remove the .txt from the script names since I was rewriting the lines that use them anyway.
415 lines
18 KiB
Bash
Executable File
415 lines
18 KiB
Bash
Executable File
#! /bin/bash
|
|
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
|
|
|
# set default AppleCommander location if ADTPro is not installed
|
|
defaultAcPath=$(echo -n /usr/local/bin/AppleCommander-*-ac.jar)
|
|
|
|
echoerr() {
|
|
echo "$@" 1>&2;
|
|
}
|
|
|
|
helpExit () {
|
|
if [[ -s $acmdStdErr ]]; then
|
|
if [[ $(grep CommandLineHelp $acmdStdErr) ]]; then
|
|
grep -v ^-[pge][[:space:]] $acmdStdErr | grep -v '^ or' | grep -v 0x2000 1>&2
|
|
echoerr "-g <imagename> <filename> [<outputFilename>] copy filename out of any"
|
|
echoerr " disk image. Using - for outputFilename will copy to stdout."
|
|
echoerr "-e <imagename> <filename> [<outputFilename>] like -g, with conversion"
|
|
echoerr " to modern file format if possible."
|
|
echoerr "-p <imagename> <filename> [[$|0x]<type>] [[$|0x]<auxtype>] copy filename"
|
|
echoerr " into ProDOS disk image. <type> is either three-letter or numeric"
|
|
echoerr " ProDOS file type (BIN if omitted). Will read from stdin if supplied."
|
|
echoerr " ProDOS subdirectories in <filename> will be created if needed."
|
|
echoerr " If an AppleDouble file or Nulib2 extended filename is detected,"
|
|
echoerr " <type> and <auxtype> are automatically set, and resource forks are kept."
|
|
if hash cppo &> /dev/null; then
|
|
echoerr " (To extract these from a ProDOS image file, use cppo -ad or cppo -e.)"
|
|
fi
|
|
echoerr "-c <filename> <imagename> [[$|0x]<type>] [[$|0x]<auxtype>] synonym for -p"
|
|
echoerr " with filename and imagename reversed."
|
|
else
|
|
cat $acmdStdErr
|
|
fi
|
|
if [[ $arg1 == "-h" ]]; then
|
|
exitVal=0
|
|
else
|
|
exitVal=1
|
|
fi
|
|
else
|
|
if [[ $vsd1_md5 && ( "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ) ]]; then
|
|
if [[ "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ]]; then
|
|
echoerr "One of the virtual drive image files has changed while ADTPro server is active."
|
|
echoerr " If using VSDRIVE, type 'vsdsync' now to see changes and prevent corruption."
|
|
fi
|
|
fi
|
|
exitval=0
|
|
fi
|
|
rm $acmdStdErr &> /dev/null
|
|
exit $exitVal
|
|
}
|
|
|
|
decToBin () {
|
|
dec="$(( 10#$1 ))"
|
|
bits=""
|
|
for i in 7 6 5 4 3 2 1 0; do
|
|
bits+=$(( (dec & (2**i)) >> i ))
|
|
done
|
|
echo -n "$(( 10#$bits ))"
|
|
}
|
|
|
|
arg1=$1
|
|
|
|
acmdStdErr="/tmp/acmd_$RANDOM$RANDOM"
|
|
|
|
[[ -f /usr/libexec/java_home ]] && osx=1 || osx=
|
|
|
|
if [[ $osx ]]; then
|
|
if ! /usr/libexec/java_home &> /dev/null; then
|
|
echo -n "AppleCommander requires the Java JDK. Do you want to install it now? "
|
|
read
|
|
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
|
# install Oracle Java for OS X
|
|
echo "Downloading Java JDK..."
|
|
mkdir -p /tmp/jdk
|
|
curl -L --cookie oraclelicense=accept-securebackup-cookie $(curl -L "http://www.oracle.com/"$(curl -L "http://www.oracle.com/technetwork/java/javase/downloads/" 2> /dev/null | grep -o -m 1 '/technetwork/java/javase/downloads/jdk.-downloads-[0-9]*\.html') 2> /dev/null | grep -o 'http://.*macosx-x64.dmg' | sort | tail -1) 2> /dev/null > /tmp/jdk/jdk.dmg
|
|
echo "Installing Java JDK..."
|
|
hdiutil attach /tmp/jdk/jdk.dmg &> /dev/null
|
|
sudo installer -pkg /Volumes/JDK*/JDK*.pkg -target /
|
|
diskutil unmountDisk /Volumes/JDK*
|
|
rm -r /tmp/jdk 2> /dev/null
|
|
if ! /usr/libexec/java_home &> /dev/null; then
|
|
echo "The Java JDK could not be installed."
|
|
echo "Type \"java\" and then click \"More Info...\" to download and install it manually."
|
|
exit 1
|
|
fi
|
|
else
|
|
exit 1
|
|
fi
|
|
fi
|
|
else # not OS X, so presumably Linux
|
|
if ! hash java &> /dev/null; then
|
|
echo -n "AppleCommander requires the Java JDK. "
|
|
if hash apt-get; then
|
|
echo -n "Do you want to install it now? "
|
|
read
|
|
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
|
# from http://www.webupd8.org/2012/06/how-to-install-oracle-java-7-in-debian.html
|
|
if { ! grep -q webupd8team /etc/apt/sources.list; }; then
|
|
{
|
|
echo;
|
|
echo "# Oracle Java JDK";
|
|
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu precise main";
|
|
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu precise main";
|
|
} | sudo tee -a /etc/apt/sources.list > /dev/null
|
|
fi
|
|
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
|
|
sudo apt-get -y update
|
|
echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections
|
|
sudo apt-get -y install oracle-java8-installer
|
|
sudo apt-get -y clean
|
|
else
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
if ! hash java &> /dev/null; then
|
|
echo
|
|
echo "Get it from http://www.oracle.com/technetwork/java/javase/downloads/"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
setAcPath () {
|
|
acPath=$defaultAcPath
|
|
adtPath=
|
|
if [[ ! -f $acPath ]]; then
|
|
if [[ -f /usr/local/adtpro/adtpro.sh ]]; then
|
|
adtPath="/usr/local/adtpro"
|
|
elif [[ $osx ]]; then
|
|
adtPath=$(echo -n /Applications/ADTPro* | tr ' ' '\n' | sort | head -1);
|
|
fi
|
|
if [[ -d "$adtPath" ]]; then
|
|
acPath="$adtPath"/lib/AppleCommander/AppleCommander-ac.jar
|
|
[[ ! -f $acPath ]] && acPath=$(echo -n "$adtPath"/lib/AppleCommander/AppleCommander-*-ac.jar)
|
|
fi
|
|
fi
|
|
acPath=$(echo -n $acPath)
|
|
}
|
|
|
|
setAcPath
|
|
if [[ ! -f $acPath ]]; then
|
|
echo "Installing AppleCommander..."
|
|
sudo mkdir -p /usr/local/bin
|
|
acUrl="http://sourceforge.net/projects/applecommander/files/AppleCommander%20-%20Interim/testcase/AppleCommander-1.3.5.13id-ac.jar/download"
|
|
if [[ $osx ]]; then
|
|
curl -L "$acUrl" 2> /dev/null | sudo tee /usr/local/bin/AppleCommander-1.3.5.13id-ac.jar > /dev/null
|
|
else
|
|
sudo wget -qO /usr/local/bin/AppleCommander-1.3.5.13id-ac.jar "$acUrl"
|
|
fi
|
|
setAcPath
|
|
if [[ ! -f "$acPath" ]]; then
|
|
echo "AppleCommander couldn't be installed. Download it from"
|
|
echo "http://applecommander.sourceforge.net and put it in /usr/local/bin."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
ac="java -Xmx128m -jar $acPath"
|
|
|
|
if [[ ! $2 || $arg1 == "-h" ]]; then
|
|
java -jar "$acPath" 2> $acmdStdErr
|
|
[[ $? -eq 127 ]] && exit 127 || helpExit $arg1
|
|
fi
|
|
|
|
if [[ $arg1 != "-i" && $arg1 != "-ls" && $arg1 != "-l" && $arg1 != "-ll" && $arg1 != "-x" && $arg1 != "-g" && $arg1 != "-e" && $(ps aux | grep [A]DTPro) ]]; then
|
|
vsd1_md5="$(md5sum /usr/local/adtpro/disks/Virtual.po)"
|
|
vsd2_md5="$(md5sum /usr/local/adtpro/disks/Virtual2.po)"
|
|
fi
|
|
|
|
if [[ ( $arg1 == "-p" || $arg1 == "-c" || $arg1 == "-g" || $arg1 == "-e" ) && $2 && $3 ]]; then
|
|
|
|
AD=
|
|
EX=
|
|
prodosArg=
|
|
prodosArgParent=
|
|
rFile=
|
|
getArg=
|
|
if [[ $arg1 == "-c" || $arg1 == "-p" ]]; then
|
|
if [[ $arg1 == "-c" ]]; then
|
|
prodosArg="$2"
|
|
imageArg="$3"
|
|
elif [[ $arg1 == "-p" ]]; then
|
|
prodosArg="$3"
|
|
imageArg="$2"
|
|
fi
|
|
[[ $prodosArg == *"/"* ]] && prodosArgParent="${prodosArg%/*}/"
|
|
rFile="${prodosArgParent}.AppleDouble/${prodosArg##*/}"
|
|
if [[ -f "$prodosArg" && -f "$rFile" ]]; then # AppleDouble
|
|
AD=1
|
|
elif [ -f "${prodosArg%#*}"#?????? ]; then # Nulib2 ext filename
|
|
EX=1
|
|
prodosArg=$(echo -n "${prodosArg%#*}"#??????)
|
|
rFile="${prodosArg}"r
|
|
fi
|
|
if [[ $AD || $EX ]]; then
|
|
# if target is not a ProDOS disk, ignore metadata
|
|
if ! $ac -i "$imageArg" | grep -q '^Disk Format: ProDOS'; then
|
|
AD=
|
|
EX=
|
|
fi
|
|
fi
|
|
elif [[ $arg1 == "-g" || $arg1 == "-e" ]]; then
|
|
fileArg="$3"
|
|
imageArg="$2"
|
|
getArg="$arg1"
|
|
else
|
|
exit 2;
|
|
fi
|
|
|
|
shift
|
|
|
|
if [[ $getArg ]]; then # get file
|
|
|
|
outFile=
|
|
[[ $3 && $3 != "-" ]] && outFile="$3"
|
|
[[ ! $3 ]] && outFile="${2##*/}"
|
|
$ac $getArg "$imageArg" "$fileArg" $outFile 2> $acmdStdErr
|
|
|
|
else # put file
|
|
|
|
# test ProDOS name validity
|
|
prodosPath=$(tr [:lower:] [:upper:] <<< "${prodosArg%#*}" )
|
|
IFS_orig="$IFS"; IFS="/";
|
|
prodosPathParts="$prodosPath"
|
|
for thisProdosPathPart in $prodosPathParts; do
|
|
if [[ ${#thisProdosPathPart} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $thisProdosPathPart) ]]; then
|
|
echoerr "Invalid ProDOS name: $prodosPath"; exit 1;
|
|
fi
|
|
done
|
|
IFS="$IFS_orig"
|
|
|
|
# filetype to name table
|
|
P_00=UNK; P_01=BAD; P_02=PCD; P_03=PTX; P_04=TXT; P_05=PDA; P_06=BIN; P_07=FNT; P_08=FOT; P_09=BA3; P_0a=DA3; P_0b=WPF; P_0c=SOS; P_0f=DIR; P_10=RPD; P_11=RPI; P_12=AFD; P_13=AFM; P_14=AFR; P_15=SCL; P_16=PFS; P_19=ADB; P_1a=AWP; P_1b=ASP; P_20=TDM; P_21=IPS; P_22=UPV; P_29=3SD; P_2a=8SC; P_2b=8OB; P_2c=8IC; P_2d=8LD; P_2e=P8C; P_41=OCR; P_42=FTD; P_50=GWP; P_51=GSS; P_52=GDB; P_53=DRW; P_54=GDP; P_55=HMD; P_56=EDU; P_57=STN; P_58=HLP; P_59=COM; P_5a=CFG; P_5b=ANM; P_5c=MUM; P_5d=ENT; P_5e=DVU; P_60=PRE; P_6b=BIO; P_6d=DVR; P_6e=PRE; P_6f=HDV; P_80=GEZ; P_81=GE1; P_82=GEO; P_83=GE3; P_84=GE4; P_85=GE5; P_86=GE6; P_87=GE7; P_88=GE8; P_89=GE9; P_8a=GEA; P_8b=GEB; P_8c=GEC; P_8d=GED; P_8e=GEE; P_8f=GEF; P_a0=WP_; P_ab=GSB; P_ac=TDF; P_ad=BDF; P_b0=SRC; P_b1=OBJ; P_b2=LIB; P_b3=S16; P_b4=RTL; P_b5=EXE; P_b6=STR; P_b7=TSF; P_b8=NDA; P_b9=CDA; P_ba=TOL; P_bb=DRV; P_bc=LDF; P_bd=FST; P_bf=DOC; P_c0=PNT; P_c1=PIC; P_c2=ANI; P_c3=PAL; P_c5=OOG; P_c6=SCR; P_c7=CDV; P_c8=FON; P_c9=FND; P_ca=ICN; P_d5=MUS; P_d6=INS; P_d7=MDI; P_d8=SND; P_db=DBM; P_e0=SHK; P_e2=DTS; P_ee=R16; P_ef=PAS; P_f0=CMD; P_f9=P16; P_fa=INT; P_fb=IVR; P_fc=BAS; P_fd=VAR; P_fe=REL; P_ff=SYS;
|
|
|
|
# process filetype
|
|
if [[ ! $AD && ! $EX ]]; then # no resource fork or metadata
|
|
[[ ${3:0:2} == "0x" ]] && ftArg="\$${3:2}" || ftArg="$3"
|
|
auxType="$4"
|
|
|
|
# assume BIN/$2000 if filetype omitted
|
|
if [[ ! $ftArg ]]; then
|
|
ft="BIN"
|
|
auxType="\$2000"
|
|
# accept hex or decimal number for file type
|
|
elif [[ ( ${ftArg:0:1} == '$' && ${#ftArg} -eq 3 ) || $(grep [0-9] <<< ${ftArg:0:1}) ]]; then
|
|
if [[ ${ftArg:0:1} == '$' ]]; then
|
|
fc=$(tr [:upper:] [:lower:] <<< ${ftArg:1:2})
|
|
else
|
|
fc=$(printf %02X "$ftArg" | tr [:upper:] [:lower:])
|
|
fi
|
|
ftVar="P_$fc";
|
|
[[ ${!ftVar} ]] && ft=${!ftVar} || ft="\$$fc";
|
|
else
|
|
ft="$ftArg"
|
|
fi
|
|
|
|
# set auxtype to $0801 for Applesoft programs if not specified
|
|
[[ $ft == "BAS" && ! $auxType ]] && auxType="\$0801"
|
|
|
|
# test for absence of stdin [[ -t 0 ]] and if absent use ProDOS name
|
|
if [[ -t 0 ]]; then
|
|
[[ ! -f $prodosArg ]] && { echoerr "$prodosArg not found."; exit 1; }
|
|
$ac -d "$imageArg" $prodosPath &> /dev/null
|
|
$ac -p "$imageArg" $prodosPath $ft $auxType < $prodosArg 2> $acmdStdErr
|
|
else
|
|
$ac -d "$imageArg" $prodosPath &> /dev/null
|
|
$ac -p "$imageArg" $prodosPath $ft $auxType 2> $acmdStdErr
|
|
fi
|
|
else # AppleDouble or nulib extended, get resource fork and file metadata from header file
|
|
|
|
[[ ! -f $prodosArg ]] && { echoerr "$prodosArg not found."; exit 1; }
|
|
[[ $AD && ! -f $rFile ]] && { echoerr "Not an AppleDouble file: $rFile"; exit 1; }
|
|
|
|
if [[ $AD ]]; then
|
|
# get metadata from AppleDouble header
|
|
[[ $(dd if="$rFile" bs=1 count=1 skip=741 2> /dev/null | wc -c) -gt 0 ]] && isExtFile=1 || isExtFile=
|
|
fileData=$(dd if="$rFile" bs=1 count=24 skip=637 2> /dev/null | xxd -p | tr -d '\n')
|
|
ftVar="P_${fileData:34:2}";
|
|
auxType="\$"${fileData:36:4}
|
|
cDateTime=$(printf %d 0x${fileData:0:8})
|
|
mDateTime=$(printf %d 0x${fileData:8:8})
|
|
[[ $(printf %d 0x"${fileData:0:2}") -gt 127 ]] && (( cDateTime-=4294967296 )) # handle negative hex number
|
|
[[ $(printf %d 0x"${fileData:8:2}") -gt 127 ]] && (( mDateTime-=4294967296 )) # handle negative hex number
|
|
(( cDateTime+=946684800 )) # convert AD timestamp to Unix timestamp
|
|
(( mDateTime+=946684800 )) # convert AD timestamp to Unix timestamp
|
|
else # EX
|
|
# get metadata from file info
|
|
[[ -f "$rFile" ]] && isExtFile=1 || isExtFile=
|
|
ftVar="P_${prodosArg: -6:2}"
|
|
auxType="\$"${prodosArg: -4}
|
|
if [[ $osx ]]; then
|
|
mDateTime=$(stat -f "%m" "$prodosArg")
|
|
else
|
|
mDateTime=$(stat -c %Y "$prodosArg")
|
|
fi
|
|
cDateTime=$mDateTime
|
|
fi
|
|
[[ ${!ftVar} ]] && ft=${!ftVar} || ft="\$$fc"; # set file type
|
|
# convert unix timestamp to ProDOS bitfield yyyyyyymmmmddddd 000hhhhh00mmmmmm
|
|
cDateFields=($(date -d @$cDateTime +"%y %m %d %H %M" 2> /dev/null))
|
|
[[ ! $cDateFields ]] && cDateFields=($(date -r $cDateTime +"%y %m %d %H %M")) # OS X/BSD
|
|
mDateFields=($(date -d @$mDateTime +"%y %m %d %H %M" 2> /dev/null))
|
|
[[ ! $mDateFields ]] && mDateFields=($(date -r $mDateTime +"%y %m %d %H %M")) # OS X/BSD
|
|
cDateTimeHex=$(printf %08X $(( 2#$(printf %07d $(decToBin ${cDateFields[0]}))$(printf %04d $(decToBin ${cDateFields[1]}))$(printf %05d $(decToBin ${cDateFields[2]}))$(printf %08d $(decToBin ${cDateFields[3]}))$(printf %08d $(decToBin ${cDateFields[4]})) )))
|
|
cDateTimeHex=${cDateTimeHex:2:2}${cDateTimeHex:0:2}${cDateTimeHex:6:2}${cDateTimeHex:4:2}
|
|
mDateTimeHex=$(printf %08X $(( 2#$(printf %07d $(decToBin ${mDateFields[0]}))$(printf %04d $(decToBin ${mDateFields[1]}))$(printf %05d $(decToBin ${mDateFields[2]}))$(printf %08d $(decToBin ${mDateFields[3]}))$(printf %08d $(decToBin ${mDateFields[4]})) )))
|
|
mDateTimeHex=${mDateTimeHex:2:2}${mDateTimeHex:0:2}${mDateTimeHex:6:2}${mDateTimeHex:4:2}
|
|
|
|
# create forks and file entry
|
|
### RIGHT HERE PROBLEMS IF #000000 specified and maybe if not
|
|
fileName="${prodosPath##*/}"
|
|
if [[ $isExtFile ]]; then
|
|
dfName=X$(printf %04X $RANDOM $RANDOM $RANDOM)
|
|
while [[ ! $rfName || $rfName == $dfName ]]; do
|
|
rfName=X$(printf %04X $RANDOM $RANDOM $RANDOM)
|
|
done
|
|
while [[ $fileName == "${prodosPath##*/}" || $rfName == $fileName || $dfName == $fileName ]]; do
|
|
fileName=X$(printf %04X $RANDOM $RANDOM $RANDOM)
|
|
done
|
|
$ac -d "$imageArg" "${prodosArgParent}$dfName" 2> /dev/null
|
|
dd if="$prodosArg" 2> /dev/null | $ac -p "$imageArg" "${prodosArgParent}$dfName" $00 2> $acmdStdErr
|
|
$ac -d "$imageArg" "${prodosArgParent}$rfName" 2> /dev/null
|
|
dd if="$rFile" bs=1 skip=$(( 0$AD ? 741 : 0 )) 2> /dev/null | $ac -p "$imageArg" "${prodosArgParent}$rfName" $00 2> $acmdStdErr
|
|
fi
|
|
|
|
# create file entry, then find it
|
|
$ac -d "$imageArg" "${prodosArgParent}$fileName" 2> /dev/null
|
|
[[ $isExtFile ]] && ddsrc="if=/dev/zero bs=512 count=1" || ddsrc="if=$prodosArg"
|
|
dd $ddsrc 2> /dev/null | $ac -p "$imageArg" "${prodosArgParent}$fileName" "$ft" "$auxType" 2> $acmdStdErr
|
|
# thx to http://unix.stackexchange.com/a/122945/99697 for perl alternative to broken --byte-offset in grep 2.5.1 (e.g. in OS X)
|
|
fileEntryOffset=$(perl -n0777e "print pos()-length('.$fileName') while /.$fileName/g" < "$imageArg")
|
|
fileEntry=$(dd if="$imageArg" bs=1 count=39 skip=$fileEntryOffset 2> /dev/null | xxd -p | tr -d '\n')
|
|
|
|
if [[ $isExtFile ]]; then
|
|
extKeyBlockOffset=$(( ( ( $(printf %d 0x"${fileEntry:36:2}") * 256 ) + $(printf %d 0x"${fileEntry:34:2}") * 512 ) ))
|
|
|
|
# find data fork, copy storage type, key block, block size, length to extended key block mini-entry
|
|
# then mark as available/deleted
|
|
dfOffset=$(perl -n0777e "print pos()-length('.$dfName') while /.$dfName/g" < "$imageArg")
|
|
dfEntry=$(dd if="$imageArg" bs=1 count=39 skip=$dfOffset 2> /dev/null | xxd -p | tr -d '\n')
|
|
dfStorageType=$(printf %02X $(( $(printf %d 0x${dfEntry:0:2}) >> 4 )) )
|
|
dfBlocksUsed=$(( ( $(printf %d 0x${dfEntry:40:2}) * 256 ) + $(printf %d 0x${dfEntry:38:2}) ))
|
|
dfInfo=${dfEntry:34:14}
|
|
echo -n -e \\x"$dfStorageType"$(sed 's/../\\x&/g' <<< $dfInfo) \
|
|
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( extKeyBlockOffset+0 )) 2> /dev/null
|
|
# mark as deleted
|
|
echo -n -e \\x0${dfEntry:1:1} \
|
|
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( dfOffset+0 )) 2> /dev/null
|
|
|
|
# find resource fork, copy storage type, key block, block size, length to extended key block mini-entry
|
|
# then mark as available/deleted
|
|
rfOffset=$(perl -n0777e "print pos()-length('.$rfName') while /.$rfName/g" < "$imageArg")
|
|
rfEntry=$(dd if="$imageArg" bs=1 count=39 skip=$rfOffset 2> /dev/null | xxd -p | tr -d '\n')
|
|
rfStorageType=$(printf %02X $(( $(printf %d 0x${rfEntry:0:2}) >> 4 )) )
|
|
rfBlocksUsed=$(( ( $(printf %d 0x${rfEntry:40:2}) * 256 ) + $(printf %d 0x${rfEntry:38:2}) ))
|
|
rfInfo=${rfEntry:34:14}
|
|
echo -n -e \\x"$rfStorageType"$(sed 's/../\\x&/g' <<< $rfInfo) \
|
|
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( extKeyBlockOffset+256 )) 2> /dev/null
|
|
# mark as deleted
|
|
echo -n -e \\x0${rfEntry:1:1} \
|
|
| dd of="$imageArg" conv=notrunc bs=1 seek=$(( rfOffset+0 )) 2> /dev/null
|
|
|
|
# reduce active file count in directory by two
|
|
parentDirKeyBlockOffset=$(( ( ( $(printf %d 0x"${fileEntry:76:2}") * 256 ) + $(printf %d 0x"${fileEntry:74:2}") * 512 ) ))
|
|
fileCountHex=$(dd if="$imageArg" bs=1 count=2 skip=$((parentDirKeyBlockOffset+4+33)) 2> /dev/null | xxd -p)
|
|
fileCount=$(( ( $(printf %d 0x${fileCountHex:2:2}) * 256 ) + $(printf %d 0x${fileCountHex:0:2}) ))
|
|
fileCountHex=$(printf %04X $((fileCount - 2)))
|
|
echo -n -e \\x${fileCountHex:2:2}\\x${fileCountHex:0:2} \
|
|
| dd of="$imageArg" conv=notrunc bs=1 seek=$((parentDirKeyBlockOffset+4+33)) 2> /dev/null
|
|
|
|
# update extended file metadata
|
|
|
|
# storage type (5), name length, name
|
|
name="${prodosPath##*/}"
|
|
nameLen=${#name}
|
|
nameHeader=$(printf %02X $((nameLen + 80)) )
|
|
nameField=$(echo -n $name | xxd -p | tr -d '\n' | sed -e :a -e 's/^.\{1,29\}$/&00/;ta')
|
|
|
|
# blocks used
|
|
blocksUsed=$(( dfBlocksUsed + rfBlocksUsed + 1 ))
|
|
|
|
# store updated metadata
|
|
fileEntry=${nameHeader}${nameField}${fileEntry:32}
|
|
fi
|
|
|
|
# put creation and modified date in file entry
|
|
fileEntry=${fileEntry:0:48}${cDateTimeHex}${fileEntry:56:10}${mDateTimeHex}${fileEntry:74:4}
|
|
|
|
# put casemask for mixed case filename in file entry
|
|
[[ $EX ]] && prodosArg="${prodosArg%#*}"
|
|
if [[ "${prodosPath##*/}" != "${prodosArg##*/}" ]]; then # mixed case
|
|
caseMaskDec=32768
|
|
mixedName="${prodosArg##*/}"
|
|
[[ $EX ]] && mixedName="${mixedName%#*}"
|
|
for (( i=0; i<${#mixedName}; i++ )); do
|
|
[[ "${mixedName:$i:1}" == $(tr [:lower:] [:upper:] <<< "${mixedName:$i:1}") ]] # $? == 0 means uppercase
|
|
(( caseMaskDec+=$(( $? * (2**(14-i)) )) ))
|
|
done
|
|
caseMaskHex=$(printf %04X $caseMaskDec)
|
|
fileEntry=${fileEntry:0:56}${caseMaskHex:2:2}${caseMaskHex:0:2}${fileEntry:60}
|
|
fi
|
|
|
|
# write updated metadata to file entry
|
|
echo -n -e $(sed 's/../\\x&/g' <<< $fileEntry) | dd of="$imageArg" bs=1 conv=notrunc seek=$fileEntryOffset 2> /dev/null
|
|
fi
|
|
fi
|
|
|
|
else
|
|
|
|
imageArg="$2"
|
|
$ac "$@" 2> $acmdStdErr
|
|
|
|
fi
|
|
|
|
helpExit
|