source: src-sh/libsh/functions.sh @ 1620346

9.1-release9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 1620346 was 1620346, checked in by Kris Moore <kris@…>, 15 months ago

Initial import of PC-BSD /current/ SVN repo

  • Property mode set to 100755
File size: 11.7 KB
RevLine 
[1620346]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  # Where are the packages on our mirrors?
47  pkgUrl="/packages/`uname -r`/${ARCH}"
48
49  if [ ! -d "$PKG_CACHEDIR/All" ] ; then
50     mkdir -p ${PKG_CACHEDIR}/All
51  fi
52
53  for i in $pkgList
54  do
55    if [ -e "${PKG_CACHEDIR}/All/${i}" ] ; then rm ${PKG_CACHEDIR}/All/${i} ; fi
56    get_file_from_mirrors "${pkgUrl}/All/${i}" "${PKG_CACHEDIR}/All/${i}"
57    if [ $? -ne 0 ] ; then
58      exit_err "Failed downloading: /${pkgUrl}/All/${i}"
59    fi
60  done
61}
62
63get_mirror() {
64
65  # Check if we already looked up a mirror we can keep using
66  if [ -n "$CACHED_PCBSD_MIRROR" ] ; then
67     VAL="$CACHED_PCBSD_MIRROR"
68     export VAL
69     return
70  fi
71
72  # Set the mirror URL
73  VAL="`cat ${PCBSD_ETCCONF} 2>/dev/null | grep 'PCBSD_MIRROR: ' | sed 's|PCBSD_MIRROR: ||g'`"
74  if [ -n "$VAL" ] ; then
75     echo "Using mirror: $VAL"
76     CACHED_PCBSD_MIRROR="$VAL"
77     export VAL CACHED_PCBSD_MIRROR
78     return
79  fi
80
81  echo "Getting regional mirror..."
82  . /etc/profile
83
84  # No URL? Lets get one from the master server
85  local mFile="${HOME}/.mirrorUrl.$$"
86  touch $mFile
87  fetch -o $mFile http://getmirror.pcbsd.org >/dev/null 2>/dev/null
88  VAL="`cat $mFile | grep 'URL: ' | sed 's|URL: ||g'`"
89  rm $mFile
90  if [ -n "$VAL" ] ; then
91     echo "Using mirror: $VAL"
92     CACHED_PCBSD_MIRROR="$VAL"
93     export VAL CACHED_PCBSD_MIRROR
94     return
95  fi
96
97  # Still no mirror? Lets try the PC-BSD FTP server...
98  VAL="ftp://ftp.pcbsd.org/pub/mirror"
99  CACHED_PCBSD_MIRROR="$VAL"
100  export VAL CACHED_PCBSD_MIRROR
101  echo "Using mirror: $VAL"
102  return 
103}
104
105# Function which returns the installed list of PC-BSD mirrors for use
106# with the aria2c command
107# Will return just a single mirror, if the user has manually specified one
108# in /usr/local/etc/pcbsd.conf
109get_aria_mirror_list()
110{
111  if [ -z $1 ] ; then
112     exit_err "Need to supply file to grab from mirrors..."
113  fi
114
115  # Set the mirror URL
116  local VAL="`cat ${PCBSD_ETCCONF} 2>/dev/null | grep 'PCBSD_MIRROR: ' | sed 's|PCBSD_MIRROR: ||g'`"
117  if [ -n "$VAL" ] ; then
118     echo "${VAL}${1}"
119     return
120  fi
121
122  if [ ! -e "/usr/local/share/pcbsd/conf/pcbsd-mirrors" ] ; then
123     exit_err "Missing mirror list: /usr/local/share/pcbsd/conf/pcbsd-mirrors"
124  fi
125
126  # Build the mirror list
127  while read line
128  do
129    VAL="$VAL ${line}${1}"
130  done < /usr/local/share/pcbsd/conf/pcbsd-mirrors
131  echo ${VAL}
132}
133
134# Function to download a file from the pcbsd mirrors
135# Arg1 = Remote File URL
136# Arg2 = Where to save file
137get_file_from_mirrors()
138{
139   _rf="${1}"
140   _lf="${2}"
141
142   # Get any proxy information
143   . /etc/profile
144
145   # Split up the dir / file name
146   local aDir=`dirname $_lf`
147   local aFile=`basename $_lf`
148
149   # Server status flag
150   local aStatFile=${HOME}/.pcbsd-aria-stat
151   if [ -e "$aStatFile" ] ; then
152     local aStat="--server-stat-of=$aStatFile --server-stat-if=$aStatFile --uri-selector=adaptive --server-stat-timeout=864000"
153   else
154     local aStat="--server-stat-of=$aStatFile --uri-selector=adaptive"
155   fi
156   touch $aStatFile
157
158   # Get mirror list
159   local mirrorList="$(get_aria_mirror_list $1)"
160   
161   # Running from a non GUI?
162   if [ "$GUI_FETCH_PARSING" != "YES" -a "$PBI_FETCH_PARSING" != "YES" -a -z "$PCFETCHGUI" ] ; then
163      aria2c -k 5M ${aStat} --check-certificate=false --file-allocation=none -d "${aDir}" -o "${aFile}" ${mirrorList}
164      return $?
165   fi
166
167   echo "FETCH: ${_rf}"
168
169   # Doing a front-end download, parse the output of fetch
170   _eFile="/tmp/.fetch-exit.$$"
171   fetch -s "`echo ${mirrorList} | awk '{print $1}'`" > /tmp/.fetch-size.$$ 2>/dev/null
172   _fSize=`cat /tmp/.fetch-size.$$ 2>/dev/null`
173   _fSize="`expr ${_fSize} / 1024 2>/dev/null`"
174   rm "/tmp/.fetch-size.$$" 2>/dev/null
175   _time=1
176
177   ( aria2c -o ${aFile} -d ${aDir} -k 5M ${aStat} --check-certificate=false --file-allocation=none ${mirrorList} >/dev/null 2>/dev/null ; echo "$?" > ${_eFile} ) &
178   FETCH_PID=`ps -auwwwx | grep -v grep | grep "aria2c -o ${aFile}" | awk '{print $2}'`
179   while :
180   do
181      if [ -e "${_lf}" ] ; then
182         _dSize=`du -k ${_lf} | tr -d '\t' | cut -d '/' -f 1`
183         if [ $(is_num "$_dSize") ] ; then
184            if [ ${_fSize} -lt ${_dSize} ] ; then _dSize="$_fSize" ; fi
185            _kbs=`expr ${_dSize} \/ $_time`
186            echo "SIZE: ${_fSize} DOWNLOADED: ${_dSize} SPEED: ${_kbs} KB/s"
187         fi
188      fi
189
190      # Make sure download isn't finished
191      ps -p $FETCH_PID >/dev/null 2>/dev/null
192      if [ "$?" != "0" ] ; then break ; fi
193      sleep 2
194      _time=`expr $_time + 2`
195   done
196
197   _err="`cat ${_eFile}`"
198   rm ${_eFile} 2>/dev/null
199   if [ "$_err" = "0" ]; then echo "FETCHDONE" ; fi
200   unset FETCH_PID
201   return $_err
202
203}
204
205# Function to download a file from remote using fetch
206# Arg1 = Remote File URL
207# Arg2 = Where to save file
208# Arg3 = Number of attempts to make before failing
209get_file() {
210
211        _rf="${1}"
212        _lf="${2}"
213        _ftries=${3}
214        if [ -z "$_ftries" ] ; then _ftries=3; fi
215
216        # Get any proxy information
217        . /etc/profile
218
219        if [ -e "${_lf}" ] ; then
220                echo "Resuming download of: ${_lf}"
221        fi
222
223        if [ "$GUI_FETCH_PARSING" != "YES" -a -z "$PCFETCHGUI" ] ; then
224                fetch -r -o "${_lf}" "${_rf}"
225                _err=$?
226        else
227                echo "FETCH: ${_rf}"
228
229                # Doing a front-end download, parse the output of fetch
230                _eFile="/tmp/.fetch-exit.$$"
231                fetch -s "${_rf}" > /tmp/.fetch-size.$$ 2>/dev/null
232                _fSize=`cat /tmp/.fetch-size.$$ 2>/dev/null`
233                _fSize="`expr ${_fSize} / 1024 2>/dev/null`"
234                rm "/tmp/.fetch-size.$$" 2>/dev/null
235                _time=1
236
237                ( fetch -r -o "${_lf}" "${_rf}" >/dev/null 2>/dev/null ; echo "$?" > ${_eFile} ) &
238                FETCH_PID=`ps -auwwwx | grep -v grep | grep "fetch -r -o ${_lf}" | awk '{print $2}'`
239                while :
240                do
241                        if [ -e "${_lf}" ] ; then
242                                _dSize=`du -k ${_lf} | tr -d '\t' | cut -d '/' -f 1`
243                                if [ $(is_num "$_dSize") ] ; then
244                                        if [ ${_fSize} -lt ${_dSize} ] ; then _dSize="$_fSize" ; fi
245                                        _kbs=`expr ${_dSize} \/ $_time`
246                                        echo "SIZE: ${_fSize} DOWNLOADED: ${_dSize} SPEED: ${_kbs} KB/s"
247                                fi
248                        fi
249
250                        # Make sure download isn't finished
251                        ps -p $FETCH_PID >/dev/null 2>/dev/null
252                        if [ "$?" != "0" ] ; then break ; fi
253                        sleep 2
254                        _time=`expr $_time + 2`
255                done
256
257                _err="`cat ${_eFile}`"
258                rm ${_eFile} 2>/dev/null
259                if [ "$_err" = "0" ]; then echo "FETCHDONE" ; fi
260                unset FETCH_PID
261        fi
262
263        echo ""
264        if [ $_err -ne 0 -a $_ftries -gt 0 ] ; then
265                sleep 30
266                _ftries=`expr $_ftries - 1`
267
268                # Remove the local file if we failed
269                if [ -e "${_lf}" ]; then rm "${_lf}"; fi
270
271                get_file "${_rf}" "${_lf}" $_ftries     
272                _err=$?
273        fi
274        return $_err
275}
276
277# Check if a value is a number
278is_num()
279{
280        expr $1 + 1 2>/dev/null
281        return $?
282}
283
284# Exit with a error message
285exit_err() {
286        if [ -n "${LOGFILE}" ] ; then
287           echo "ERROR: $*" >> ${LOGFILE}
288        fi
289        echo >&2 "ERROR: $*"
290        exit 1
291}
292
293
294### Print an error on STDERR and bail out
295printerror() {
296  exit_err $*
297}
298
299
300# Check if the target directory is on ZFS
301# Arg1 = The dir to check
302# Arg2 = If set to 1, don't dig down to lower level directory
303isDirZFS() {
304  local _chkDir="$1"
305  while :
306  do
307     # Is this dir a ZFS mount
308     mount | grep -w "on $_chkDir " | grep -qw "(zfs," && return 0
309
310     # If this directory is mounted, but NOT ZFS
311     if [ "$2" != "1" ] ; then
312       mount | grep -qw "on $_chkDir " && return 1
313     fi
314     
315     # Quit if not walking down
316     if [ "$2" = "1" ] ; then return 1 ; fi
317 
318     if [ "$_chkDir" = "/" ] ; then break ; fi
319     _chkDir=`dirname $_chkDir`
320  done
321 
322  return 1
323}
324
325# Gets the mount-point of a particular zpool / dataset
326# Arg1 = zpool to check
327getZFSMount() {
328  local zpool="$1"
329  local mnt=`mount | grep "^${zpool} on" | grep "(zfs," | awk '{print $3}'`
330  if [ -n "$mnt" ] ; then
331     echo "$mnt"
332     return 0
333  fi
334  return 1
335}
336
337# Get the ZFS dataset of a particular directory
338getZFSDataset() {
339  local _chkDir="$1"
340  while :
341  do
342    local zData=`mount | grep " on ${_chkDir} " | grep "(zfs," | awk '{print $1}'`
343    if [ -n "$zData" ] ; then
344       echo "$zData"
345       return 0
346    fi
347    if [ "$2" != "rec" ] ; then return 1 ; fi
348    if [ "$_chkDir" = "/" ] ; then return 1 ; fi
349    _chkDir=`dirname $_chkDir`
350  done
351  return 1
352}
353
354# Get the ZFS tank name for a directory
355# Arg1 = Directory to check
356getZFSTank() {
357  local _chkDir="$1"
358
359  _chkdir=${_chkDir%/}
360  while :
361  do
362     zpath=`zfs list | awk -v path="${_chkDir}" '$5 == path { print $1 }'`
363     if [ -n "${zpath}" ] ; then
364        echo $zpath | cut -f1 -d '/'
365        return 0
366     fi
367
368     if [ "$_chkDir" = "/" ] ; then return 1 ; fi
369     _chkDir=`dirname $_chkDir`
370  done
371
372  return 1
373}
374
375# Get the mountpoint for a ZFS name
376# Arg1 = name
377getZFSMountpoint() {
378   local _chkName="${1}"
379   if [ -z "${_chkName}" ]; then return 1 ; fi
380
381   zfs list "${_chkName}" | tail -1 | awk '{ print $5 }'
382}
383
384# Get the ZFS relative path for a path
385# Arg1 = Path
386getZFSRelativePath() {
387   local _chkDir="${1}"
388   local _tank=`getZFSTank "$_chkDir"`
389   local _mp=`getZFSMountpoint "${_tank}"`
390
391   if [ -z "${_tank}" ] ; then return 1 ; fi
392
393   local _name="${_chkDir#${_mp}}"
394   echo "${_name}"
395   return 0
396}
397
398# Check if an address is IPv6
399isV6() {
400  echo ${1} | grep -q ":"
401  return $?
402}
403   
404# Is a mount point, or any of its parent directories, a symlink?
405is_symlinked_mountpoint()
406{
407        local _dir
408        _dir=$1
409        [ -L "$_dir" ] && return 0
410        [ "$_dir" = "/" ] && return 1
411        is_symlinked_mountpoint `dirname $_dir`
412        return $?
413}
414
415# Function to ask the user to press Return to continue
416rtn()
417{
418  echo -e "Press ENTER to continue\c";
419  read garbage
420};
421
422# Function to check if an IP address passes a basic sanity test
423check_ip()
424{
425  ip="$1"
426 
427  # If this is a V6 address, skip validation for now
428  isV6 "${ip}"
429  if [ $? -eq 0 ] ; then return ; fi
430
431  # Check if we can cut this IP into the right segments
432  SEG="`echo $ip | cut -d '.' -f 1 2>/dev/null`"
433  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
434  if [ "$?" != "0" ]
435  then
436     return 1
437  fi
438  if [ $SEG -gt 255 -o $SEG -lt 0 ]
439  then
440     return 1
441  fi
442 
443  # Second segment
444  SEG="`echo $ip | cut -d '.' -f 2 2>/dev/null`"
445  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
446  if [ "$?" != "0" ]
447  then
448     return 1
449  fi
450  if [ $SEG -gt 255 -o $SEG -lt 0 ]
451  then
452     return 1
453  fi
454
455  # Third segment
456  SEG="`echo $ip | cut -d '.' -f 3 2>/dev/null`"
457  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
458  if [ "$?" != "0" ]
459  then
460     return 1
461  fi
462  if [ $SEG -gt 255 -o $SEG -lt 0 ]
463  then
464     return 1
465  fi
466 
467  # Fourth segment
468  SEG="`echo $ip | cut -d '.' -f 4 2>/dev/null`"
469  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
470  if [ "$?" != "0" ]
471  then
472     return 1
473  fi
474  if [ $SEG -gt 255 -o $SEG -lt 0 ]
475  then
476     return 1
477  fi
478
479  return 0
480};
Note: See TracBrowser for help on using the repository browser.