#!/bin/bash
v=190529 #sfs, RoDoN 
p="Сoздание 090-save.pfs v.$v" #sfslinux@gmail.com , Zay (29.12.11)
[ "`whoami`" != "root" ] && exec sudo -A ${0} ${@}
value() { egrep -o "(^| )$1=[^ ]+" /proc/cmdline | cut -d= -f2; } #sfs

[ "`value changes`" ] && ntf -a "Используется другой тип сохранения сессии" "changes=`value changes`
Если Вы хотите использовать сохранение.pfs:
  -перезагрузите систему без changes=
  -переконвертируйте свой файл (папку или раздел) в .pfs" && exit

rw="`realpath /mnt/live/memory/changes`" #porteus-initrd
[ ! -d $rw ] && rw="/initrd/pup_rw  /initrd/pup_ro1 /initrd/pup_usr" && pup=1 #|| PUPMODE=1 #puppy

case $1 in
    net) 
	[ ! "`find "$rw"/etc/netctl "$rw"/etc/systemd "$rw"/etc/rc.d/net* -type f`" ] && ntf -a "Сетевые настройки в '$rw' не обнаружены" && exit
	type="$1" ; msgnet="сетевых настроек" ;;
    --help|-h) 
	echo "$p
Usage: $0 [net]
    net  - только сетевые настройки" ;exit
    ;;
esac


if [ "$pup" ] ;then
. /etc/rc.d/PUPSTATE
. /etc/DISTRO_SPECS
fi

exitfunc(){
if [ -f "/tmp/umount_part" ];then
 cd ~
 for ONEUMNT in `cat /tmp/umount_part | tr '\n' ' '`
 do
  umount /dev/$ONEUMNT
 done
 rm -f /tmp/umount_part
fi
exit
}

    if [ "$pup" ] ;then
PDIR1="$(dirname `echo $PUPSFS | cut -f3 -d ','`)"
if [ "$PUPSAVE" = "" ];then
 if ! [ -f "/mnt/$PDEV1`echo $PUPSFS | cut -f3 -d ','`" ];then
  mkdir -p /mnt/$PDEV1
  mount -t $DEV1FS /dev/$PDEV1 /mnt/$PDEV1
  echo $PDEV1 >>/tmp/umount_part
 fi
 dirwork="/mnt/$PDEV1$PDIR1"
else
 dirwork="/mnt/home$PDIR1"
fi
    else
	dirwork="/mnt/home/`value dir`/base" #pra
    fi

[ -d "${dirwork}" ] || yaf-splash -timeout 6 -font "8x16" -outline 0 -margin 4 -bg green -text "Ошибка! Раздел с Puppy не найден! "

cd "$dirwork"

    if [ "$pup" ] ;then
if [ $PUPMODE -eq 5 ];then
 save=user
else
 save="save-`date +%y%m%d`$type"
fi
pfs="$dirwork/$save\_${DISTRO_VERSION}.sfs"
    else
	[ "$type" = "net" ] && netn=1 || netn=0
	save="09$netn-save-`date +%y%m%d`$type" ; pfs="$dirwork/$save-`uname -n`.pfs"
    fi
    
TST() {
bSFS="`basename $SFSNAME`"
if [ -n "`losetup | grep $bSFS`" ];then 
 m=" и в данный момент используется"
 b=Удалить; im=gtk-delete ;b1="Старый файл будет переименован в $SFSNAME.old и не будет автоподключаться.
Если создать новый файл - информации из старого файла в нем не будет."

else
 b=Заменить; b1="$SFSNAME не используется.
Можно пересоздать. Информация сессии не будет потеряна.
Старый файл будет переименован в $SFSNAME.old и не будет автоподключаться"; im=gtk-apply
fi

export Y_DIALOG='
<window title="'$p'"  window-position="1" icon-name="gtk-save">
 <vbox>
  <hbox>
  <pixmap><height>48</height><width>48</width><input file icon="gtk-dialog-warning"></input></pixmap>
  <text use-markup="true">
    <label>"Файл <b>'$SFSNAME'</b> существует'$m'."</label>
  </text>
  <pixmap><height>48</height><width>48</width><input file icon="application-pfs"></input></pixmap>
  </hbox>
  <hbox>
   <button cancel></button>
   <button tooltip-text="'$b1'">
    <input file icon="'$im'"></input>
    <label>'$b'</label>
   </button>
   <button tooltip-text="Все файлы /base/090-save* при автозагрузке наложатся друг на друга">
    <input file icon="gtk-refresh"></input>
    <label>Переименовать</label>
   </button>
  </hbox>
 </vbox>
</window>
'
ret="`gtkdialog --program=Y_DIALOG --center`"
#echo $ret ;exit
eval "$ret"

case "$EXIT" in
"Заменить" ) mv "$SFSNAME" "$SFSNAME.old";;
"Обновить" ) mv "$SFSNAME" "$SFSNAME.old";;
"Удалить" ) mv "$SFSNAME" "$SFSNAME.old";;
"Переименовать" ) CRT;;
*       ) exitfunc;;
esac
}
#SFS=/etc/fstab;TST;exit

