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

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

If we cannot determine file size, set to 0

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