1#!/bin/sh
2#-
3# Copyright (c) 2010 iXsystems, Inc.  All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.
13#
14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24# SUCH DAMAGE.
25#
26# $FreeBSD$
27
28# Functions which runs commands on the system
29
30. ${BACKEND}/functions.sh
31. ${BACKEND}/functions-parse.sh
32. ${BACKEND}/functions-ftp.sh
33
34
35get_package_index_by_ftp()
36{
37  local INDEX_FILE
38  local FTP_SERVER
39
40  FTP_SERVER="${1}"
41  INDEX_FILE="INDEX"
42  USE_BZIP2=0
43
44  if [ -f "/usr/bin/bzip2" ]
45  then
46    INDEX_FILE="${INDEX_FILE}.bz2"
47    USE_BZIP2=1
48    INDEX_PATH="${INDEXFILE}.bz2"
49  else
50    INDEX_PATH="${INDEXFILE}"
51  fi
52
53  fetch_file "${FTP_SERVER}/${INDEX_FILE}" "${INDEX_PATH}" "1"
54  if [ -f "${INDEX_PATH}" ] && [ "${USE_BZIP2}" -eq "1" ]
55  then
56    bzip2 -d "${INDEX_PATH}"
57  fi
58};
59
60get_package_index_by_fs()
61{
62  if [ "$INSTALLMEDIUM" = "local" ] ; then
63    INDEXFILE="${LOCALPATH}/packages/INDEX"
64  else
65    INDEXFILE="${CDMNT}/packages/INDEX"
66  fi
67};
68
69get_package_index_size()
70{
71  if [ -f "${INDEXFILE}" ]
72  then
73    SIZE=`ls -l ${INDEXFILE} | awk '{ print $5 }'`
74  else
75    get_ftp_mirror
76    FTPHOST="${VAL}"
77
78    FTPDIR="/pub/FreeBSD/releases/${FBSD_ARCH}/${FBSD_BRANCH}"
79    FTPPATH="ftp://${FTPHOST}${FTPDIR}/packages"
80
81    fetch -s "${FTPPATH}/INDEX.bz2"
82  fi
83};
84
85get_package_index()
86{
87  RES=0
88
89  if [ -z "${INSTALLMODE}" ]
90  then
91    get_ftp_mirror
92    FTPHOST="${VAL}"
93
94    FTPDIR="/pub/FreeBSD/releases/${FBSD_ARCH}/${FBSD_BRANCH}"
95    FTPPATH="ftp://${FTPHOST}${FTPDIR}/packages"
96
97    get_package_index_by_ftp "${FTPPATH}"
98
99  else
100
101    case "${INSTALLMEDIUM}" in
102    usb|dvd|local) get_package_index_by_fs ;;
103              ftp) get_value_from_cfg ftpHost
104    		   if [ -z "$VAL" ]; then
105      		     exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" 
106    	  	   fi
107    		   FTPHOST="${VAL}"
108
109    		   get_value_from_cfg ftpDir
110    		   if [ -z "$VAL" ]; then
111      		     exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" 
112    		   fi
113    	 	   FTPDIR="${VAL}"
114    		   FTPPATH="ftp://${FTPHOST}${FTPDIR}"
115                   get_package_index_by_ftp "${FTPPATH}" ;;
116             sftp) ;;
117                *) RES=1 ;;
118    esac
119
120  fi
121
122  return ${RES}
123};
124
125parse_package_index()
126{
127  echo_log "Building package dep list.. Please wait.."
128  INDEX_FILE="${PKGDIR}/INDEX"
129
130  exec 3<&0
131  exec 0<"${INDEXFILE}"
132
133  while read -r line
134  do
135    PKGNAME=""
136    CATEGORY=""
137    PACKAGE=""
138    DESC=""
139    DEPS=""
140    i=0
141
142    SAVE_IFS="${IFS}"
143    IFS="|"
144
145    for part in ${line}
146    do
147      if [ ${i} -eq 0 ]
148      then
149        PKGNAME="${part}"
150
151      elif [ ${i} -eq 1 ]
152      then
153        PACKAGE=`basename "${part}"`
154
155      elif [ ${i} -eq 3 ]
156      then
157        DESC="${part}"
158
159      elif [ ${i} -eq 6 ]
160      then
161        CATEGORY=`echo "${part}" | cut -f1 -d' '`
162
163      elif [ ${i} -eq 8 ]
164      then
165        DEPS="${part}"
166      fi
167
168      i=$((i+1))
169    done
170
171    echo "${CATEGORY}|${PACKAGE}|${DESC}" >> "${INDEX_FILE}.parsed"
172    echo "${PACKAGE}|${PKGNAME}|${DEPS}" >> "${INDEX_FILE}.deps"
173
174    IFS="${SAVE_IFS}"
175  done
176
177  exec 0<&3
178};
179
180show_package_file()
181{
182  PKGFILE="${1}"
183
184  echo "Available Packages:"
185
186  exec 3<&0
187  exec 0<"${PKGFILE}"
188
189  while read -r line
190  do
191    CATEGORY=`echo "${line}" | cut -f1 -d'|'`
192    PACKAGE=`echo "${line}" | cut -f2 -d'|'`
193    DESC=`echo "${line}" | cut -f3 -d'|'`
194
195    echo "${CATEGORY}/${PACKAGE}:${DESC}"
196  done
197
198  exec 0<&3
199};
200
201show_packages_by_category()
202{
203  CATEGORY="${1}"
204  INDEX_FILE="${PKGDIR}/INDEX.parsed"
205  TMPFILE="/tmp/.pkg.cat"
206
207  grep "^${CATEGORY}|" "${INDEX_FILE}" > "${TMPFILE}"
208  show_package_file "${TMPFILE}"
209  rm "${TMPFILE}"
210};
211
212show_package_by_name()
213{
214  CATEGORY="${1}"
215  PACKAGE="${2}"
216  INDEX_FILE="${PKGDIR}/INDEX.parsed"
217  TMPFILE="/tmp/.pkg.cat.pak"
218
219  grep "^${CATEGORY}|${PACKAGE}" "${INDEX_FILE}" > "${TMPFILE}"
220  show_package_file "${TMPFILE}"
221  rm "${TMPFILE}"
222};
223
224show_packages()
225{
226  show_package_file "${PKGDIR}/INDEX.parsed"
227};
228
229get_package_dependencies()
230{
231  PACKAGE="${1}"
232  LONG="${2:-0}"
233  RES=0
234
235  INDEX_FILE="${PKGDIR}/INDEX.deps"
236  REGEX="^${PACKAGE}|"
237
238  if [ ${LONG} -ne 0 ]
239  then
240    REGEX="^.*|${PACKAGE}|"
241  fi
242
243  LINE=`grep "${REGEX}" "${INDEX_FILE}" 2>/dev/null`
244  DEPS=`echo "${LINE}"|cut -f3 -d'|'`
245
246  export VAL="${DEPS}"
247
248  if [ -z "${VAL}" ]
249  then
250    RES=1
251  fi
252
253  return ${RES}
254};
255
256get_package_name()
257{
258  PACKAGE="${1}"
259  RES=0
260  local PKGPTH
261
262  # If we are on a local medium, we can parse the Latest/ directory
263  if [ "${INSTALLMEDIUM}" != "ftp" ] ; then
264    case "${INSTALLMEDIUM}" in
265      usb|dvd) PKGPTH="${CDMNT}/packages" ;; 
266        *) PKGPTH="${LOCALPATH}/packages" ;;
267    esac
268    
269    # Check the /Latest dir for generic names, then look for specific version in All/
270    if [ -e "${PKGPTH}/Latest/${PACKAGE}.${PKGEXT}" ] ; then
271       NAME=`ls -al ${PKGPTH}/Latest/${PACKAGE}.${PKGEXT} 2>/dev/null | cut -d '>' -f 2 | rev | cut -f1 -d'/' | rev | tr -s ' '`
272    else
273       NAME=`ls -al ${PKGPTH}/All/${PACKAGE}.${PKGEXT} 2>/dev/null | cut -d '>' -f 2 | rev | cut -f1 -d'/' | rev | tr -s ' '`
274    fi
275    export VAL="${NAME}"
276  else
277    # Doing remote fetch, we we will look up, but some generic names like
278    # "perl" wont work, since we don't know the default version
279    INDEX_FILE="${PKGDIR}/INDEX.deps"
280    REGEX="^${PACKAGE}|"
281	
282    LINE=`grep "${REGEX}" "${INDEX_FILE}" 2>/dev/null`
283    NAME=`echo "${LINE}"|cut -f2 -d'|'`
284
285    export VAL="${NAME}"
286  fi
287
288  if [ -z "${VAL}" ]
289  then
290    RES=1
291  fi
292  return ${RES}
293};
294
295get_package_short_name()
296{
297  PACKAGE="${1}"
298  RES=0
299
300  INDEX_FILE="${PKGDIR}/INDEX.deps"
301  REGEX="^.*|${PACKAGE}|"
302	
303  LINE=`grep "${REGEX}" "${INDEX_FILE}" 2>/dev/null`
304  NAME=`echo "${LINE}"|cut -f1 -d'|'`
305
306  export VAL="${NAME}"
307
308  if [ -z "${VAL}" ]
309  then
310    RES=1
311  fi
312
313  return ${RES}
314};
315
316get_package_category()
317{
318  PACKAGE="${1}"
319  INDEX_FILE="${PKGDIR}/INDEX.parsed"
320  RES=0
321
322  LINE=`grep "|${PACKAGE}|" "${INDEX_FILE}" 2>/dev/null`
323  NAME=`echo "${LINE}"|cut -f1 -d'|'`
324
325  export VAL="${NAME}"
326
327  if [ -z "${VAL}" ]
328  then
329    RES=1
330  fi
331
332  return ${RES}
333};
334
335fetch_package_by_ftp()
336{
337  CATEGORY="${1}"
338  PACKAGE="${2}"
339  SAVEDIR="${3}"
340
341  get_value_from_cfg ftpHost
342  if [ -z "$VAL" ]
343  then
344    exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" 
345  fi
346  FTPHOST="${VAL}"
347
348  get_value_from_cfg ftpDir
349  if [ -z "$VAL" ]
350  then
351    exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" 
352  fi
353  FTPDIR="${VAL}"
354
355  PACKAGE="${PACKAGE}.${PKGEXT}"
356  FTP_SERVER="ftp://${FTPHOST}${FTPDIR}"
357
358  if [ ! -f "${SAVEDIR}/${PACKAGE}" ]
359  then
360    PKGPATH="${CATEGORY}/${PACKAGE}"
361    FTP_PATH="${FTP_HOST}/packages/${PKGPATH}"
362    fetch_file "${FTP_PATH}" "${SAVEDIR}/" "0"
363  fi
364};
365
366fetch_package()
367{
368  CATEGORY="${1}"
369  PACKAGE="${2}"
370  SAVEDIR="${3}"
371
372  # Fetch package, but skip if installing from local media
373  case "${INSTALLMEDIUM}" in
374  usb|dvd|local) return ;;
375    ftp) fetch_package_by_ftp "${CATEGORY}" "${PACKAGE}" "${SAVEDIR}" ;;
376    sftp) ;;
377  esac
378};
379
380bootstrap_pkgng()
381{
382  # Check if we need to boot-strap pkgng
383  if run_chroot_cmd "which pkg-static" >/dev/null 2>/dev/null
384  then
385     return
386  fi
387  local PKGPTH
388
389  # Ok, lets boot-strap this sucker
390  echo_log "Bootstraping pkgng.."
391  fetch_package "Latest" "pkg" "${PKGDLDIR}"
392
393  # Figure out real location of "pkg" package
394  case "${INSTALLMEDIUM}" in
395    usb|dvd|local) PKGPTH="${PKGTMPDIR}/Latest/pkg.${PKGEXT}" ;;
396          *) PKGPTH="${PKGTMPDIR}/pkg.${PKGEXT}" ;;
397  esac
398  rc_halt "pkg -c ${FSMNT} add ${PKGPTH}" ; run_chroot_cmd "pkg2ng"
399}
400
401get_package_location()
402{
403  case "${INSTALLMEDIUM}" in
404  usb|dvd) rc_halt "mount_nullfs ${CDMNT}/packages ${FSMNT}${PKGTMPDIR}"
405           PKGDLDIR="${FSMNT}${PKGTMPDIR}/All" ;;
406    local) rc_halt "mount_nullfs ${LOCALPATH}/packages ${FSMNT}${PKGTMPDIR}"
407           PKGDLDIR="${FSMNT}${PKGTMPDIR}/All" ;;
408        *) PKGDLDIR="${FSMNT}${PKGTMPDIR}" ;;
409  esac
410  export PKGDLDIR
411}
412