#  <text use-markup="true" wrap="true" width-chars="10">
HLP() {
[ ! "$pup" ] && (defaultbrowser "http://wiki.puppyrus.org/puppyrus/pra#модуль_сохраненияpfs" &) && return
#ntf -w "Help" "Пока не написан" && return

export MAIN_DIALOG='
<window title="Справка '$p'"  window-position="1" icon-name="gtk-save">
 <vbox>
  <text use-markup="true">
    <label>"
Создание фиксированной сессии:

Меню > Система > Создать фиксированную сессию.


Возврат к сохранённой сессии:

Запустите систему с параметром <b>pfix=nosave</b>.
Меню > Система > Восстановить фиксированную сессию.


Постоянная загрузка фиксированной сессии:

Для автоматического подключения SFS-файла c сессией используйте параметр загрузки <b>usersfs</b> (файл с названием <b>user_'${DISTRO_VERSION}'.sfs</b> будет подключаться всегда, даже без параметра <b>usersfs</b>).

Чтобы отключить функцию создания сессии используйте параметр <b>pfix=nosave</b>."</label>
  </text>
  <hbox>
   <button ok></button>
  </hbox>
 </vbox>
</window>
'
ret="`gtkdialog --program=MAIN_DIALOG --center`"
}

DLG() {
export DIALOG='	
<window title="'$p'"  window-position="1" icon-name="gtk-save">
 <hbox>
 <vbox>

 <hbox space-expand="true">
 <pixmap>
        <height>48</height><width>48</width><input file icon="save48"></input>
 </pixmap>
   <text use-markup="true"><label>"<big><b>Создание модуля.pfs '$msgnet' сохраненной сессии</b></big>"</label></text>
 <pixmap>
        <height>48</height><width>48</width><input file icon="application-pfs"></input>
 </pixmap>
 </hbox>
   <frame ->
   <text use-markup="true"><label>"Вы можете сохранить состояние системы (все настройки, установленные пакеты и файлы) в модуль.pfs.
   
Модуль.pfs подключается в режиме <i>только чтение</i>. Вы получаете <i>неубиваемую</i> систему, которая может находиться на любом носителе (флэш, CD, HDD) и любой файловой системе (ext*, fat*, ntfs).

Можно сделать несколько модулей.pfs и подключать их отдельно или вместе, используя <i>/base</i> и параметры загрузки ядра <b>load= noload=</b>
Модули загружаются в алфавитном порядке (z.pfs перекрывает файлы a.pfs)
"</label></text>
   <hbox>
    <entry activates_default="true" accept="savefilename">
     <variable>SFSNAME</variable>
	 <input>echo '$pfs'</input>
    </entry>
    <button>
     <input file icon="gtk-open"></input>
     <action type="fileselect">SFSNAME</action>
    </button>
    </hbox>
   </frame>
    <hbox>
       <button help></button>
       <button cancel></button>
       <button can-default="true" has-default="true">
        <input file icon="gtk-apply"></input>
        <label>СОЗДАТЬ</label>
       </button>
    </hbox>
 </vbox>
 </hbox>
</window>'
}
DLG
CRT () {
ret="`gtkdialog --program=DIALOG`"
eval "$ret"
#echo $ret-$SFS

case "$EXIT" in
"СОЗДАТЬ" ) 
    [ -f "$SFSNAME" ] && TST
    ;;
"Help" ) 
    HLP;CRT;;
*       ) exitfunc;;
esac
}

CRT

os="false"

if [ ! "$pup" ] ;then
#old-save
so="`find /mnt/live/memory/images -maxdepth 1 -name "090-save*.[sp]fs" |sort -r`"
    if [ "$so" ] ;then
