source: src-sh/libsh/functions.sh @ 02f5b7c

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since 02f5b7c was 2bba3b7, checked in by Kris Moore <kris@…>, 20 months ago

Don't exit_err on a download_cache_packages call, let the calling program
handle that its own way

  • Property mode set to 100755
File size: 15.2 KB
Line 
1#!/bin/sh
2# Functions we can source for pc-bsd scripts
3# Author: Kris Moore
4# Copyright: 2012
5# License: BSD
6##############################################################
7
8PCBSD_ETCCONF="/usr/local/etc/pcbsd.conf"
9
10download_cache_packages()
11{
12  if [ ! -e "/usr/local/etc/pkg.conf" ] ; then
13    exit_err "No /usr/local/etc/pkg.conf!"
14  fi
15
16  # Tickle pkg update first
17  pkg-static update
18  local ARCH="`uname -m`"
19
20  ${1} > /tmp/.pkgUpList.$$
21
22  while read line
23  do
24     lTag=`echo $line | awk '{print $1}'` 
25     case $lTag in
26    Upgrading|Downgrading) pkgList="`echo $line | awk '{print $2}' | sed 's|:||g'`-`echo $line | awk '{print $5}'`.txz $pkgList" ;;
27 Reinstalling) pkgList="`echo $line | awk '{print $2}'`.txz $pkgList" ;;
28   Installing) pkgList="`echo $line | awk '{print $2}' | sed 's|:||g'`-`echo $line | awk '{print $3}'`.txz $pkgList" ;;
29                    *) continue ;;
30     esac
31
32  done < /tmp/.pkgUpList.$$
33  rm /tmp/.pkgUpList.$$
34
35  # Get the PKG_CACHEDIR
36  PKG_CACHEDIR="/var/cache/pkg"
37  cat /usr/local/etc/pkg.conf | grep -q "^PKG_CACHEDIR:"
38  if [ $? -eq 0 ] ; then
39    PKG_CACHEDIR="`grep '^PKG_CACHEDIR:' /usr/local/etc/pkg.conf | awk '{print $2}'`"
40  fi
41  if [ -z "$PKG_CACHEDIR" ] ; then
42     exit_err "Failed getting PKG_CACHEDIR"
43  fi
44  export PKG_CACHEDIR
45
46  PKGREL=`uname -r | cut -d '-' -f 1-2`
47
48  # Where are the packages on our mirrors?
49  pkgUrl="/packages/${PKGREL}/${ARCH}"
50
51  if [ ! -d "$PKG_CACHEDIR/All" ] ; then
52     mkdir -p ${PKG_CACHEDIR}/All
53  fi
54
55  for i in $pkgList
56  do
57    # Does the package already exist?
58    if [ -e "${PKG_CACHEDIR}/All/${i}" ] ; then 
59        # For now just remove the cached file
60        # Once bapt gives us a working rquery string, we can add a check here to skip
61        # re-downloading already valid files
62        #pName=`echo $i | sed 's|.txz$||g'`
63        # Check the sizes
64        #eSize=`pkg rquery "%sb" $pName`
65        #dSize=`ls -al `
66        rm ${PKG_CACHEDIR}/All/${i} ;
67    fi
68    get_file_from_mirrors "${pkgUrl}/All/${i}" "${PKG_CACHEDIR}/All/${i}"
69    if [ $? -ne 0 ] ; then
70      echo "Failed downloading: /${pkgUrl}/All/${i}"
71      return 1
72    fi
73  done
74  return 0
75}
76
77get_mirror() {
78
79  # Check if we already looked up a mirror we can keep using
80  if [ -n "$CACHED_PCBSD_MIRROR" ] ; then
81     VAL="$CACHED_PCBSD_MIRROR"
82     export VAL
83     return
84  fi
85
86  # Set the mirror URL
87  VAL="`cat ${PCBSD_ETCCONF} 2>/dev/null | grep 'PCBSD_MIRROR: ' | sed 's|PCBSD_MIRROR: ||g'`"
88  if [ -n "$VAL" ] ; then
89     echo "Using mirror: $VAL"
90     CACHED_PCBSD_MIRROR="$VAL"
91     export VAL CACHED_PCBSD_MIRROR
92     return
93  fi
94
95  echo "Getting regional mirror..."
96  . /etc/profile
97
98  # No URL? Lets get one from the master server
99  local mFile="${HOME}/.mirrorUrl.$$"
100  touch $mFile
101  fetch -o $mFile http://getmirror.pcbsd.org >/dev/null 2>/dev/null
102  VAL="`cat $mFile | grep 'URL: ' | sed 's|URL: ||g'`"
103  rm $mFile
104  if [ -n "$VAL" ] ; then
105     echo "Using mirror: $VAL"
106     CACHED_PCBSD_MIRROR="$VAL"
107     export VAL CACHED_PCBSD_MIRROR
108     return
109  fi
110
111  # Still no mirror? Lets try the PC-BSD FTP server...
112  VAL="ftp://ftp.pcbsd.org/pub/mirror"
113  CACHED_PCBSD_MIRROR="$VAL"
114  export VAL CACHED_PCBSD_MIRROR
115  echo "Using mirror: $VAL"
116  return 
117}
118
119# Function which returns the installed list of PC-BSD mirrors for use
120# with the aria2c command
121# Will return just a single mirror, if the user has manually specified one
122# in /usr/local/etc/pcbsd.conf
123get_aria_mirror_list()
124{
125  if [ -z $1 ] ; then
126     exit_err "Need to supply file to grab from mirrors..."
127  fi
128
129  # Set the mirror URL
130  local VAL="`cat ${PCBSD_ETCCONF} 2>/dev/null | grep 'PCBSD_MIRROR: ' | sed 's|PCBSD_MIRROR: ||g'`"
131  if [ -n "$VAL" ] ; then
132     echo "${VAL}${1}"
133     return
134  fi
135
136  if [ ! -e "/usr/local/share/pcbsd/conf/pcbsd-mirrors" ] ; then
137     exit_err "Missing mirror list: /usr/local/share/pcbsd/conf/pcbsd-mirrors"
138  fi
139
140  # Build the mirror list
141  while read line
142  do
143    VAL="$VAL ${line}${1}"
144  done < /usr/local/share/pcbsd/conf/pcbsd-mirrors
145  echo ${VAL}
146}
147
148# Function to download a file from the pcbsd mirrors
149# Arg1 = Remote File URL
150# Arg2 = Where to save file
151get_file_from_mirrors()
152{
153   _rf="${1}"
154   _lf="${2}"
155
156   # Get any proxy information
157   . /etc/profile
158
159   # Split up the dir / file name
160   local aDir=`dirname $_lf`
161   local aFile=`basename $_lf`
162
163   # Server status flag
164   if [ `id -u` = "0" ] ; then
165      aStatFile=/root/.pcbsd-aria-stat
166   else
167      aStatFile=${HOME}/.pcbsd-aria-stat
168   fi
169
170   if [ -e "$aStatFile" ] ; then
171     local aStat="--server-stat-of=$aStatFile --server-stat-if=$aStatFile --uri-selector=adaptive --server-stat-timeout=864000"
172   else
173     local aStat="--server-stat-of=$aStatFile --uri-selector=adaptive"
174   fi
175   touch $aStatFile
176
177   # Get mirror list
178   local mirrorList="$(get_aria_mirror_list $1)"
179   
180   # Running from a non GUI?
181   if [ "$GUI_FETCH_PARSING" != "YES" -a "$PBI_FETCH_PARSING" != "YES" -a -z "$PCFETCHGUI" ] ; then
182      aria2c -k 5M ${aStat} --check-certificate=false --file-allocation=none -d "${aDir}" -o "${aFile}" ${mirrorList}
183      return $?
184   fi
185
186   echo "FETCH: ${_rf}"
187
188   # Doing a front-end download, parse the output of fetch
189   _eFile="/tmp/.fetch-exit.$$"
190   fetch -s "`echo ${mirrorList} | awk '{print $1}'`" > /tmp/.fetch-size.$$ 2>/dev/null
191   _fSize=`cat /tmp/.fetch-size.$$ 2>/dev/null`
192   _fSize="`expr ${_fSize} / 1024 2>/dev/null`"
193   rm "/tmp/.fetch-size.$$" 2>/dev/null
194   _time=1
195   if [ -z "$_fSize" ] ; then _fSize=0; fi
196
197   ( aria2c -o ${aFile} -d ${aDir} -k 5M ${aStat} --check-certificate=false --file-allocation=none ${mirrorList} >/dev/null 2>/dev/null ; echo "$?" > ${_eFile} ) &
198   FETCH_PID=$!
199   while :
200   do
201      if [ -e "${_lf}" ] ; then
202         _dSize=`du -k ${_lf} | tr -d '\t' | cut -d '/' -f 1`
203         if [ $(is_num "$_dSize") ] ; then
204            if [ ${_fSize} -lt ${_dSize} ] ; then _dSize="$_fSize" ; fi
205            _kbs=`expr ${_dSize} \/ $_time`
206            echo "SIZE: ${_fSize} DOWNLOADED: ${_dSize} SPEED: ${_kbs} KB/s"
207         fi
208      fi
209
210      # Make sure download isn't finished
211      jobs -l >/tmp/.jobProcess.$$
212      cat /tmp/.jobProcess.$$ | awk '{print $3}' | grep -q ${FETCH_PID}
213      if [ "$?" != "0" ] ; then rm /tmp/.jobProcess.$$ ; break ; fi
214      sleep 1
215      _time=`expr $_time + 1`
216   done
217
218   _err="`cat ${_eFile}`"
219   rm ${_eFile} 2>/dev/null
220   if [ "$_err" = "0" ]; then echo "FETCHDONE" ; fi
221   unset FETCH_PID
222   return $_err
223
224}
225
226# Function to download a file from remote using fetch
227# Arg1 = Remote File URL
228# Arg2 = Where to save file
229# Arg3 = Number of attempts to make before failing
230get_file() {
231
232        _rf="${1}"
233        _lf="${2}"
234        _ftries=${3}
235        if [ -z "$_ftries" ] ; then _ftries=3; fi
236
237        # Get any proxy information
238        . /etc/profile
239
240        if [ -e "${_lf}" ] ; then
241                echo "Resuming download of: ${_lf}"
242        fi
243
244        if [ "$GUI_FETCH_PARSING" != "YES" -a -z "$PCFETCHGUI" ] ; then
245                fetch -r -o "${_lf}" "${_rf}"
246                _err=$?
247        else
248                echo "FETCH: ${_rf}"
249
250                # Doing a front-end download, parse the output of fetch
251                _eFile="/tmp/.fetch-exit.$$"
252                fetch -s "${_rf}" > /tmp/.fetch-size.$$ 2>/dev/null
253                _fSize=`cat /tmp/.fetch-size.$$ 2>/dev/null`
254                _fSize="`expr ${_fSize} / 1024 2>/dev/null`"
255                rm "/tmp/.fetch-size.$$" 2>/dev/null
256                _time=1
257
258                ( fetch -r -o "${_lf}" "${_rf}" >/dev/null 2>/dev/null ; echo "$?" > ${_eFile} ) &
259                FETCH_PID=`ps -auwwwx | grep -v grep | grep "fetch -r -o ${_lf}" | awk '{print $2}'`
260                while :
261                do
262                        if [ -e "${_lf}" ] ; then
263                                _dSize=`du -k ${_lf} | tr -d '\t' | cut -d '/' -f 1`
264                                if [ $(is_num "$_dSize") ] ; then
265                                        if [ ${_fSize} -lt ${_dSize} ] ; then _dSize="$_fSize" ; fi
266                                        _kbs=`expr ${_dSize} \/ $_time`
267                                        echo "SIZE: ${_fSize} DOWNLOADED: ${_dSize} SPEED: ${_kbs} KB/s"
268                                fi
269                        fi
270
271                        # Make sure download isn't finished
272                        ps -p $FETCH_PID >/dev/null 2>/dev/null
273                        if [ "$?" != "0" ] ; then break ; fi
274                        sleep 2
275                        _time=`expr $_time + 2`
276                done
277
278                _err="`cat ${_eFile}`"
279                rm ${_eFile} 2>/dev/null
280                if [ "$_err" = "0" ]; then echo "FETCHDONE" ; fi
281                unset FETCH_PID
282        fi
283
284        echo ""
285        if [ $_err -ne 0 -a $_ftries -gt 0 ] ; then
286                sleep 30
287                _ftries=`expr $_ftries - 1`
288
289                # Remove the local file if we failed
290                if [ -e "${_lf}" ]; then rm "${_lf}"; fi
291
292                get_file "${_rf}" "${_lf}" $_ftries     
293                _err=$?
294        fi
295        return $_err
296}
297
298# Check if a value is a number
299is_num()
300{
301        expr $1 + 1 2>/dev/null
302        return $?
303}
304
305# Exit with a error message
306exit_err() {
307        if [ -n "${LOGFILE}" ] ; then
308           echo "ERROR: $*" >> ${LOGFILE}
309        fi
310        echo >&2 "ERROR: $*"
311        exit 1
312}
313
314
315### Print an error on STDERR and bail out
316printerror() {
317  exit_err $*
318}
319
320
321# Check if the target directory is on ZFS
322# Arg1 = The dir to check
323# Arg2 = If set to 1, don't dig down to lower level directory
324isDirZFS() {
325  local _chkDir="$1"
326  while :
327  do
328     # Is this dir a ZFS mount
329     mount | grep -w "on $_chkDir " | grep -qw "(zfs," && return 0
330
331     # If this directory is mounted, but NOT ZFS
332     if [ "$2" != "1" ] ; then
333       mount | grep -qw "on $_chkDir " && return 1
334     fi
335     
336     # Quit if not walking down
337     if [ "$2" = "1" ] ; then return 1 ; fi
338 
339     if [ "$_chkDir" = "/" ] ; then break ; fi
340     _chkDir=`dirname $_chkDir`
341  done
342 
343  return 1
344}
345
346# Gets the mount-point of a particular zpool / dataset
347# Arg1 = zpool to check
348getZFSMount() {
349  local zpool="$1"
350  local mnt=`mount | grep "^${zpool} on" | grep "(zfs," | awk '{print $3}'`
351  if [ -n "$mnt" ] ; then
352     echo "$mnt"
353     return 0
354  fi
355  return 1
356}
357
358# Get the ZFS dataset of a particular directory
359getZFSDataset() {
360  local _chkDir="$1"
361  while :
362  do
363    local zData=`mount | grep " on ${_chkDir} " | grep "(zfs," | awk '{print $1}'`
364    if [ -n "$zData" ] ; then
365       echo "$zData"
366       return 0
367    fi
368    if [ "$2" != "rec" ] ; then return 1 ; fi
369    if [ "$_chkDir" = "/" ] ; then return 1 ; fi
370    _chkDir=`dirname $_chkDir`
371  done
372  return 1
373}
374
375# Get the ZFS tank name for a directory
376# Arg1 = Directory to check
377getZFSTank() {
378  local _chkDir="$1"
379
380  _chkdir=${_chkDir%/}
381  while :
382  do
383     zpath=`zfs list | awk -v path="${_chkDir}" '$5 == path { print $1 }'`
384     if [ -n "${zpath}" ] ; then
385        echo $zpath | cut -f1 -d '/'
386        return 0
387     fi
388
389     if [ "$_chkDir" = "/" ] ; then return 1 ; fi
390     _chkDir=`dirname $_chkDir`
391  done
392
393  return 1
394}
395
396# Get the mountpoint for a ZFS name
397# Arg1 = name
398getZFSMountpoint() {
399   local _chkName="${1}"
400   if [ -z "${_chkName}" ]; then return 1 ; fi
401
402   zfs list "${_chkName}" | tail -1 | awk '{ print $5 }'
403}
404
405# Get the ZFS relative path for a path
406# Arg1 = Path
407getZFSRelativePath() {
408   local _chkDir="${1}"
409   local _tank=`getZFSTank "$_chkDir"`
410   local _mp=`getZFSMountpoint "${_tank}"`
411
412   if [ -z "${_tank}" ] ; then return 1 ; fi
413
414   local _name="${_chkDir#${_mp}}"
415   echo "${_name}"
416   return 0
417}
418
419# Check if an address is IPv6
420isV6() {
421  echo ${1} | grep -q ":"
422  return $?
423}
424   
425# Is a mount point, or any of its parent directories, a symlink?
426is_symlinked_mountpoint()
427{
428        local _dir
429        _dir=$1
430        [ -L "$_dir" ] && return 0
431        [ "$_dir" = "/" ] && return 1
432        is_symlinked_mountpoint `dirname $_dir`
433        return $?
434}
435
436# Function to ask the user to press Return to continue
437rtn()
438{
439  echo -e "Press ENTER to continue\c";
440  read garbage
441};
442
443# Function to check if an IP address passes a basic sanity test
444check_ip()
445{
446  ip="$1"
447 
448  # If this is a V6 address, skip validation for now
449  isV6 "${ip}"
450  if [ $? -eq 0 ] ; then return ; fi
451
452  # Check if we can cut this IP into the right segments
453  SEG="`echo $ip | cut -d '.' -f 1 2>/dev/null`"
454  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
455  if [ "$?" != "0" ]
456  then
457     return 1
458  fi
459  if [ $SEG -gt 255 -o $SEG -lt 0 ]
460  then
461     return 1
462  fi
463 
464  # Second segment
465  SEG="`echo $ip | cut -d '.' -f 2 2>/dev/null`"
466  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
467  if [ "$?" != "0" ]
468  then
469     return 1
470  fi
471  if [ $SEG -gt 255 -o $SEG -lt 0 ]
472  then
473     return 1
474  fi
475
476  # Third segment
477  SEG="`echo $ip | cut -d '.' -f 3 2>/dev/null`"
478  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
479  if [ "$?" != "0" ]
480  then
481     return 1
482  fi
483  if [ $SEG -gt 255 -o $SEG -lt 0 ]
484  then
485     return 1
486  fi
487 
488  # Fourth segment
489  SEG="`echo $ip | cut -d '.' -f 4 2>/dev/null`"
490  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
491  if [ "$?" != "0" ]
492  then
493     return 1
494  fi
495  if [ $SEG -gt 255 -o $SEG -lt 0 ]
496  then
497     return 1
498  fi
499
500  return 0
501};
502
503check_pkg_conflicts()
504{
505  # Lets test if we have any conflicts
506  pkg-static ${1} 2>/tmp/.pkgConflicts.$$ >/tmp/.pkgConflicts.$$
507  if [ $? -eq 0 ] ; then rm /tmp/.pkgConflicts.$$ ; return ; fi
508 
509  # Found conflicts, suprise suprise, yet another reason I hate packages
510  # Lets start building a list of the old packages we can prompt to remove
511
512  # Nice ugly sed line, sure this can be neater
513  cat /tmp/.pkgConflicts.$$ | grep 'WARNING: locally installed' \
514        | sed 's|.*installed ||g' | sed 's| conflicts.*||g' | sort | uniq \
515        > /tmp/.pkgConflicts.$$.2
516  while read line
517  do
518    cList="$line $cList"
519  done < /tmp/.pkgConflicts.$$.2
520  rm /tmp/.pkgConflicts.$$.2
521  rm /tmp/.pkgConflicts.$$
522
523  if [ "$GUI_FETCH_PARSING" != "YES" -a "$PBI_FETCH_PARSING" != "YES" -a -z "$PCFETCHGUI" ] ; then
524        echo "The following packages will conflict with your pkg command:"
525        echo "-------------------------------------"
526        echo "$cList" | more
527        echo "Do you wish to remove them automatically?"
528        echo -e "Default yes: (y/n)\c"
529        read tmp
530        if [ "$tmp" != "y" -a "$tmp" != "Y" ] ; then return 1 ; fi
531  else
532        echo "PKGCONFLICTS: $cList"
533        echo "PKGREPLY: /tmp/pkgans.$$"
534        while :
535        do
536          if [ -e "/tmp/pkgans.$$" ] ; then
537            ans=`cat /tmp/pkgans.$$`
538            if [ "$ans" = "yes" ] ; then
539               break
540            else
541               return 1
542            fi
543          fi
544          sleep 3
545        done
546  fi
547
548  # Lets auto-resolve these bad-boys
549  # Right now the logic is pretty simple, you conflict, you die
550  for bPkg in $cList
551  do
552     # Nuked!
553     echo "Removing conflicting package: $bPkg"
554     pkg delete -q -y -f ${bPkg}
555  done
556
557  # Lets test if we still have any conflicts
558  pkg-static ${1} 2>/dev/null >/dev/null
559  if [ $? -eq 0 ] ; then return 0; fi
560
561  # Crapola, we still have conflicts, lets warn and bail
562  echo "ERROR: pkg ${1} is still reporting conflicts... Resolve these manually and try again"
563  return 1
564}
565
566# Run the first boot wizard
567# Should be called from a .xinitrc script, after fluxbox is already running
568run_firstboot()
569{
570  # Is the trigger file set?
571  if [ ! -e "/var/.pcbsd-firstgui" ] ; then return; fi
572
573  # Set all our path variables
574  PATH="/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/bin:/usr/local/sbin"
575  HOME="/root"
576  export PATH HOME
577
578  # Unset the PROGDIR variable
579  PROGDIR=""
580  export PROGDIR
581
582  if [ -e "/root/.xprofile" ] ; then . /root/.xprofile ; fi
583
584  # Figure out which intro video to play
585  res=`xdpyinfo | grep dimensions: | awk "{print $2}"`
586  h=`echo $res | cut -d "x" -f 1`
587  w=`echo $res | cut -d "x" -f 2`
588  h=`expr 100 \* $h`
589  ratio=`expr $h \/ $w | cut -c 1-2`
590  case $ratio in
591    13) mov="PCBSD9_4-3_UXGA.flv";;
592    16) mov="PCBSD9_16-10_WUXGA.flv";;
593    17) mov="PCBSD9_16-9_1080p.flv";;
594     *) mov="PCBSD9_4-3_UXGA.flv";;
595  esac
596
597  # Play the video now
598  mplayer -fs -nomouseinput -zoom /usr/local/share/pcbsd/movies/$mov
599
600  # Setting a language
601  if [ -e "/etc/pcbsd-lang" ] ; then
602    LANG=`cat /etc/pcbsd-lang`
603    export LANG
604  fi
605
606  # Start first-boot wizard
607  /usr/local/bin/pc-firstboot
608  if [ $? -eq 0 ] ; then
609    rm /var/.pcbsd-firstgui
610  fi
611}
Note: See TracBrowser for help on using the repository browser.