Sve brisanje se događa u remove_bloat()
[carnet-upgrade.git] / src / functions.sh
1 # Ivan 'ico' Rako <irako@srce.hr>
2 # Zoran 'jelly' Dzelajlija <jelly@srce.hr>
3 # Zeljko Boros <zelja@carnet.hr>
4
5 PHPVER="7.4"
6 MDB="10.5"
7 PINFILE="/etc/apt/preferences.d/99-carnet"
8
9
10 notice () {
11   LC_MESSAGES=hr_HR dialog --backtitle "$title" --msgbox "$*" 18 75
12 }
13
14 first_warning () {
15   LC_MESSAGES=hr_HR dialog --backtitle "$title" --yesno "$msg_first_warning" 18 75
16   if [ $? -ne 0 ]; then
17     log "Upgrade canceled."
18     exit 0
19   fi
20 }
21
22 second_warning () {
23   LC_MESSAGES=hr_HR dialog --backtitle "$title" --yesno "$msg_second_warning" 18 75
24   if [ $? -ne 0 ]; then
25     log "Upgrade canceled."
26     exit 0
27   fi
28 }
29
30 pkg() {
31   local version
32   dpkg -l "$1" 2> /dev/null | egrep -q "^.i" || return 1
33   [ -z "$2" ] && return 0
34   version=$(dpkg -s "$1" | awk '/^Version:/ {print $2}')
35   dpkg --compare-versions "$version" "$2" "$3" 2>&1 > /dev/null
36 }
37
38 log() {
39   local old_umask
40   logfile=${logfile:=/var/log/carnet-upgrade.log}
41
42   old_umask=$(umask)
43   umask 0077
44
45   echo "$(date +'%Y-%m-%d %H:%M:%S') $*" >> $logfile
46   echo "CN: $*"
47
48   umask $old_umask
49   chmod og= $logfile
50 }
51
52 # safe in-place s///
53 check_and_sed() {
54   [ "$DEBIAN_SCRIPT_DEBUG" ] && set -vx
55   local s sedcmd ret i
56   s="$1"
57   shift
58   sedcmd="$1"
59   shift
60   ret=2
61   for i in $*
62   do
63     [ -e "$i" ]        || continue
64     egrep -q "$s" "$i" || continue
65     [ -h "$i" ]        && i=$(readlink -f "$i")
66     sed "$sedcmd" "$i" > "$i.dpkg-tmp"
67     chown --reference "$i" "$i.dpkg-tmp"
68     chmod --reference "$i" "$i.dpkg-tmp"
69     mv "$i.dpkg-tmp" "$i"
70     ret=0
71   done
72   if [ "$ret" -eq 0 ]; then
73     log "Done \"$sedcmd\" to $*"
74   fi
75   return $ret
76 }
77
78 pkgadd () {
79   [ -n "$*" ] || return 0
80   log "Installing $* ..."
81   apt-get -y$s install $* || {
82     dpkg --configure -a
83     apt-get -yf install
84     apt-get -y$s install $*
85   }
86 }
87
88 pkgrm () {
89   [ -n "$*" ] || return 0
90   log "Purging $* ..."
91   apt-get -y$s --purge remove $* || {
92     dpkg --configure -a
93     apt-get -yf install
94     apt-get -y$s --purge remove $*
95   }
96 }
97
98 pkgrm_only () {
99   [ -n "$*" ] || return 0
100   log "Removing $* ..."
101   apt-get -y$s remove $* || {
102     dpkg --configure -a
103     apt-get -yf install
104     apt-get -y$s remove $*
105   }
106 }
107
108
109 apt_update() {
110   log "Running apt-get update ..."
111   apt-get -y$s update || {
112     apt-get -yf install
113     apt-get -y$s update
114   }
115   apt-get autoclean
116 }
117
118 apt_download() {
119   log "Running apt-get download ..."
120   apt-get -dy$s dist-upgrade
121 }
122
123 dist_upgrade () {
124   log "Running upgrade ..."
125   apt-get -y$s upgrade || {
126     dpkg --configure -a
127     apt-get -y$s upgrade
128   }
129
130   log "Running dist-upgrade ..."
131   apt-get -y$s dist-upgrade || {
132     dpkg --configure -a
133     apt-get -y$s dist-upgrade
134   }
135 }
136
137 apt_autoremove () {
138   log "Running autoremove ..."
139   apt-get -y$s --purge autoremove || {
140     dpkg --configure -a
141     apt-get -yf install
142   }
143 }
144
145 # remove stale package information from available
146 #   warning, in file '/var/lib/dpkg/available'
147 #   near line 58185 package 'vim-cn': missing architecture
148 cleanup_available () {
149   log "Cleaning dpkg available file"
150
151   available=$(mktemp /var/lib/carnet-upgrade/available.XXXXXX)
152   apt-cache dumpavail > $available
153
154   dpkg --clear-avail
155   dpkg --update-avail $available
156
157   rm -f $available
158 }
159
160 remove_x() {
161   LC_MESSAGES=hr_HR dialog --backtitle "$title" --yesno "$msg_remove_x" 18 75
162   if [ $? -eq 0 ]; then
163     log "Removing X Window System"
164     pkgrm xserver-xorg
165   else
166     log "Skipping X Window System removal"
167   fi
168 }
169
170 remove_bloat() {
171 ### zelja 2023-07-06
172 tempdelfile=$(mktemp /tmp/tempdelfile.XXXX)
173
174 for a in $bloats; do echo apt-get -qq -y remove $a 2\> /dev/null ; done > $tempdelfile
175
176 /bin/bash $tempdelfile
177 rm $tempdelfile
178
179 return 0
180
181
182   local to_remove add_this i j n text to_show cmd tmpfile installed
183   local update_selections pkgs_to_deselect pkgs_to_remove oldifs pkglist
184   text="$msg_remove_bloat"
185
186   [ "$DEBUG" ] && set -x
187   n=0
188   pkglist=$(mktemp /var/lib/carnet-upgrade/pkglist.XXXXXX)
189   COLUMNS=200 dpkg -l | awk '$1 ~ /^.i/ { print $2 }' > $pkglist
190   for i in $(echo "$bloats" | sed 's/           */      /g'| awk -F'    ' '{print $2}')
191   do
192     if grep -q "^$i$" $pkglist; then
193       installed="$installed $i"
194       add_this="$(echo "$bloats" | egrep "      .*\b${i}\b" | sed 's/           */      /g'| awk -F'    ' '{print $1}')"
195       if ! echo "$to_show" | grep -q "$add_this"; then
196         to_show="$to_show \"$add_this\" \"\" on"
197         n=$(($n+1))
198       fi
199     fi
200   done
201   [ "$DEBUG" ] || rm -f $pkglist
202   [ -z "$to_show" ] && return 0
203   test $n -gt 8 && n=8
204   tmpfile=$(mktemp /var/lib/carnet-upgrade/dialog-tmp.XXXXXX)
205   cmd="LC_MESSAGES=hr_HR dialog --nocancel --backtitle \""$title"\" --checklist \""$text"\" 20 75 $n $to_show"
206   [ "$DEBUG" ] && set +x
207     eval $cmd 2> $tmpfile
208   [ "$DEBUG" ] && set -x
209   to_remove="$(cat $tmpfile | sed 's/\"\ \"/    /g; s/\"\ *//g; s/\\//g')"
210   [ "$DEBUG" ] || rm -f $tmpfile 
211   [ "$DEBUG" ] && echo "DEBUG: to_remove=$to_remove" 1>&2
212   oldifs="$IFS"
213   IFS=" " # tab
214   for i in $(echo "$to_remove")
215   do
216     IFS="$oldifs"
217     for j in $(echo "$bloats" | grep "^$i" | sed 's/            */      /g'| awk -F'    ' '{print $2}')
218     do
219       # hopefully this will tell apt not to reinstall them at upgrade time
220       update_selections="${update_selections}
221         $j      deinstall"
222       pkgs_to_deselect="$pkgs_to_deselect $j"
223       # only remove those that really are installed
224       if echo "$installed" | grep -q "$j"; then
225         pkgs_to_remove="$pkgs_to_remove $j"
226       fi
227     done
228   done
229   IFS="$oldifs"
230   [ "$DEBUG" ] && echo "DEBUG: pkgs_to_remove=$pkgs_to_remove" 1>&2
231   # Finally, remove those
232   if [ -n "$update_selections" ]; then
233     echo "$update_selections" | dpkg --set-selections
234     log "Deselected:${pkgs_to_deselect}"
235   fi
236   eval pkgrm $pkgs_to_remove
237 }
238
239 remove_cn_bloat() {
240 ### Sve obrisano u remove_bloat()
241 return 0
242
243   local installed pkg cn_pkgs dialog_list selection cn_del to_del del_pkgs
244
245   # get installed packages
246   installed=$(mktemp /var/lib/carnet-upgrade/pkglist.XXXXXX)
247   COLUMNS=200 dpkg -l | awk '$1 ~ /^.i/ { print $2 }' >$installed
248
249   # detect installed CN packagees
250   for pkg in $(echo "$cn_bloats" | cut -d' ' -f1); do
251     if grep -qx $pkg $installed; then
252       cn_pkgs="$cn_pkgs $pkg"
253       dialog_list="$dialog_list $pkg '' off"
254     fi
255   done
256   rm -f $installed
257
258   # report status or finish if no CN packages found
259   if [ "$cn_pkgs" ]; then
260     log "Found CN packages:$cn_pkgs"
261   else
262     log "No CN packages found."
263     return
264   fi
265
266   # user selects the packages to delete
267   selection=$(mktemp /var/lib/carnet-upgrade/selection.XXXXXX)
268   eval LC_MESSAGES=hr_HR dialog --nocancel --backtitle \""$title"\" \
269     --checklist \""$msg_remove_cn_bloat"\" 20 75 6 $dialog_list 2>$selection
270
271   # expand the package list to include the services
272   for pkg in $(cat $selection); do
273     pkg=${pkg%\"}
274     pkg=${pkg#\"}
275     cn_del="$cn_del $pkg"
276     to_del=$(echo "$cn_bloats" | grep ^$pkg)
277     del_pkgs="$del_pkgs $to_del"
278   done
279   rm -f $selection
280
281   # report selection or finish if no service selected
282   if [ "$cn_del" ]; then
283     log "Removing CN services:$cn_del"
284   else
285     log "No CN services selected for removal."
286     return
287   fi
288
289   # delete the cn packages and relevant services
290   pkgrm_only $del_pkgs
291 }
292
293 post_upgrade() {
294   touch "$post_upgrade_queuetab"
295   if ! grep -q "true    $*" "$post_upgrade_queuetab"; then
296     echo "true  $*" >> "$post_upgrade_queuetab"
297   fi
298 }
299
300 run_post_upgrade() {
301   if [ -f "$post_upgrade_queuetab" ]; then
302     run_actions post_upgrade "$post_upgrade_queuetab"
303     mv "$post_upgrade_queuetab" "${post_upgrade_queuetab}.done.$(date '+%Y-%m-%d.%H:%M:%S')"
304   fi      
305 }
306
307 ###
308
309 run_actions() {
310   local line lineno lineno2 f n name action checkmsg check
311   [ "$DEBUG" ] && set -vx
312   name="$1"
313   f="$2"
314   [ -f "$f" ] ||   return 2 # no such file
315   n=$(wc -l "$f" | awk '{print $1}')
316   [ "$n" -lt 1 ] && return 1 # no lines to process
317   log "run_actions ($name) started, processing $n lines from \"$f\"."
318   log "-----"
319   lineno=0
320   lineno2=0
321   while [ "$lineno" -lt "$n" ]
322   do
323     lineno=$(($lineno+1))
324     lineno2=$lineno
325     line=$(head -$lineno "$f" | tail -1)
326     if echo $line | grep -q '^#'; then  # comment
327       continue
328     fi
329     while echo "$line" | egrep -q '\\$' # continuation
330     do
331       lineno2=$(($lineno2+1))
332       line=$(echo -n "$line"| sed 's/\\$//'; head -$lineno2 "$f" | tail -1)
333     done
334     check=$(echo "$line" | sed 's/              */      /g'| awk -F'    ' '{print $1}')
335     action=$(echo "$line" | sed 's/             */      /g'| awk -F'    ' '{print $2}')
336     checkmsg=""
337     [ "$check" != "true" ] && checkmsg="if '$check'"
338     if eval $check; then
339       log "$(printf 'action %02d' $lineno) starting: '${action}' $checkmsg "
340       if ! eval $action; then
341         log "$(printf 'action %02d' $lineno) failed: '${action}' $checkmsg "
342         display_action_failure "$action"
343         exit 1
344       else  
345         log "$(printf 'action %02d' $lineno) finished: '${action}' $checkmsg"
346       fi
347     else
348       log "$(printf 'action %02d' $lineno) skipping: '${action}' $checkmsg"
349     fi
350     [ "$lineno2" -gt "$lineno" ] && lineno=$lineno2
351   done
352   log "run_actions ($1) finished"
353   log "-----"
354 }
355
356 # report action failure
357 display_action_failure () {
358   local action=$1
359
360   notice "
361 Doslo je do greske prilikom izvrsavanja akcije '$action'. Detalje problema moguce je vidjeti u log datotekama:
362
363   /var/log/carnet-upgrade.log
364   /var/log/carnet-upgrade.typescript
365
366 Da bi dovrsili zapocete operacije nad paketima pokrenite:
367
368   # dpkg --configure -a
369   # apt -f install
370
371 Nakon toga ponovno pozovite carnet-upgrade skriptu."
372 }
373
374 # funkcija vraca popis paketa koje treba upgradeati
375 what_upgrade () {
376   local IFSOLD name version package
377
378   for package in `echo "$needed_versions" | awk '{print $1}'| grep -v ^$`; do
379     IFSOLD="$IFS"
380     IFS="       " # tab
381     read name version <<-EOPTS
382         $(echo "$needed_versions" | sed 's/             */      /g' | grep ^$package)
383         EOPTS
384     IFS="$IFSOLD"
385     if pkg "$name" lt "$version"; then
386         echo -n " $name"
387     fi
388   done
389 }
390
391 # funkcija za ispis paketa koje treba upgradeati
392 check_upgrade () {
393   local upgrade
394   upgrade=${1:-"`what_upgrade`"}
395
396   if [ "$upgrade" ]; then
397     notice "
398 Prije prelaska na Debian bullseye potrebno je napraviti nadogradnju ovih paketa:
399   $upgrade
400
401 Pokrenite:
402   # apt-get update
403   # apt-get dist-upgrade
404 ili:
405   # apt-get update
406   # apt-get install${upgrade}
407   
408 Nakon toga ponovno pozovite ovu skriptu."
409     log "carnet-upgrade aborted, upgrade of$upgrade needed."
410     exit 1
411   fi
412 }
413
414 # try to check if we are using the latest version of carnet-upgrade script
415 check_my_version () {
416   local packages latest_version
417
418   packages=$(mktemp /var/lib/carnet-upgrade/Packages.XXXXXX)
419   if wget -q -O$packages $packages_uri; then
420     latest_version=$(sed -ne \
421         '/Package: carnet-upgrade/,/Description:/{ /Version: /s///p }' \
422         $packages)
423     rm -f $packages
424
425     if [ "$latest_version" ]; then
426       log "Running carnet-upgrade version is $version"
427       log "Latest carnet-upgrade version is $latest_version"
428       if dpkg --compare-versions "$version" lt "$latest_version"; then
429         check_upgrade " carnet-upgrade"
430       else log "Already using the latest carnet-upgrade version."; fi
431     else log "Failed to get latest version, skipping check."; fi
432   else log "Failed to download Packages file, skipping check."; fi
433
434   rm -f $packages
435 }
436
437 check_reboot () {
438   reboot_required || return 0
439
440   LC_MESSAGES=hr_HR dialog --backtitle "$title" --yesno "$reboot_warning" 18 +75
441   if [ $? -eq 0 ]; then
442     log "Reboot before continuing."
443     exit 0
444   else
445     log "Proceed without reboot."
446   fi
447 }
448
449 # check if the latest kernel is booted
450 reboot_required () {
451   local default_kernel kernel_package running_release running_version
452
453   # try to get default kernel from grub2
454   if [ -z "$default_kernel" -a -r "/boot/grub/grub.cfg" ]; then
455       default_kernel=$( awk '
456            $0 ~ /^set default=".*"/ { 
457                def = gensub(/default="(.*)"/, "\\1", "1", $2);
458                if (def !~ /^[0-9]+$/) { exit }
459            }
460            $1 == "menuentry" { menuentry+=1 }
461            $1 == "linux" && menuentry==def+1 { print $2; exit }' \
462            /boot/grub/grub.cfg 2>/dev/null )
463   fi
464
465   # try to get default kernel from grub-legacy
466   if [ -z "$default_kernel" -a -r "/boot/grub/menu.lst" ]; then
467       default_kernel=$( awk '
468            $1 == "default" { def = $2; 
469                              if (def !~ /^[0-9]+$/) { exit } }
470            $1 == "title" { title+=1 }
471            $1 == "kernel" && title==def+1 { print $2; exit }' \
472            /boot/grub/menu.lst 2>/dev/null )
473   fi
474
475   # try to get default kernel from lilo
476   if [ -z "$default_kernel" ] && type lilo >/dev/null 2>&1; then
477       default_kernel=$( lilo -t -v 2>/dev/null \
478                         | grep -B3 '[*]$' \
479                         | sed -n -e '/^Boot image: / { s///p; q; }' )
480   fi
481
482   if [ -z "$default_kernel" ]; then
483       log "Could not find default kernel"
484       return 1
485   fi
486
487   log "Default kernel image: $default_kernel"
488
489   if [ ! -e "$default_kernel" ]; then
490       # /boot prefix might be missing
491       default_kernel="/boot/${default_kernel#/}"
492       if [ ! -e "$default_kernel" ]; then
493           log "Default kernel image doesn't exist!?"
494           return 1
495       fi
496   fi
497
498   kernel_package=$( dpkg -S $default_kernel | cut -d: -f 1 )
499
500   if [ -z "$kernel_package" ]; then
501       log "Default kernel not installed from a package"
502       return 1
503   fi
504
505   log "Default kernel package: $kernel_package"
506
507   running_release=$( uname -r )
508   running_version=$( uname -v )
509   log "Running kernel: $running_release $running_version"
510
511   if [ "$kernel_package" != "${kernel_package#linux-image-3.2.0-}" ] ||
512      grep -q "$running_release .* $running_version" $default_kernel
513   then
514       log "Latest kernel version is running." 
515       return 1
516   else
517       log "Reboot to latest version required."
518       return 0
519   fi
520 }
521
522 upgrade () {
523   local packages
524   case "$1" in
525     first)
526       packages="$packages_first"
527     ;;
528     second)
529       packages="$packages_second"
530     ;;
531     *)
532     return 1
533   esac
534
535   pkgupgrade $packages
536 }
537
538 # install packages introduced in this release
539 install_new () {
540   if [ "$new_packages" ]; then
541     pkgadd $new_packages
542   fi
543 }
544
545 # funkcija utrpa ispravan sources.list
546 create_sources_list () {
547     local sl sl_new
548     sl=/etc/apt/sources.list
549     sl_new=$( copy_template $sl )
550
551     # comment aai repository if not in use
552     if ! pkg srce-keyring; then
553         sed -i 's/^\(deb.*ftp.srce.hr\)/#\1/' $sl_new
554     fi
555
556     # check if already installed
557     if ! cmp $sl $sl_new >/dev/null; then
558
559         # backup old version
560         if [ -f $sl -a ! -f $sl.$backup_ext ]; then
561             cp -v $sl $sl.$backup_ext
562         fi
563
564         # install new version
565         cp -v $sl_new $sl
566         notice "Novi sadrzaj datoteke /etc/apt/sources.list:
567
568 `cat /etc/apt/sources.list`"
569     fi
570
571     # make sure permissions are correct
572     chmod 0644 $sl
573     rm $sl_new
574 }
575
576 # funkcija koja brise grupu proc
577 remove_group_proc () {
578   if getent group proc > /dev/null; then
579     groupdel proc || true
580     log "groupdel proc (temporarily)"
581     post_upgrade add_group_proc
582   fi
583 }
584
585 add_group_proc () {
586   if ! getent group proc > /dev/null; then
587     # grsec uses gid 99 for /proc files
588     groupadd -g 99 proc 
589     log "groupadd -g 99 proc"
590
591     # update oidentd so it uses the proc group
592     if [ -x /etc/init.d/oidentd ]; then
593         if gpasswd -a oident proc; then
594             /etc/init.d/oidentd restart
595         fi
596     fi
597   fi
598 }
599
600 # backup ldap database
601 backup_slapd_db () {
602   local ldap_backup=/var/backups/slapcat.$backup_ext.gz
603   local old_umask result
604
605   if [ ! -f $ldap_backup ]; then
606     [ -x /etc/init.d/freeradius ] && /etc/init.d/freeradius stop || true
607
608     if [ -x /etc/init.d/slapd -a -d /var/lib/ldap ]; then
609       /etc/init.d/slapd stop || true
610       old_umask=`umask`
611       umask 0077 # protect the backup file
612       slapcat | gzip --best > $ldap_backup
613       result=$?
614       umask $old_umask
615       /etc/init.d/slapd start || true
616
617       if [ "$result" -eq 0 ]; then
618         log "$ldap_backup created"
619         notice "Napravljen backup slapd baze u $ldap_backup."
620       else
621         log "$ldap_backup was not created"
622         notice "Backup slapd baze u $ldap_backup nije uspio."
623         exit 1
624       fi
625     fi
626
627     [ -x /etc/init.d/freeradius ] && /etc/init.d/freeradius start || true
628   else
629     log "slapd backup already at $ldap_backup, skipping."
630     #notice "Backup slapd baze u $ldap_backup vec postoji!"
631   fi
632 }
633
634 # backup etc direktorija
635 backup_etc_dir () {
636   local etc_backup=/var/backups/etc.$backup_ext.tar.gz
637   local old_umask
638
639   if [ ! -f $etc_backup ]; then
640     old_umask=`umask`
641     umask 0077 # protect the backup file
642
643     if tar cfz $etc_backup /etc 2> /dev/null; then
644       log "$etc_backup created"
645       notice "Napravljen backup /etc direktorija u $etc_backup."
646     else
647       log "$etc_backup was not created"
648       notice "Backup /etc direktorija u $etc_backup nije uspio."
649       exit 1
650     fi
651     umask $old_umask
652   else
653     log "/etc backup already present in $etc_backup, skipping."
654     #notice "Backup /etc direktorija u $etc_backup vec postoji!"
655   fi
656 }
657
658 # restore a configuration file if it contains only CN modifications
659 restore_file () {
660   local file file_expect file_restore file_backup
661
662   file=$1
663   file_expect=$2
664   file_restore=$3
665   file_backup=$file.$backup_ext
666
667   [ "$file_expect" ] || file_expect=$cnup/files/$file.expect
668   [ "$file_restore" ] || file_restore=$cnup/files/$file.restore
669
670   # check if all required files are there
671   if ! [ -e $file -a -e $file_expect -a -e $file_restore ]; then
672     log "Required files missing, skipping $file restore."
673     return 1
674   fi 
675
676   # is restore needed
677   if ! cmp $file_expect $file >/dev/null; then
678     log "Config doesn't match the template, skipping $file restore."
679     return 1
680   fi
681
682   # backup and restore
683   if [ ! -e $file_backup ]; then
684     log "Restoring config file $file."
685
686     # backup local changes
687     cp -av $file $file_backup
688
689     # restore original
690     cp -v $file_restore $file
691
692     # restore succedded
693     return 0
694   else 
695     log "Backup file exists, skipping $file restore."
696     return 1
697   fi
698 }
699
700 # force reconfiguration at the end if package is not upgraded automatically
701 postupgrade_reconfigure () {
702   local cn_package cn_version
703
704   cn_package=$1
705   cn_version=$( dpkg -s "$cn_package" | awk '/^Version:/ {print $2}' )
706   post_upgrade "pkg $cn_package gt $cn_version || dpkg-reconfigure $cn_package"
707 }
708
709 # copy template into a temporary file
710 copy_template () {
711   local path file template config_new
712
713   path=$1
714   file=$(basename $path)
715   template=$cnup/files/$path.template
716   config_new=$(mktemp /var/lib/carnet-upgrade/$file.XXXXXX)
717   cp $template $config_new
718
719   echo $config_new
720 }
721
722 # restore modified config to their package defaults
723 # so the upgrade doesn't complain so much
724 restore_configs () {
725   local hostname domain config_new memtotal memlimit
726
727   # restore simple configs
728   if pkg ntp-cn && pkg ntp lt 1:4.2.6.p5+dfsg-2; then
729      if restore_file /etc/ntp.conf; then
730         postupgrade_reconfigure ntp-cn
731      fi
732   fi
733
734   if pkg vsftpd-cn && pkg vsftpd lt 2.3.5-3; then
735      if restore_file /etc/vsftpd.conf; then
736         postupgrade_reconfigure vsftpd-cn
737      fi
738   fi
739
740   if pkg amavisd-cn && pkg amavisd-new lt 1:2.7.1-2; then
741      if restore_file /etc/cron.d/amavisd-new; then
742         rm -f /etc/cron.d/amavisd-new.$backup_ext
743         postupgrade_reconfigure amavisd-cn
744      fi
745   fi
746
747   if pkg ossec-hids lt 2.7-1; then
748      if restore_file /var/ossec/rules/local_rules.xml; then
749         postupgrade_reconfigure ossec-hids-cn
750      fi
751   fi
752
753   if pkg sasl2-bin lt 2.1.25.dfsg1-6+deb7u1; then
754      if restore_file /etc/default/saslauthd; then
755         postupgrade_reconfigure postfix-cn
756      fi
757   fi
758
759   if pkg base-files lt 7.1wheezy2; then
760      restore_file /etc/issue
761      restore_file /etc/issue.net
762   fi
763
764   # check if monitrc is template based
765   if [ -e /etc/monit/monitrc ]; then # monit is removed at this point
766      # regenerate config from template
767      hostname=$(hostname)
768      domain=$(hostname --domain)
769      config_new=$(copy_template /etc/monit/monitrc)
770      check_and_sed "@localhost" \
771        "s/@localhost/@$hostname.$domain/g" $config_new || true
772      restore_file /etc/monit/monitrc $config_new
773      rm -f $config_new
774   fi
775 }
776
777 # load various debconf defaults
778 debconf_preload () {
779   echo libc6 libraries/restart-without-asking boolean true | debconf-set-selections
780 }
781
782 # temporary disable listchanges packages to reduce clutter during upgrade
783 apt_listchanges () {
784   local file command=$1
785
786   for file in /etc/apt/apt.conf.d/20listchanges \
787               /etc/apt/apt.conf.d/20listchanges-cn
788   do
789       case $command in
790            disable)
791                if [ -f $file ]; then
792                    dpkg-divert --local --rename --divert $file.disabled \
793                                --add $file || true
794                fi
795                ;;
796
797            enable)
798                # cleanup the diversion even if the file is already removed
799                dpkg-divert --rename --remove $file || true
800                ;;
801      esac
802   done
803 }
804
805 # make a silent installation of carnet and srce keyrings
806 install_keyrings () {
807   pkgadd carnet-keyring debian-archive-keyring
808   dpkg-reconfigure carnet-keyring debian-archive-keyring
809
810   if pkg srce-keyring; then
811     pkgadd srce-keyring
812     dpkg-reconfigure srce-keyring
813   fi
814
815   apt_update
816 }
817
818 # check if package is orphaned (nothing depends on it)
819 is_orphaned () {
820   local package deps
821
822   package=$1
823   deps=$(apt-get remove -s $package | grep ^Remv | wc -l)
824   if [ "$deps" -eq 1 ]; then 
825     return 0
826   else 
827     return 1
828   fi
829 }
830
831 # remove old and unused libraries
832 remove_orphaned () {
833   local package remove
834
835   apt_autoremove
836
837   remove=
838   for package in $orphaned_packages; do
839     if is_orphaned $package; then
840       remove="$remove $package"
841     fi
842   done
843
844   if [ "$remove" ]; then
845     pkgrm $remove
846   fi
847 }
848
849 # monit it causing problems for postinst scripts
850 # restarting daemons so try to disable it
851 disable_monit () {
852   if pkg monit-cn; then
853     pkgrm monit-cn # disables monit in prerm
854   fi
855
856   # if configured manually
857   if pkg monit; then
858     # remove the binary but leave the config
859     apt-get remove --yes monit
860     # stop the binary
861     pkill -9 monit || true
862     # move away init for insserv to work
863     mv /etc/init.d/monit /var/lib/carnet-upgrade/
864   fi
865 }
866
867 # allow monit to run again
868 enable_monit () {
869   if [ -f /var/lib/carnet-upgrade/monit ]; then
870     mv /var/lib/carnet-upgrade/monit /etc/init.d/monit
871     pkgadd monit-cn
872   fi 
873 }
874
875 # check which of the given packages are installed
876 grep_installed () {
877   local package installed
878
879   for package in $*; do
880     if pkg $package; then
881       installed="$installed $package"
882     fi
883   done
884
885   echo $installed
886 }
887
888 # only upgrade packages if they are already installed
889 pkgupgrade () {
890   local packages
891
892   packages=$( grep_installed $* )
893
894   if [ "$packages" ]; then
895     eval pkgadd $packages
896   fi
897 }
898
899 # upgrade apache2/php
900 upgrade_apache2 () {
901 ### ne treba od etcha
902 ### pkgrm apache-common # prevents installation of apache2-suexec
903   pkgupgrade libapache2-mod-php$PHPVER php$PHPVER-cli php$PHPVER-cn apache2-cn \
904     php$PHPVER-odbc mod-security-cn
905 }
906
907 upgrade_amavis () {
908   local conf
909
910   # move old config aside
911   for conf in /etc/amavisd.conf /etc/amavis/amavisd.conf; do
912     if [ -e $conf -a ! -e $conf.$backup_ext ]; then
913       mv -v $conf $conf.$backup_ext
914     fi
915   done
916
917   # workaround for insserv complaining
918   if [ -x /sbin/insserv ]; then
919     if [ -r /etc/init.d/amavis.amavisd-new ]; then
920       /sbin/insserv amavis.amavisd-new
921     fi
922   fi
923
924   # install new packages
925   pkgadd amavisd-cn amavisd-new
926
927   # workaround for insserv complaining
928   if [ -x /sbin/insserv ]; then
929     if [ -r /etc/init.d/amavis.amavisd-new ]; then
930       /sbin/insserv amavis.amavisd-new
931     fi
932   fi
933
934   # start new packages
935   ### By zelja, nema vise amavisd-cn, vjerujemo systemd-u
936   ### /etc/init.d/amavisd-cn restart
937   /etc/init.d/amavis restart
938 }
939
940 # handle mysql upgrade
941 upgrade_mysql () {
942   if pkg mysql-server || pkg mysql-server-5.5 || \
943      pkg mariadb-server || pkg mariadb-server-$MDB
944   then
945      pkgadd default-mysql-server
946      dpkg -P mysql-server mysql-server-5.5 mariadb-server-$MDB
947      service mysql restart
948   fi
949 }
950
951 # fix postgresql deinstallation during upgrade
952 upgrade_postgresql () {
953   if check_services show 2>&1 | grep -qw postgresql; then
954      apt-get install -y postgresql || apt-get -yf install
955   fi
956 }
957
958 # upgrade the MTA
959 upgrade_postfix () {
960   pkgadd sasl2-bin postfix-cn
961
962   if pkg postgrey; then
963      pkgrm postgrey # not used by postfix-cn anymore
964   fi
965 }
966
967
968 # pinning za baculu da se ne nadogradi sa 7.4.4 na 9.* u busteru
969 # istu stvar radi i bacula-cn.postinst
970
971 fix_bacula() {
972
973    echo "CN: Dodajem pinning bacule na inačicu 7.4.4..."
974
975    test -f $PINFILE || touch $PINFILE
976
977    cp-update bacula-cn $PINFILE <<EOF
978    
979 Package: bacula-fd
980 Pin: version 7.4.4*
981 Pin-Priority: 1001
982
983 Package: bacula-common
984 Pin: version 7.4.4*
985 Pin-Priority: 1001
986
987 Package: bacula-console
988 Pin: version 7.4.4*
989 Pin-Priority: 1001
990
991 EOF
992
993 }
994
995 # pinning za ocsinventory da se ne nadogradi sa 2.0.5 na 2.4.2
996
997 fix_ocsinventory() {
998
999    echo "CN: Dodajem pinning ocsinventory-agenta na inačicu 2.0.5..."
1000    test -f $PINFILE || touch $PINFILE
1001
1002    cp-update ocsinventory-agent-cn $PINFILE <<EOF
1003
1004 Package: ocsinventory-agent
1005 Pin: version 2:2.0.5*
1006 Pin-Priority: 1001
1007
1008 EOF
1009
1010 }
1011
1012 # upgrade the IMAP server
1013 upgrade_dovecot() {
1014  # Funkcija koju je dodao Valentin da popravi propuste u dovecot-cn
1015  # Mičem zaostale konfiguracije iz conf.d i izlazim prije njegovih akcija jer ubiju certifikate
1016
1017  test -f /etc/dovecot/conf.d/95-cn6-upgrade.conf && mv /etc/dovecot/conf.d/95-cn6-upgrade.conf* /var/backups || true
1018  test -f /etc/dovecot/conf.d/95-cn7-upgrade.conf && mv /etc/dovecot/conf.d/95-cn7-upgrade.conf* /var/backups || true
1019  test -f /etc/dovecot/conf.d/95-cn8-upgrade.conf && mv /etc/dovecot/conf.d/95-cn8-upgrade.conf* /var/backups || true
1020  test -f /etc/dovecot/conf.d/95-cn9-upgrade.conf && mv /etc/dovecot/conf.d/95-cn9-upgrade.conf* /var/backups || true
1021    
1022  return 0
1023
1024 # ostatak se nikada ne izvrši
1025
1026   local local_conf=/etc/dovecot/conf.d/95-${backup_ext}.conf
1027
1028   if [ -f /etc/dovecot/conf.d/95-local -a ! -f $local_conf ]; then
1029      mv /etc/dovecot/conf.d/95-local $local_conf
1030      sed -i 's/\/usr\/lib\/dovecot\/modules\/imap/\/usr\/lib\/dovecot\/modules/g' $local_conf
1031      /etc/init.d/dovecot restart
1032   fi
1033
1034   if [ ! -f $local_conf ]; then
1035      pkgrm dovecot-cn
1036
1037      # restore config
1038      if [ ! -f /etc/dovecot/dovecot.conf.$backup_ext ]; then
1039         mv /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.$backup_ext
1040         cp /usr/share/dovecot/dovecot.conf /etc/dovecot/dovecot.conf
1041      fi
1042
1043      # copy SSL certificates
1044      OLD_SSL_CERT="/etc/ssl/certs/dovecot.pem"
1045      OLD_SSL_KEY="/etc/ssl/private/dovecot.pem"
1046      SSL_CERT="/etc/dovecot/dovecot.pem"
1047      SSL_KEY="/etc/dovecot/private/dovecot.pem"
1048      if [ -f $OLD_SSL_CERT -a -f $OLD_SSL_KEY -a ! -f $SSL_CERT -a ! -f $SSL_KEY ]; then
1049         if [ ! -e /etc/dovecot/private ]; then
1050            install -d -o root -g root -m0700 /etc/dovecot/private
1051         fi
1052
1053         cp -av $OLD_SSL_CERT $SSL_CERT
1054         cp -av $OLD_SSL_KEY $SSL_KEY
1055
1056         chown root:dovecot $SSL_CERT
1057         chmod 0644 $SSL_CERT
1058         chown root:dovecot $SSL_KEY
1059         chmod 0600 $SSL_KEY
1060      fi
1061
1062      # install new version and restore local changes
1063      pkgadd dovecot-core
1064      doveconf -n -c /etc/dovecot/dovecot.conf.$backup_ext > $local_conf
1065      sed -i 's/\/user\/lib\/dovecot\/modules\/imap/\/usr\/lib\/dovecot\/modules/g' $local_conf
1066
1067      pkgadd dovecot-cn
1068   fi
1069 }
1070
1071 # upgrade bind separately so DNS is not down for too long
1072 # or breaks postinst scripts of other cn packages that depend on
1073 # working resolver
1074 upgrade_bind() {
1075   pkgadd bind9-cn
1076 }
1077
1078 # handle fail2ban upgrade due to error:
1079 # trying to overwrite '/etc/fail2ban/filter.d/dovecot.conf', which is also in package fail2ban-cn
1080 upgrade_fail2ban() {
1081   if pkg fail2ban-cn && dpkg -L fail2ban-cn | grep -qF dovecot.conf; then
1082     pkgrm fail2ban-cn
1083     pkgadd fail2ban
1084     pkgadd fail2ban-cn
1085   fi
1086 }
1087
1088 # manual upgrade of mailman to avoid two copies of mailman running
1089 # first started by python upgrade and second started by mailman itself
1090 upgrade_mailman() {
1091   if pkg mailman-cn lt 2:2.1.15~cn0; then
1092     /etc/init.d/mailman stop || true
1093     pkgadd python
1094     pkgadd mailman mailman-cn
1095   fi
1096 }
1097
1098 # manual upgrade of kernel due to new packet name
1099 upgrade_kernel() {
1100   if pkg kernel-2.6-cn; then
1101     pkgrm kernel-2.6-cn
1102
1103     if pkg grub-pc; then
1104       pkgadd kernel-cn grub-pc
1105     else
1106       pkgadd kernel-cn
1107     fi
1108   fi
1109 }
1110
1111 get_variable () {
1112   local name=$1 file=$2 val
1113
1114   if [ -f "$file" ]; then
1115      val=$(sed -n "/^[[:space:]]*$name[[:space:]]*=/s/[[:space:]]*//gp" $file)
1116      val=${val#*=}
1117   fi
1118
1119   echo $val
1120 }
1121
1122 # switch to rsyslog
1123 upgrade_syslog() {
1124   # libc6-dev prevents upgrade
1125   if pkg libc6-dev; then
1126      pkgrm libc6-dev
1127   fi
1128
1129   pkgadd rsyslog
1130   dpkg -P sysklogd klogd > /dev/null 2>&1
1131 }
1132
1133 # restore munin configs for silent upgrade
1134 upgrade_munin () {
1135   local config backup hostname domain
1136
1137   # new htmldir location
1138   if [ -d /var/www/munin -a ! -e /var/cache/munin/www ]; then
1139     mkdir -p /var/cache/munin
1140     mv /var/www/munin /var/cache/munin/www
1141   fi
1142
1143   for pkg_name in munin munin-node; do
1144      pkg $pkg_name lt '1.4.5-3' || continue
1145
1146      config=/etc/munin/$pkg_name.conf
1147      backup=$config.$backup_ext
1148      if [ -f $config -a ! -f $backup ]; then
1149         hostname=$(hostname)
1150         domain=$(hostname --domain)
1151
1152         cp -av $config $backup
1153         check_and_sed "$hostname.$domain" \
1154           "s/$hostname.$domain/localhost.localdomain/g" $config
1155      fi
1156      pkgadd $pkg_name
1157   done
1158
1159   # force localhost -> hostname replacement in config files
1160   pkgadd munin-cn
1161   dpkg-reconfigure munin-cn
1162 }
1163
1164 check_archives_space() {
1165   local available_disk_space archives_size
1166   available_disk_space=$(free_space /var/cache/apt/archives/)
1167   archives_size=$(download_size dist-upgrade)
1168
1169   if [ $? -ne 0 ]; then
1170     log "Failed to get download size, skipping check."
1171     return 0
1172   fi
1173
1174   log "Archives space: ${available_disk_space}MB"
1175   log "Download size: ${archives_size}MB"
1176
1177   if [ $available_disk_space -lt $archives_size ]; then
1178     log "carnet-upgrade aborted: not enough space in /var/cache/apt/archives/ (have ${available_disk_space}MB, need ${archives_size}MB)"
1179     notice "Premalo slobodnog mjesta u /var/cache/apt/archives/ za skidanje paketa (potrebno je barem ${archives_size}MB). Procitajte poglavlje 'Izvanredne situacije' u dokumentaciji."
1180     exit 1
1181   fi
1182 }
1183
1184 # calculate the list of linux-image packages from kernel-cn dependencies
1185 get_cn_kernels() {
1186   local cn_kernels linux_images metapkg pkg
1187
1188   cn_kernels=
1189   linux_images=$(apt-cache show kernel-cn | grep ^Depends: \
1190     | grep -o 'linux-image[^, ]*')
1191   for metapkg in $linux_images; do
1192     pkg=$(apt-cache show $metapkg | grep ^Depends: \
1193           | grep -o 'linux-image[^, ]*' | head -1)
1194     [ "$pkg" ] && cn_kernels="$cn_kernels $pkg"
1195   done
1196
1197   echo $cn_kernels
1198 }
1199
1200 # check if there is enough space on / for the new kernel package
1201 check_kernel_space() {
1202   local available_disk_space kernel_size linux_images pkg ret
1203   available_disk_space=$(free_space /)
1204
1205   linux_images=$( get_cn_kernels )
1206   for pkg in $linux_images; do
1207     kernel_size=$(installed_size $pkg)
1208     ret=$?
1209     [ $ret -eq 0 ] && break
1210   done
1211
1212   if [ $ret -ne 0 ]; then
1213     log "Failed to get installed size, skipping check."
1214     return 0
1215   fi
1216
1217   log "Free space in /: ${available_disk_space}MB"
1218   log "Kernel package: $pkg"
1219   log "Kernel size: ${kernel_size}MB"
1220
1221   if LC_ALL=C apt-get -s install kernel-cn 2>/dev/null \
1222      | grep -q '^kernel-cn is already the newest version.$'
1223   then
1224      log "Not checking free space in /: kernel-cn already installed"
1225      return
1226   fi
1227
1228   if [ $available_disk_space -lt $kernel_size ]; then
1229     log "carnet-upgrade aborted: not enough space in / (have ${available_disk_space}MB, need ${kernel_size}MB)"
1230     notice "Premalo mjesta u / za instalaciju kernela (potrebno je barem ${kernel_size}MB). Procitajte poglavlje 'Izvanredne situacije' u dokumentaciji."
1231     exit 1
1232   fi
1233 }
1234
1235 # free some space on / partition by cleaning old unused kernels
1236 clean_old_kernels() {
1237   local installed keep pkg keep remove delete name dialog_list selection
1238
1239   # find all installed kernels
1240   installed=$(
1241     dpkg -l | egrep '^ii  linux-image-[0-9]+[.][0-9]+[.][0-9]+-' \
1242     | awk '{print $2}'
1243   )
1244   log "Found kernel packages: $installed"
1245
1246   # leave current and new kernels
1247   keep="linux-image-$(uname -r) $(get_cn_kernels)"
1248   log "Keep kernel packages: $keep"
1249
1250   # check what to remove
1251   remove=
1252   for pkg in $installed; do
1253     delete=yes
1254     for name in $keep; do
1255       [ "$pkg" = "$name" ] && delete=
1256     done
1257     if [ "$delete" = yes ]; then
1258       remove="$remove $pkg"
1259     fi
1260   done
1261   log "Obsolete kernel packages: $remove"
1262
1263   if [ "$remove" ]; then
1264     for pkg in $remove; do
1265       dialog_list="$dialog_list $pkg '' off"
1266     done
1267
1268     # user selects the packages to delete
1269     selection=$( mktemp /var/lib/carnet-upgrade/selection.XXXXXX )
1270     eval LC_MESSAGES=hr_HR dialog --nocancel --backtitle \""$title"\" \
1271       --checklist \""$msg_remove_kernels"\" 20 75 6 $dialog_list 2>$selection
1272
1273     selected=$( tr -d \" < $selection )
1274     rm -f $selection
1275
1276     if [ "$selected" ]; then
1277       log "Removing kernel packages: $selected"
1278       pkgrm $selected
1279     fi
1280   fi
1281 }
1282
1283 # prevent sysv-rc migration problems
1284 clean_initd_packages() {
1285   local list removed pkg dialog_list selection selected
1286
1287   list=$( dpkg -S /etc/init.d/\* | grep -v ^diversion | cut -d: -f1 | sort -u )
1288   removed=$( dpkg -l $list | sed -n 's/^r.[[:space:]]\+\([^[:space:]]\+\).*/\1/p' )
1289   log "Found removed packages: $removed"
1290
1291   if [ "$removed" ]; then
1292     for pkg in $removed; do
1293       dialog_list="$dialog_list $pkg '' off"
1294     done
1295
1296     # user selects the packages to delete
1297     selection=$( mktemp /var/lib/carnet-upgrade/selection.XXXXXX )
1298     eval LC_MESSAGES=hr_HR dialog --nocancel --backtitle \""$title"\" \
1299       --checklist \""$msg_remove_initd"\" 20 75 6 $dialog_list 2>$selection
1300
1301     selected=$( tr -d \" < $selection )
1302     rm -f $selection
1303
1304     if [ "$selected" ]; then
1305       log "Purging packages: $selected"
1306       dpkg -P $selected
1307     fi
1308   fi
1309 }
1310
1311 free_space() {
1312   df --portability --block-size=1M "$1" | tail -1 | awk '{print $4}'
1313 }
1314
1315 download_size() {
1316   local size
1317   size=$(LC_ALL=C apt-get --yes --print-uris "$@" | grep '^Need to get ')
1318
1319   if [ $? -ne 0 ]; then
1320     log "Failed to get download size for 'apt-get $@'."
1321     return 1
1322   fi
1323
1324   size=${size#Need to get }
1325   size=${size%%B*}
1326
1327   size_to_mb "${size}B"
1328 }
1329
1330 installed_size() {
1331   local package size
1332   package=$1
1333   size=$(apt-cache show $package | grep '^Installed-Size:')
1334
1335   if [ $? -ne 0 ]; then
1336     log "Failed to get installed size for '$package'."
1337     return 1
1338   fi
1339
1340   size=${size#*: }
1341
1342   size_to_mb "${size}kB"
1343 }
1344
1345 size_to_mb() {
1346   local size
1347   size=$1
1348   if [ -z "$size" ]; then
1349     size=0;
1350   fi
1351
1352   if [ "${size%kB}" != "$size" ]; then
1353     size=$(round ${size%kB})
1354     size=$(($size/1024+1))
1355   elif [ "${size%MB}" != "$size" ]; then
1356     size=$(round ${size%MB})
1357   elif [ "${size%GB}" != "$size" ]; then
1358     size=$(round ${size%GB})
1359     size=$(($size*1024))
1360   elif [ "${size%[0-9]B}" != "$size" ]; then
1361     size=$(round ${size%B})
1362     size=$(($size/1024/1024+1))
1363   else
1364     log "unrecognized size unit: $size"
1365     return 1
1366   fi
1367
1368   echo $size
1369 }
1370
1371 round() {
1372   local num
1373   num=$1
1374
1375   if [ "${num%.*}" != "$num" ]; then
1376     num=${num%.*}
1377     num=$(($num+1))
1378   fi
1379
1380   echo $num
1381 }
1382
1383 # make sure carnet-upgrade doesn't get upgraded until the end
1384 hold_carnet_upgrade() {
1385   echo carnet-upgrade hold | dpkg --set-selections
1386 }
1387
1388 release_carnet_upgrade() {
1389   echo carnet-upgrade install | dpkg --set-selections
1390 }