SO(){
for i in $so ;do
	wt -o "cp -aR "$i"/* /tmp/makesfs"
	#ntf -q "cp -aR "$i/"* /tmp/makesfs"
	mv "$dirwork/`basename $i`" "$dirwork/`basename $i`.old" 
	#rm -R  "$dirwork/`basename $i`"
done
}
filesize2=0
for i in $so ;do
    filesize2=`du -s "$i" |awk '{ s = s + $1} END {print int(s/32000)+1+'$filesize2'}'`
    sob="$sob 
`basename $i`"
done
os="true"
#	ntf -q "Найдены старые 090-save" "$sob
#
#<b>Объединить с новым и удалить старые?</b>" && SO
    fi
fi


if [ "$type" != "net" ];then
nsf="/home/`sfsusr`/.config/.nosave"
[ -f "$nsf" ] && nosave=true || nosave=false
o="$(ntf -k "\
true
Только настройки (/etc, /home/`sfsusr`, /root)
1
\
$os
Объединить с имеющимися 090-save*.pfs
4
\
t
Переносить содержимое корзины в 090-save*.pfs
2
\
gtk-no
Cлабое (gz) сжатие. 090-save*.pfs будет большего размера, но создастся быстрее
3
\
$nosave
Не напоминать при выключении ПК о 090-save*.pfs
5"  "Параметры создания сохранения.pfs" "\
</i><u>Только настройки: </u><i><small><b>'/etc'</b> , <b>'/home/`sfsusr`'</b> и <b>'/root'</b>
Уменьшит размер, но установленные программы (не путайте с подключенными модулями.pfs) не сохранятся. Их лучше сделать отдельными модулями.
При полном сохранении размер может получиться большим. Не рекомендуется при copy2ram (загрузке системы в память). В этом случае удобнее 'сохранение в папку'</small>")"
[ "$?" = "0" ] || exit
[ "`echo $o |grep 1`" ] && type=home || type=save
[ "`echo $o |grep 4`" ] || filesize2=0 #не объединяем
[ "`echo $o |grep 5`" ] && sudo -u "`sfsusr`" touch "$nsf" || rm "$nsf"
echo "ret=$ret"
#echo "o=$o" ;exit
#[ "$type" = "net" ] || type="$ret"
  else
  filesize2=0 #не объединяем
fi
[ "$os" = "true" ] || filesize2=0 #не объединяем

file2fs="`dirname $SFSNAME`/user`date +%y%m%d`.2fs"

##filesize=`du -s /initrd/pup_rw  /initrd/pup_ro1 /initrd/pup_usr |awk '{ s = s + $1} END {print int(s/32000)+1}'`
filesize=`du -s $rw |awk '{ s = s + $1} END {print int(s/32000)+1+'$filesize2'}'`
wt -start "Создание промежуточного файла $file2fs"
dd if=/dev/null of="$file2fs" bs=32M seek=$filesize
/sbin/mkfs.ext2 -F "$file2fs"
mkdir -p /tmp/makesfs

mount $file2fs /tmp/makesfs -o loop
status=$?
if [ $status -ne 0 ];then
 numloop=3
 while [ -b /dev/loop$numloop ]
 do
  numloop=`expr $numloop + 1`
 done
 mknod /dev/loop$numloop b 7 $numloop
 m1="`mount $file2fs /tmp/makesfs -o loop 2>&1`"
 status=$?
fi

if [ $status -ne 0 ];then
 m="Ошибка монтирования loop-устройства!"
 ntf -a "$m" "$m1" || gxmessage "$m" --borderless --center --wrap --bg red
 exitfunc
fi
wt -kill

