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

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

Fix a bug setting the right URL for fetching from mirrors when
the uname -r has a -pX number at the end

  • 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
179   ( aria2c -o ${aFile} -d ${aDir} -k 5M ${aStat} --check-certificate=false --file-allocation=none ${mirrorList} >/dev/null 2>/dev/null ; echo "$?" > ${_eFile} ) &
180   FETCH_PID=`ps -auwwwx | grep -v grep | grep "aria2c -o ${aFile}" | awk '{print $2}'`
181   while :
182   do
183      if [ -e "${_lf}" ] ; then
184         _dSize=`du -k ${_lf} | tr -d '\t' | cut -d '/' -f 1`
185         if [ $(is_num "$_dSize") ] ; then
186            if [ ${_fSize} -lt ${_dSize} ] ; then _dSize="$_fSize" ; fi
187            _kbs=`expr ${_dSize} \/ $_time`
188            echo "SIZE: ${_fSize} DOWNLOADED: ${_dSize} SPEED: ${_kbs} KB/s"
189         fi
190      fi
191
192      # Make sure download isn't finished
193      ps -p $FETCH_PID >/dev/null 2>/dev/null
194      if [ "$?" != "0" ] ; then break ; fi
195      sleep 2
196      _time=`expr $_time + 2`
197   done
198
199   _err="`cat ${_eFile}`"
200   rm ${_eFile} 2>/dev/null
201   if [ "$_err" = "0" ]; then echo "FETCHDONE" ; fi
202   unset FETCH_PID
203   return $_err
204
205}
206
207# Function to download a file from remote using fetch
208# Arg1 = Remote File URL
209# Arg2 = Where to save file
210# Arg3 = Number of attempts to make before failing
211get_file() {
212
213        _rf="${1}"
214        _lf="${2}"
215        _ftries=${3}
216        if [ -z "$_ftries" ] ; then _ftries=3; fi
217
218        # Get any proxy information
219        . /etc/profile
220
221        if [ -e "${_lf}" ] ; then
222                echo "Resuming download of: ${_lf}"
223        fi
224
225        if [ "$GUI_FETCH_PARSING" != "YES" -a -z "$PCFETCHGUI" ] ; then
226                fetch -r -o "${_lf}" "${_rf}"
227                _err=$?
228        else
229                echo "FETCH: ${_rf}"
230
231                # Doing a front-end download, parse the output of fetch
232                _eFile="/tmp/.fetch-exit.$$"
233                fetch -s "${_rf}" > /tmp/.fetch-size.$$ 2>/dev/null
234                _fSize=`cat /tmp/.fetch-size.$$ 2>/dev/null`
235                _fSize="`expr ${_fSize} / 1024 2>/dev/null`"
236                rm "/tmp/.fetch-size.$$" 2>/dev/null
237                _time=1
238
239                ( fetch -r -o "${_lf}" "${_rf}" >/dev/null 2>/dev/null ; echo "$?" > ${_eFile} ) &
240                FETCH_PID=`ps -auwwwx | grep -v grep | grep "fetch -r -o ${_lf}" | awk '{print $2}'`
241                while :
242                do
243                        if [ -e "${_lf}" ] ; then
244                                _dSize=`du -k ${_lf} | tr -d '\t' | cut -d '/' -f 1`
245                                if [ $(is_num "$_dSize") ] ; then
246                                        if [ ${_fSize} -lt ${_dSize} ] ; then _dSize="$_fSize" ; fi
247                                        _kbs=`expr ${_dSize} \/ $_time`
248                                        echo "SIZE: ${_fSize} DOWNLOADED: ${_dSize} SPEED: ${_kbs} KB/s"
249                                fi
250                        fi
251
252                        # Make sure download isn't finished
253                        ps -p $FETCH_PID >/dev/null 2>/dev/null
254                        if [ "$?" != "0" ] ; then break ; fi
255                        sleep 2
256                        _time=`expr $_time + 2`
257                done
258
259                _err="`cat ${_eFile}`"
260                rm ${_eFile} 2>/dev/null
261                if [ "$_err" = "0" ]; then echo "FETCHDONE" ; fi
262                unset FETCH_PID
263        fi
264
265        echo ""
266        if [ $_err -ne 0 -a $_ftries -gt 0 ] ; then
267                sleep 30
268                _ftries=`expr $_ftries - 1`
269
270                # Remove the local file if we failed
271                if [ -e "${_lf}" ]; then rm "${_lf}"; fi
272
273                get_file "${_rf}" "${_lf}" $_ftries     
274                _err=$?
275        fi
276        return $_err
277}
278
279# Check if a value is a number
280is_num()
281{
282        expr $1 + 1 2>/dev/null
283        return $?
284}
285
286# Exit with a error message
287exit_err() {
288        if [ -n "${LOGFILE}" ] ; then
289           echo "ERROR: $*" >> ${LOGFILE}
290        fi
291        echo >&2 "ERROR: $*"
292        exit 1
293}
294
295
296### Print an error on STDERR and bail out
297printerror() {
298  exit_err $*
299}
300
301
302# Check if the target directory is on ZFS
303# Arg1 = The dir to check
304# Arg2 = If set to 1, don't dig down to lower level directory
305isDirZFS() {
306  local _chkDir="$1"
307  while :
308  do
309     # Is this dir a ZFS mount
310     mount | grep -w "on $_chkDir " | grep -qw "(zfs," && return 0
311
312     # If this directory is mounted, but NOT ZFS
313     if [ "$2" != "1" ] ; then
314       mount | grep -qw "on $_chkDir " && return 1
315     fi
316     
317     # Quit if not walking down
318     if [ "$2" = "1" ] ; then return 1 ; fi
319 
320     if [ "$_chkDir" = "/" ] ; then break ; fi
321     _chkDir=`dirname $_chkDir`
322  done
323 
324  return 1
325}
326
327# Gets the mount-point of a particular zpool / dataset
328# Arg1 = zpool to check
329getZFSMount() {
330  local zpool="$1"
331  local mnt=`mount | grep "^${zpool} on" | grep "(zfs," | awk '{print $3}'`
332  if [ -n "$mnt" ] ; then
333     echo "$mnt"
334     return 0
335  fi
336  return 1
337}
338
339# Get the ZFS dataset of a particular directory
340getZFSDataset() {
341  local _chkDir="$1"
342  while :
343  do
344    local zData=`mount | grep " on ${_chkDir} " | grep "(zfs," | awk '{print $1}'`
345    if [ -n "$zData" ] ; then
346       echo "$zData"
347       return 0
348    fi
349    if [ "$2" != "rec" ] ; then return 1 ; fi
350    if [ "$_chkDir" = "/" ] ; then return 1 ; fi
351    _chkDir=`dirname $_chkDir`
352  done
353  return 1
354}
355
356# Get the ZFS tank name for a directory
357# Arg1 = Directory to check
358getZFSTank() {
359  local _chkDir="$1"
360
361  _chkdir=${_chkDir%/}
362  while :
363  do
364     zpath=`zfs list | awk -v path="${_chkDir}" '$5 == path { print $1 }'`
365     if [ -n "${zpath}" ] ; then
366        echo $zpath | cut -f1 -d '/'
367        return 0
368     fi
369
370     if [ "$_chkDir" = "/" ] ; then return 1 ; fi
371     _chkDir=`dirname $_chkDir`
372  done
373
374  return 1
375}
376
377# Get the mountpoint for a ZFS name
378# Arg1 = name
379getZFSMountpoint() {
380   local _chkName="${1}"
381   if [ -z "${_chkName}" ]; then return 1 ; fi
382
383   zfs list "${_chkName}" | tail -1 | awk '{ print $5 }'
384}
385
386# Get the ZFS relative path for a path
387# Arg1 = Path
388getZFSRelativePath() {
389   local _chkDir="${1}"
390   local _tank=`getZFSTank "$_chkDir"`
391   local _mp=`getZFSMountpoint "${_tank}"`
392
393   if [ -z "${_tank}" ] ; then return 1 ; fi
394
395   local _name="${_chkDir#${_mp}}"
396   echo "${_name}"
397   return 0
398}
399
400# Check if an address is IPv6
401isV6() {
402  echo ${1} | grep -q ":"
403  return $?
404}
405   
406# Is a mount point, or any of its parent directories, a symlink?
407is_symlinked_mountpoint()
408{
409        local _dir
410        _dir=$1
411        [ -L "$_dir" ] && return 0
412        [ "$_dir" = "/" ] && return 1
413        is_symlinked_mountpoint `dirname $_dir`
414        return $?
415}
416
417# Function to ask the user to press Return to continue
418rtn()
419{
420  echo -e "Press ENTER to continue\c";
421  read garbage
422};
423
424# Function to check if an IP address passes a basic sanity test
425check_ip()
426{
427  ip="$1"
428 
429  # If this is a V6 address, skip validation for now
430  isV6 "${ip}"
431  if [ $? -eq 0 ] ; then return ; fi
432
433  # Check if we can cut this IP into the right segments
434  SEG="`echo $ip | cut -d '.' -f 1 2>/dev/null`"
435  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
436  if [ "$?" != "0" ]
437  then
438     return 1
439  fi
440  if [ $SEG -gt 255 -o $SEG -lt 0 ]
441  then
442     return 1
443  fi
444 
445  # Second segment
446  SEG="`echo $ip | cut -d '.' -f 2 2>/dev/null`"
447  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
448  if [ "$?" != "0" ]
449  then
450     return 1
451  fi
452  if [ $SEG -gt 255 -o $SEG -lt 0 ]
453  then
454     return 1
455  fi
456
457  # Third segment
458  SEG="`echo $ip | cut -d '.' -f 3 2>/dev/null`"
459  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
460  if [ "$?" != "0" ]
461  then
462     return 1
463  fi
464  if [ $SEG -gt 255 -o $SEG -lt 0 ]
465  then
466     return 1
467  fi
468 
469  # Fourth segment
470  SEG="`echo $ip | cut -d '.' -f 4 2>/dev/null`"
471  echo $SEG | grep -E "^[0-9]+$" >/dev/null 2>/dev/null
472  if [ "$?" != "0" ]
473  then
474     return 1
475  fi
476  if [ $SEG -gt 255 -o $SEG -lt 0 ]
477  then
478     return 1
479  fi
480
481  return 0
482};
Note: See TracBrowser for help on using the repository browser.