if [ "$pup" ] ;then
cp -a /initrd/pup_usr/* /tmp/makesfs
for ONEDIR in `find /initrd/pup_ro1/ -maxdepth 1 -type d`
do
 [ "$ONEDIR" = "/initrd/pup_ro1/" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/dev" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/initrd" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/mnt" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/proc" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/sys" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/tmp" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/.wh..wh.orph" ] && continue
 [ "$ONEDIR" = "/initrd/pup_ro1/.wh..wh.plnk" ] && continue
 basename="`basename $ONEDIR`"
 cp -a -R $ONEDIR/ /tmp/makesfs
done
fi

#######copy
[ "$filesize2" = "0" ] || SO #объединяем сохраненки

rw1="$rw"
[ "$pup" ] && rw1=/initrd/pup_rw

TRASHX(){ 
#ntf -q "Переносить содержимое корзины" "в save.pfs?" || 
[ "`echo $o |grep -v 2`" ] && rm -R /tmp/makesfs/root/.local/share/Trash "/tmp/makesfs/home/`sfsusr`/.local/share/Trash" 
echo trashx
}

HOME(){
o1="/tmp/makesfs/$1"
mkdir -p "$o1" && stat --printf='chmod %a "/tmp/makesfs%n"; chown %U:%G "/tmp/makesfs%n"\n' "/$1" |ash
#echo "==cp "$rw1/$1"/.* "$o1""
cp -pd "$rw1/$1"/.* "$o1"
cp -pd "$rw1/$1"/* "$o1"

#for ONEDIR in $(find "$rw1/$1" -maxdepth 1 -type d) ; do
find "$rw1/$1" -maxdepth 1 -type d | while read ONEDIR  ; do
# echo "=====$ONEDIR="
 [ "$ONEDIR" = "$rw1/$1" ] && continue
 [ "$ONEDIR" = "$rw1/$1/.dbus" ] && continue
 [ "$ONEDIR" = "$rw1/$1/.opera" ] && continue
 [ "$ONEDIR" = "$rw1/$1/.cache" ] && continue
 [ "$ONEDIR" = "$rw1/$1/cache" ] && continue
 [ "$ONEDIR" = "$rw1/$1/.thumbnails" ] && continue
 cp -aR "$ONEDIR" "$o1"
 #echo "cp -aR "$ONEDIR" "$o1""
 #echo "++$rw1++cp -a -R "$ONEDIR" "$o1""
done
}

ALSA(){
`which sudo` alsactl store
mkdir -p /tmp/makesfs/var/lib/alsa
cp -aR "$rw1"/var/lib/alsa /tmp/makesfs/var/lib
}
CONNMAN(){
which connman || return
mkdir -p /tmp/makesfs/var/lib/connman
cp -aR "$rw1"/var/lib/connman /tmp/makesfs/var/lib
mkdir -p /tmp/makesfs/var/lib/connman-vpn
cp -aR "$rw1"/var/lib/connman-vpn /tmp/makesfs/var/lib
}
wt -start "Копирование файлов в $SFSNAME" &

HOME1(){
[ -d "/$1" ] && HOME "$1"
}

case $type in
    home)
	echo --home--
	cp -aR "$rw1"/etc /tmp/makesfs
	
	HOME1 "home/`sfsusr`" 
#	HOME1 "home/`sfsusr`/.opera" 
	HOME1 "root" 
	ALSA
	CONNMAN
	wt -kill
	TRASHX
	;;
    net)
	mkdir -p /tmp/makesfs/etc/rc.d
	cp -aR "$rw1"/etc/netctl/ /tmp/makesfs/etc
	cp -aR "$rw1"/etc/systemd/ /tmp/makesfs/etc
	cp -a "$rw1"/etc/rc.d/net* /tmp/makesfs/etc/rc.d
	nt="/home/`sfsusr`/.config/autostart/netctl-tray.desktop"
	[ -f "$nt" ] && mkdir -p "/tmp/makesfs`dirname "$nt"`" && \
	    cp -a "$nt" "/tmp/makesfs`dirname "$nt"`" && chown -R "`sfsusr`" "/tmp/makesfs/home/`sfsusr`"
	CONNMAN
	wt -kill
    ;;
    save)
	HOME1 "home/`sfsusr`" 
#	HOME1 "home/`sfsusr`/.opera" 
	HOME1 "root" 
	ALSA
	CONNMAN
for ONEDIR in `find "$rw1" -maxdepth 1 -type d` ; do
 [ "$ONEDIR" = "$rw1/root" ] && continue
 [ "$ONEDIR" = "$rw1/home" ] && continue

 [ "$ONEDIR" = "$rw1" ] && continue
 [ "$ONEDIR" = "$rw1/dev" ] && continue
 [ "$ONEDIR" = "$rw1/initrd" ] && continue
 [ "$ONEDIR" = "$rw1/mnt" ] && continue
 [ "$ONEDIR" = "$rw1/proc" ] && continue
 [ "$ONEDIR" = "$rw1/sys" ] && continue
 [ "$ONEDIR" = "$rw1/tmp" ] && continue
 [ "$ONEDIR" = "$rw1/.wh..wh.orph" ] && continue
 [ "$ONEDIR" = "$rw1/.wh..wh.plnk" ] && continue
# basename="`basename $ONEDIR`"
 cp -a -R $ONEDIR/ /tmp/makesfs
done
	wt -kill
    #defaultterminal -e mkpfs /tmp/makesfs -o "$SFSNAME" 
    trim -g /tmp/makesfs
TRASHX

 if [ "`ls -1 /tmp/makesfs_DEV`" ] ;then
    ntf -q "Обнаружены файлы нужные только для компиляции (dev) объемом `cd /tmp/makesfs_DEV && du -sh`" "
Если их сейчас удалить - при необходимости система сама их по новому доустановит.

Удалить dev ?"
    if [ "$?" = "0" ] ;then
	rm -R /tmp/makesfs_DEV ; rm -R /tmp/makesfs/var/lib/pacman
    else
	cp -R /tmp/makesfs_DEV/* /tmp/makesfs && rm -R /tmp/makesfs_DEV
    fi
 fi
    ;;
    *) ;;
esac


if [ "$pup" ] ;then
for ONEFILE in `find /tmp/makesfs/ -name .wh.*`
do
 BASENAME="`basename "$ONEFILE"`"
 DIRNAME="`dirname "$ONEFILE"`"
 if [ -f "${DIRNAME}/${BASENAME:4}" ];then
  filelayer=0
  filewhlayer=0
  FILENAME="${DIRNAME:12}/${BASENAME:4}"
  FILEWHNAME="${DIRNAME:12}/${BASENAME}" 
  [ -f "/initrd/pup_usr${FILENAME}" ] && filelayer=1
  [ -f "/initrd/pup_ro1${FILENAME}" ] && filelayer=2
  [ -f "/initrd/pup_rw${FILENAME}" ] && filelayer=3
  [ -f "/initrd/pup_usr${FILEWHNAME}" ] && filewhlayer=1 
  [ -f "/initrd/pup_ro1${FILEWHNAME}" ] && filewhlayer=2
  [ -f "/initrd/pup_rw${FILEWHNAME}" ] && filewhlayer=3
  [ $filelayer -le $filewhlayer ] && rm -f "/tmp/makesfs${FILENAME}" || rm -f "/tmp/makesfs${FILEWHNAME}"  
 fi
done

mkdir -p /tmp/makesfs/tmp 
cp -a /tmp/firstrun /tmp/makesfs/tmp/firstrun
rm /tmp/makesfs/etc/.XLOADED

urxvt -e mksquashfs /tmp/makesfs "$SFSNAME" -e lost+found
status=$?
else
    rm -R  /tmp/makesfs/lost+found
    pfsm="`find /mnt -maxdepth 1 -wholename "/mnt/.*.[sp]fs"`"
    if [  "$pfsm" ] ;then
    #for i in $(find "$pfsm" -type f -wholename */share/applications/*.desktop) ;do
    for i in $(find $pfsm -type f -wholename */share/applications/*.desktop) ;do
	#удаляем ярлыки подключенных модулей
	#ntf -i $i &
	rm "/tmp/makesfs/usr/share/applications/`basename "$i"`" || rm "/tmp/makesfs/usr/local/share/applications/`basename "$i"`"
    done
    fi
#    ntf -q "Использовать слабое (gz) сжатие?" "
#090-save*.pfs будет большего размера, но создастся быстрее" && g="-g"
wt -start "Поиск устаревших .wh."
for i in `find /tmp/makesfs -name ".wh.*"` ;do
#    echo "$i"
#    i2="`dirname "$i"`/`basename "$i" |sed 's/.wh.//`"
    i2="`dirname "$i" |sed 's,/tmp/makesfs,,'`/`basename "$i" |sed 's/.wh.//'`"
#    i2="`dirname "$i"`/`basename "$i"`"
#    echo "i2=$i2 i="$i""
    [ -f "$i2" ] || continue
    [ `stat -c %Y "$i2"` -gt `stat -c %Y "$i"` ] || rm "$i"
done
wt -kill

if [ "`echo $o |grep 3`" ];then
    which pfsmerge && g= "-g" || g="-f" #pfs v3
fi
    m1="`wt "mkpfs -l $g /tmp/makesfs -o "$SFSNAME"" "Создание "$SFSNAME""`"
    status=$?
fi

umount /tmp/makesfs
rmdir /tmp/makesfs
rm "$file2fs"

#[ "$pup" ] || exitfunc

if [ $status -eq 0 ] ;then
    m="Создание $SFSNAME закончилось УСПЕШНО!"
    ntf -w "$m" "$m1" || yaf-splash -timeout 6 -font "8x16" -outline 0 -margin 4 -bg green -text "$m " 
else
    m="Проблема при создании SFS-модуля $SFSNAME!" ; m2="Проверьте наличие свободного места"
    ntf -a "$m $m2" "$m1" || gxmessage "$m $m2" --borderless --center --wrap --bg red
fi

exitfunc
