OSDN Git Service

Version 3.0.4+toward_3.0.5_20131213231732
[portsreinstall/current.git] / lib / libpkgsys.sh
1 #!/bin/sh -e
2 # ==============================================================================
3 # portsreinstall library script
4 # - Wrappers for hiding version differences in the Ports/Packages system -
5 # Copyright (C) 2013 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
6 # This software is distributed under the 2-Clause BSD License.
7 # ==============================================================================
8
9 # ============= Variables =============
10 PKGSYS_USE_PKGNG=yes    # no: legacy pkg_* tools, yes: the new generation package (pkgng)
11 PKGSYS_CMD_PKG_INFO='pkg info'  # Corresponding command for pkg_info
12 PKGSYS_CMD_PKG_CREATE='pkg create'      # Corresponding command for pkg_create
13 PKGSYS_CMD_PKG_DELETE='pkg delete'      # Corresponding command for pkg_delete
14 PKGSYS_CMD_PKG_ADD='pkg add'    # Corresponding command for pkg_add
15 PKGSYS_AVR_REFETCH_TIMES_PER_SITE=1     # Average number (integer) of retrials for retrieving package or distfiles per mirror site
16 PKGSYS_AVR_REFETCH_TIMES_FOR_CHKSUMERR=2        #  Number (integer) of retrials for check sum error in retrieving a package
17
18 # ============= System defined value for the ports/packages =============
19 pkgsys_sysvar ()
20 {
21         local var tmp_work
22         var=$1
23         tmp_work=${TMPDIR}/pkgsys_sysvar:work
24         rm -rf "$tmp_work"
25         mkdir "$tmp_work"
26         make -C "$tmp_work" -f "${PORTSDIR}/Mk/bsd.port.mk" -V "$var" 2> /dev/null
27 }
28
29 # ============= Get the file name of package check sum file =============
30 pkgsys_pkgchksum_file ()
31 {
32         echo CHECKSUM.MD5
33 }
34
35 # ============= Check whether a port is indispensable for the standard function of the ports/packages system =============
36 pkgsys_is_pkgtool ()
37 {
38         case $1 in
39         ports-mgmt/pkg|ports-mgmt/dialog4ports)
40                 ;;
41         *)      return 1;;
42         esac
43 }
44
45 # ============= Check whether the dialog for selecting port options is dialog4ports =============
46 pkgsys_is_dialog4ports_used ()
47 {
48         [ -n "`pkgsys_sysvar DIALOG4PORTS`" ]
49 }
50
51 # ============= Get the number of mirror sites for legacy packages =============
52 pkgsys_num_mirrorsites ()
53 {
54         local siteroots
55         siteroots=$1
56         echo "$siteroots" | tr '|' '\n' | wc -l
57 }
58
59 # ============= Get a URL one of mirror sites =============
60 pkgsys_url_from_mirrors ()
61 {
62         local siteroots subdir nsites id_site site platform version
63         siteroots=$1
64         subdir=$2
65         nsites=`pkgsys_num_mirrorsites "$siteroots"`
66         id_site=`(set +e; random -e $nsites; echo $?)`
67         site=`echo "$siteroots" | tr '|' '\n' | sed -n $((${id_site}+1))p`
68         platform=`uname -p`
69         version=`uname -r | cut -d - -f 1,2 | tr [:upper:] [:lower:]`
70         echo -n "$site"
71         printf "$subdir\n" "$platform" "$version"
72 }
73
74 # ============= Fetch a file from one of mirror sites =============
75 pkgsys_fetch_from_mirrors ()
76 {
77         local siteroots subdir filename dst tmp_work fetch itrial origdir url
78         siteroots=$1
79         subdir=$2
80         filename=$3
81         dst=$4
82         tmp_work=${TMPDIR}/pkgsys_fetch_from_mirrors:work
83         rm -rf "$tmp_work"
84         mkdir "$tmp_work"
85         fetch=`pkgsys_sysvar FETCH_CMD`
86         itrial=$((`pkgsys_num_mirrorsites "$siteroots"`*$PKGSYS_AVR_REFETCH_TIMES_PER_SITE))
87         origdir=`pwd`
88         cd "$tmp_work"
89         while [ $itrial -ge 1 ]
90         do
91                 url=`pkgsys_url_from_mirrors "$siteroots" "$subdir"`$filename
92                 message_echo "INFO: Fetching from $url:"
93                 $fetch "$url"&& break
94                 rm -f "$filename"
95                 itrial=$(($itrial-1))
96         done
97         cd "$origdir"
98         [ -e "$tmp_work/$filename" ] || return
99         mv "$tmp_work/$filename" "$dst"
100 }
101
102 # ============= Get the package check sums file ready =============
103 pkgsys_ready_checksum_file ()
104 {
105         local chksumfile
106         tmp_savedpath=${TMPDIR}/pkgsys_ready_checksum_file:savedpath
107         rm -f "$tmp_savedpath"
108         chksumfile=`pkgsys_pkgchksum_file`
109         if [ ! -e "${DBDIR}/checksum/$chksumfile" ]
110         then
111                 [ -d "${DBDIR}/checksum" ] || mkdir "${DBDIR}/checksum"
112                 if ! pkgsys_fetch_from_mirrors "${PACKAGECHECKSUMROOTS}" "${PACKAGECHECKSUMDIR}" \
113                         "$chksumfile" "${DBDIR}/checksum"
114                 then
115                         message_echo "WARNING: No check sum file is available." >&2
116                         return 1
117                 fi
118         fi
119         echo "${DBDIR}/checksum/$chksumfile" > $tmp_savedpath
120 }
121
122 # ============= Get the location of a check sums file fetched by pkgsys_ready_checksum_file =============
123 pkgsys_ready_checksum_file__fetched_file ()
124 {
125         cat "${TMPDIR}/pkgsys_ready_checksum_file:savedpath"
126 }
127
128 # ============= Fetch a legacy package from one of remote sites =============
129 pkgsys_fetch_legacy_remote ()
130 {
131         local pkg tmp_work tmp_pkgpath pkg_regexp checksumpath validMD5 fetchedMD5 needs_fetch itrial
132         pkg=$1
133         tmp_work=${TMPDIR}/pkgsys_fetch_legacy_remote:work
134         tmp_pkgpath=${TMPDIR}/pkgsys_fetch_legacy_remote:pkgpath
135         rm -rf "$tmp_work"
136         mkdir "$tmp_work"
137         pkg_regexp=`str_escape_regexp "$pkg"`
138         pkgsys_ready_checksum_file || return
139         checksumpath=`pkgsys_ready_checksum_file__fetched_file`
140         validMD5=`grep -m 1 -E -e "^MD5[[:space:]]*\($pkg_regexp\.tbz\)[[:space:]]*=" "$checksumpath" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
141         if [ -z "$validMD5" ]
142         then
143                 message_echo "WARNING: No check sum for $pkg.tbz." >&2
144                 return 1
145         fi
146         needs_fetch=yes
147         [ -d "${PKGREPOSITORY}" ] || mkdir -p "${PKGREPOSITORY}"
148         if [ -e "${PKGREPOSITORY}/$pkg.tbz" ]
149         then
150                 if [ -e "${PKGREPOSITORY}/$pkg.md5=$validMD5.tbz" ]
151                 then
152                         fetchedMD5=`md5 "${PKGREPOSITORY}/$pkg.md5=$validMD5.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
153                         [ "x$fetchedMD5" = "x$validMD5" ] || rm "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz"
154                 fi
155                 if [ -e "${PKGREPOSITORY}/$pkg.md5=$validMD5.tbz" ]
156                 then
157                         ln -f "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz" "${PKGREPOSITORY}/$pkg.tbz"
158                 else
159                         fetchedMD5=`md5 "${PKGREPOSITORY}/$pkg.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
160                         if [ "x$fetchedMD5" = "x$validMD5" ]
161                         then
162                                 needs_fetch=no
163                         else
164                                 mv "${PKGREPOSITORY}/$pkg.tbz" "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz"
165                         fi
166                 fi
167         fi
168         if [ $needs_fetch = yes ]
169         then
170                 itrial=$PKGSYS_AVR_REFETCH_TIMES_FOR_CHKSUMERR
171                 while [ $itrial -ge 1 ]
172                 do
173                         if pkgsys_fetch_from_mirrors "${PACKAGEROOTS}" "${PACKAGEDIR}" \
174                                 "$pkg.tbz" "$tmp_work"
175                         then
176                                 fetchedMD5=`md5 "$tmp_work/$pkg.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
177                                 [ "x$fetchedMD5" = "x$validMD5" ] && break
178                                 message_echo "WARNING: Check sum mismatches for $pkg.tbz." >&2
179                         fi
180                         itrial=$(($itrial-1))
181                 done
182                 [ $itrial -ge 1 ] || return
183                 mv "$tmp_work/$pkg.tbz" "${PKGREPOSITORY}"
184         fi
185         echo "${PKGREPOSITORY}/$pkg.tbz" > $tmp_pkgpath
186 }
187
188 # ============= Get the location of a package fetched by pkgsys_fetch_legacy_remote =============
189 pkgsys_fetch_legacy_remote__fetched_pkg ()
190 {
191         cat "${TMPDIR}/pkgsys_fetch_legacy_remote:pkgpath"
192 }
193
194 # ============= Check whether the dependency of a legacy package is the latest =============
195 pkg_is_dependency_of_a_legacypkg_latest ()
196 {
197         local pkgarc tmp_extract tmp_contents tmp_origin tmp_pkg pkg nlines iline origin_req pkg_req pkg_new
198         pkgarc=$1
199         tmp_extract=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:extract
200         tmp_contents=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:contents
201         tmp_origin=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:origin
202         tmp_pkg=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:pkg
203         pkg=`pkgsys_pkgarc_to_pkgname "$pkgarc"`
204         [ -e "$pkgarc" ] || return
205         rm -rf "$tmp_extract"
206         mkdir "$tmp_extract"
207         tar xf "$pkgarc" -C "$tmp_extract" +CONTENTS
208         grep -e '^@pkgdep[[:space:]]' -e '^@comment[[:space:]]*DEPORIGIN:' "$tmp_extract/+CONTENTS" \
209                 | sed 's/^@pkgdep[[:space:]]*//;s/^@comment[[:space:]]*DEPORIGIN://' > $tmp_contents
210         nlines=`wc -l < $tmp_contents`
211         iline=1
212         while [ $iline -le $nlines ]
213         do
214                 origin_req=`sed -n ${iline}p "$tmp_contents"`
215                 pkg_req=`sed -n $(($iline+1))p "$tmp_contents"`
216                 iline=$(($iline+2))
217                 pkg_new=`cat "${DBDIR}/requires/$origin_req/new_version" 2> /dev/null` || :
218                 if [ -z "$pkg_new" -o "$pkg_new" != "$pkg_req" ]
219                 then
220                         message_echo "WARNING: Requirements of remote package $pkg are not the latest." >&2
221                         return 1
222                 fi
223         done
224         :
225 }
226
227 # ============= Check whether legacy package tools are available =============
228 pkgsys_is_legacy_tool_available ()
229 {
230         which -s pkg_info
231 }
232
233 # ============= Define wrapper commands for hiding the differences between pkg_* tools and pkgng =============
234 pkgsys_def_pkgtools ()
235 {
236         if [ "${DBDIR}/WITH_PKGNG" -nt /etc/make.conf -o \( -e "${DBDIR}/WITH_PKGNG" -a ! -e /etc/make.conf \) ]
237         then
238                 PKGSYS_USE_PKGNG=`cat "${DBDIR}/WITH_PKGNG"`
239         else
240                 PKGSYS_USE_PKGNG=`pkgsys_sysvar WITH_PKGNG | tr '[:upper:]' '[:lower:]'`
241                 if [ -d "${DBDIR}" ] && misc_is_superuser_privilege
242                 then
243                         echo "$PKGSYS_USE_PKGNG" > ${DBDIR}/WITH_PKGNG.tmp
244                         mv "${DBDIR}/WITH_PKGNG.tmp" "${DBDIR}/WITH_PKGNG"
245                 fi
246         fi
247         if [ "x$PKGSYS_USE_PKGNG" = xyes ]
248         then
249                 export WITH_PKGNG=yes
250                 PKGSYS_CMD_PKG_INFO='pkg info'
251                 PKGSYS_CMD_PKG_CREATE='pkg create'
252                 PKGSYS_CMD_PKG_DELETE='pkg delete'
253                 PKGSYS_CMD_PKG_ADD='pkg add'
254                 pkg_is_tool_available ()
255                 {
256                         if [ -x /usr/sbin/pkg ]
257                         then
258                                 pkg -N 2> /dev/null && return
259                                 env ASSUME_ALWAYS_YES=yes pkg bootstrap -f
260                                 pkg_is_tool_available
261                         else
262                                 which -s pkg && return
263                         fi
264                 }
265                 pkg_info_Ea ()
266                 {
267                         pkg info -qa 2> /dev/null
268                 }
269                 pkg_info_qoa ()
270                 {
271                         pkg info -qoa 2> /dev/null
272                 }
273 #               pkg_info_qox ()
274 #               {
275 #                       pkg info -qox "$@" 2> /dev/null
276 #               }
277                 pkg_info_qoX ()
278                 {
279                         pkg info -qoX "$@" 2> /dev/null
280                 }
281                 pkg_info_qO ()
282                 {
283                         pkg info -qO "$@" 2> /dev/null
284                 }
285                 pkg_info_qo ()
286                 {
287                         pkg info -qo "$@" 2> /dev/null
288                 }
289                 pkg_info_qr ()
290                 {
291                         pkg info -qd "$@" 2> /dev/null
292                 }
293                 pkg_info_e ()
294                 {
295                         pkg info -e "$@" 2> /dev/null
296                 }
297                 pkg_info_eO ()
298                 {
299                         pkg info -eO "$1" 2> /dev/null
300                 }
301                 pkg_info_Eg ()
302                 {
303                         pkg info -Eg "$@" 2> /dev/null
304                 }
305                 pkg_info_qR ()
306                 {
307                         pkg info -qr "$@" 2> /dev/null
308                 }
309                 pkg_info_Ex ()
310                 {
311                         pkg info -Ex "$@" 2> /dev/null
312                 }
313                 pkg_info_qL ()
314                 {
315                         pkg info -ql "$@" 2> /dev/null
316                 }
317                 pkg_check_sanity ()
318                 {
319                         local pkg
320                         pkg=$1
321                         pkg check -s "$pkg" 2> /dev/null
322                 }
323                 pkg_which ()
324                 {
325                         local filepath
326                         filepath=$1
327                         pkg which -q "$filepath" 2> /dev/null
328                 }
329                 pkg_info_gen_pkg_origin_table ()
330                 {
331                         pkg query -g '%n-%v\t%o' \* 2> /dev/null > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
332                 }
333                 pkg_create_b ()
334                 {
335                         pkg create "$@"
336                 }
337                 pkg_delete_f ()
338                 {
339                         pkg delete -fqy "$@"
340                 }
341                 pkg_add_tools ()
342                 {
343                         local pkgarc tmp_extract prefix prefix_parent pkg
344                         pkgarc=$1
345                         tmp_extract=${TMPDIR}/pkgng:pkg_add_tools:extract
346                         rm -rf "$tmp_extract"
347                         mkdir "$tmp_extract"
348                         tar xf "$pkgarc" -C "$tmp_extract"
349                         prefix=`grep -m 1 '^prefix: ' "$tmp_extract/+MANIFEST" | sed 's/^prefix: *//'`
350                         prefix_parent=`dirname "$prefix"`
351                         cp -Rp "$tmp_extract/$prefix" "$prefix_parent"/
352                         pkg=`pkgsys_pkgarc_to_pkgname "$pkgarc"`
353                         message_echo "INFO: Contents of $pkg are temporarily installed by simple copy."
354                         if env ASSUME_ALWAYS_YES=YES pkg add "$pkgarc"
355                         then
356                                 message_echo "INFO: $pkg is successfully registered."
357                         else
358                                 message_echo "WARNING: Failed to register $pkg, but the process is continued." >&2
359                         fi
360                 }
361                 pkg_add_f ()
362                 {
363                         local pkgarc pkg pkg_tool pkg_gen
364                         pkg_tool=
365                         pkg_gen=
366                         for pkgarc in "$@"
367                         do
368                                 pkg=`basename "$pkgarc"`
369                                 if expr "$pkg" : '^pkg-[0-9][0-9]*\..*' > /dev/null
370                                 then
371                                         pkg_tool=$pkgarc
372                                 else
373                                         pkg_gen="$pkg_gen $pkgarc"
374                                 fi
375                         done
376                         [ -n "$pkg_tool" ] && pkg_add_tools "$pkg_tool"
377                         [ -n "$pkg_gen" ] && env ASSUME_ALWAYS_YES=YES pkg add $pkg_gen
378                 }
379                 pkg_add_fF ()
380                 {
381                         pkg_add_f "$@"
382                 }
383                 pkg_inst_remote_fetch ()
384                 {
385                         local pkg mode pkgarc
386                         pkg=$1
387                         mode=$2
388                         tmp_extract=${TMPDIR}/pkgng:pkg_inst_remote:extract
389                         pkg fetch -yU "$pkg" || return
390                         pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}/All" "$pkg"` || return
391                         [ "x$mode" = xnodepschk ] && return
392                         rm -rf "$tmp_extract"
393                         mkdir "$tmp_extract"
394                         tar xf "$pkgarc" -C "$tmp_extract" +MANIFEST
395                         sed -E '1,/^deps:/d;/^[^[:space:]]/,$d;s/^[[:space:]]*([^:]+):[[:space:]]*\{origin:[[:space:]]*([^,]+),[[:space:]]*version:[[:space:]]*([^}]+)\}/\2\\\1-\3/' "$tmp_extract/+MANIFEST" \
396                                 | tr '\\' '\t' | while read origin_req pkg_req
397                         do
398                                 pkg_new=`cat "${DBDIR}/requires/$origin_req/new_version" 2> /dev/null` || :
399                                 if [ -z "$pkg_new" -o "$pkg_new" != "$pkg_req" ]
400                                 then
401                                         message_echo "WARNING: Requirements of remote package $pkg are not latest." >&2
402                                         return 1
403                                 fi
404                         done
405                         :
406                 }
407                 pkg_inst_remote ()
408                 {
409                         local pkg mode pkgarc
410                         pkg=$1
411                         mode=$2
412                         pkg_inst_remote_fetch "$pkg" "$mode" || return
413                         pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}/All" "$pkg"` || return
414                         env ASSUME_ALWAYS_YES=YES pkg add "$pkgarc"
415                 }
416                 pkg_inst_remote_wild_fetch ()
417                 {
418                         local pkg mode pkgarc
419                         pkg=$1
420                         mode=$2
421                         if pkg_is_tool_available
422                         then
423                                 pkg_inst_remote "$pkg" "$mode" && return
424                         fi
425                         pkgsys_is_legacy_tool_available || return
426                         message_echo "INFO: Trying to use a legacy package and convert it to pkgng."
427                         pkgsys_fetch_legacy_remote "$pkg" || return
428                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
429                         [ "x$mode" = xnodepschk ] && return
430                         pkg_is_dependency_of_a_legacypkg_latest "$pkgarc"
431                 }
432                 pkg_inst_remote_wild ()
433                 {
434                         local pkg mode pkgarc
435                         pkg=$1
436                         mode=$2
437                         pkg_inst_remote_wild_fetch "$pkg" "$mode" || return
438                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
439                         pkg_add -ifF "$pkgarc" || return
440                         message_echo "INFO: Trying to convert the installed legacy package to pkgng."
441                         pkg2ng || :
442                         message_echo "INFO: Checking whether the conversion is successful."
443                         pkg info -e "$pkg"
444                 }
445                 pkg_loadconf ()
446                 {
447                         local pkg_conf
448                         # Deafult configuration for pkg(1)
449                         PKGNG_PACKAGESITE='http://pkg.freebsd.org/${ABI}/latest'
450                         PKGNG_SRV_MIRRORS=YES
451                         PKGNG_PKG_DBDIR=/var/db/pkg
452                         PKGNG_PKG_CACHEDIR=/var/cache/pkg
453                         PKGNG_PORTSDIR=/usr/ports
454                         PKGNG_PUBKEY=/etc/ssl/pkg.conf
455                         PKGNG_HANDLE_RC_SCRIPTS=NO
456                         PKGNG_PKG_MULTIREPOS=NO
457                         PKGNG_ASSUME_ALWAYS_YES=NO
458                         PKGNG_SYSLOG=YES
459                         PKGNG_SHLIBS=NO
460                         PKGNG_AUTODEPS=NO
461                         PKGNG_PORTAUDIT_SITE='http=//portaudit.FreeBSD.org/auditfile.tbz'
462                         # Load configuration for pkg(1)
463                         pkg_conf=`pkg query %Fp pkg | grep '/etc/pkg\.conf\.sample$' | sed 's/\.sample$//'`
464                         grep -v -e '^[[:space:]]*#' -e '^[[:space:]]*$' "$pkg_conf" 2> /dev/null \
465                                 | grep -e '^[[:space:]]*[A-Z0-9_]*[[:space:]]*:[[:space:]]*.*' \
466                                 | while read srcline
467                         do
468                                 var=`expr "$srcline" : '^[[:space:]]*\([A-Z0-9_]*\)[[:space:]]*:.*'` || :
469                                 val=`expr "$srcline" : '^[[:space:]]*[A-Z0-9_]*[[:space:]]*:[[:space:]]*\(.*\)'` || :
470                                 eval PKGNG_$var=\$val
471                                 misc_get_all_vardefs | grep -E "^PKGNG_$var="
472                         done > ${TMPDIR}/pkgsys_def_pkgtools:pkg.conf.sh
473                         . "${TMPDIR}/pkgsys_def_pkgtools:pkg.conf.sh"
474                 }
475                 pkg_rescue_tools ()
476                 {
477                         local packagepath checksumpath pkgname is_successful
478                         packagepath=`pkgsys_get_backup_pkg ports-mgmt/pkg` && \
479                                 pkg_add_tools "$packagepath" && return
480                         pkg_is_tool_available && return
481                         message_echo "WARNING: WITH_PKGNG is set, but pkgng is still missing. It is installed now." >&2
482                         pkgsys_ready_checksum_file || return
483                         message_echo "INFO: Installing pkgng by legacy package tool."
484                         checksumpath=`pkgsys_ready_checksum_file__fetched_file`
485                         pkgname=`sed 's/^MD5[[:space:]]*(//;s/\.tbz)[[:space:]]*=[^=]*$//' "$checksumpath" \
486                                 | grep -m 1 -E -e "^pkg-[0-9]"` || :
487                         [ -n "$pkgname" ] && pkg_inst_remote_wild "$pkgname" nodepschk && return
488                         message_echo "INFO: Failed by package, so installing pkgng by port."
489                         grep -v '^[[:space:]]*WITH_PKGNG=' /etc/make.conf > ${TMPDIR}/make.conf
490                         echo WITHOUT_PKGNG=yes >> ${TMPDIR}/make.conf
491                         ( set -e
492                                 unset WITH_PKGNG
493                                 unset WITHOUT_PKGNG
494                                 
495                                 message_echo "INFO: Attempting deinstallation of ports-mgmt/pkg to make sure."
496                                 env __MAKE_CONF="${TMPDIR}/make.conf" make -C "${PORTSDIR}/ports-mgmt/pkg" deinstall || :
497                                 message_echo "INFO: Attempting (re)installation by ports-mgmt/pkg."
498                                 env __MAKE_CONF="${TMPDIR}/make.conf" make -C "${PORTSDIR}/ports-mgmt/pkg" reinstall clean
499                         ) && {
500                                 pkg2ng || :
501                                 pkg_is_tool_available
502                         }
503                 }
504                 if ! pkg_rescue_tools
505                 then
506                         message_echo "WARNING: Pkgng is still missing, but continuing for the time being." >&2
507                 fi
508                 pkg_loadconf
509         elif ! pkgsys_is_legacy_tool_available
510         then
511                 message_echo "ERROR: Pkgng is disabled although the legacy packages tools are unavailable. Resolve the problem manually." >&2
512                 exit 1
513         else
514                 unset WITH_PKGNG
515                 PKGSYS_USE_PKGNG=no
516                 PKGSYS_CMD_PKG_INFO='pkg_info'
517                 PKGSYS_CMD_PKG_CREATE='pkg_create'
518                 PKGSYS_CMD_PKG_DELETE='pkg_delete'
519                 PKGSYS_CMD_PKG_ADD='pkg_add'
520                 pkg_is_tool_available ()
521                 {
522                         pkgsys_is_legacy_tool_available
523                 }
524                 pkg_info_Ea ()
525                 {
526                         pkg_info -Ea 2> /dev/null
527                 }
528                 pkg_info_qoa ()
529                 {
530                         pkg_info -qoa 2> /dev/null
531                 }
532 #               pkg_info_qox ()
533 #               {
534 #                       pkg_info -qox "$@" 2> /dev/null
535 #               }
536                 pkg_info_qoX ()
537                 {
538                         pkg_info -qoX "$@" 2> /dev/null
539                 }
540                 pkg_info_qO ()
541                 {
542                         pkg_info -qO "$@" 2> /dev/null
543                 }
544                 pkg_info_qo ()
545                 {
546                         pkg_info -qo "$@" 2> /dev/null
547                 }
548                 pkg_info_qr ()
549                 {
550                         pkg_info -qr "$@" | grep '^@pkgdep ' | sed 's/^@pkgdep[[:space:]]*//' 2> /dev/null
551                 }
552                 pkg_info_e ()
553                 {
554                         pkg_info -e "$@" 2> /dev/null
555                 }
556                 pkg_info_eO ()
557                 {
558                         [ `pkg_info -qO "$1" 2> /dev/null | wc -l` -gt 0 ]
559                 }
560                 pkg_info_Eg ()
561                 {
562                         pkg_info -E "$@" 2> /dev/null
563                 }
564                 pkg_info_qR ()
565                 {
566                         pkg_info -qR "$@" | grep -v '^$' 2> /dev/null
567                 }
568                 pkg_info_Ex ()
569                 {
570                         pkg_info -Ex "$@" 2> /dev/null
571                 }
572                 pkg_info_qL ()
573                 {
574                         pkg_info -qL "$@" 2> /dev/null
575                 }
576                 pkg_check_sanity ()
577                 {
578                         local pkg
579                         pkg=$1
580                         pkg_info -qg "$pkg" 2> /dev/null
581                 }
582                 pkg_which ()
583                 {
584                         local filepath
585                         filepath=$1
586                         pkg_info -qW "$filepath" 2> /dev/null
587                 }
588                 pkg_info_gen_pkg_origin_table ()
589                 {
590                         pkg_info -aE 2> /dev/null | while read pkg
591                         do
592                                 origin=`pkg_info -qo "$pkg" 2> /dev/null`
593                                 printf '%s\t%s\n' "$pkg" "$origin"
594                         done > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
595                 }
596                 pkg_create_b ()
597                 {
598                         pkg_create -b "$@"
599                 }
600                 pkg_delete_f ()
601                 {
602                         pkg_delete -f "$@"
603                 }
604                 pkg_add_f ()
605                 {
606                         pkg_add -if "$@"
607                 }
608                 pkg_add_fF ()
609                 {
610                         pkg_add -ifF "$@"
611                 }
612                 pkg_inst_remote_fetch ()
613                 {
614                         local pkg mode pkgarc
615                         pkg=$1
616                         mode=$2
617                         pkgsys_fetch_legacy_remote "$pkg" || return
618                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
619                         [ "x$mode" = xnodepschk ] && return
620                         pkg_is_dependency_of_a_legacypkg_latest "$pkgarc"
621                 }
622                 pkg_inst_remote ()
623                 {
624                         local pkg mode pkgarc
625                         pkg=$1
626                         mode=$2
627                         pkg_inst_remote_fetch "$pkg" "$mode" || return
628                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
629                         pkg_add "$pkgarc" || return
630                 }
631                 pkg_inst_remote_wild_fetch ()
632                 {
633                         pkg_inst_remote_fetch "$1" "$2"
634                 }
635                 pkg_inst_remote_wild ()
636                 {
637                         pkg_inst_remote "$1" "$2"
638                 }
639                 pkg_loadconf () { :; }
640                 pkg_rescue_tools () { :; }
641         fi
642 }
643
644 # ============= Check existence of initially or currently installed package for an origin =============
645 pkgsys_pkg_info_eO ()
646 {
647         local origin origin_regexp
648         origin=$1
649         origin_regexp=`str_escape_regexp "$origin"`
650         cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
651                 | grep -q -E "^$origin_regexp$" && return
652         pkg_info_eO "$origin"
653 }
654
655 # ============= Get the name of an initially installed package for an origin =============
656 pkgsys_pkg_info_qO_init ()
657 {
658         local origin tmppkg origin_regexp npkgs
659         origin=$1
660         tmppkg=${TMPDIR}/pkgsys_pkg_info_qO_init::pkg
661         origin_regexp=`str_escape_regexp "$origin"`
662         { sed -n -E "/[[:space:]]$origin_regexp$/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null || :; } \
663                 | cut -f 1 > $tmppkg
664         npkgs=`wc -l < $tmppkg`
665         if [ $npkgs -gt 0 ]
666         then
667                 cat "$tmppkg"
668         else
669                 pkg_info_qO "$origin"
670         fi
671 }
672
673 # ============= Get the package name of this utility =============
674 pkgsys_get_my_current_pkg ()
675 {
676         pkg_info_Ex "${APPNAME}-[0-9].*"
677 }
678
679 # ============= Get the origin of this utility =============
680 pkgsys_get_my_origin ()
681 {
682         pkg_info_qo "`pkgsys_get_my_current_pkg`"
683 }
684
685 # ============= Get the origin of an initially installed package by ambiguous matching =============
686 pkgsys_init_pkg_orig_by_ambiguous_matching ()
687 {
688         local pkg origin tmporigin ambsuffix len_pkg pkg_regexp norigins
689         pkg=$1
690         origin=`pkg_info_qo "$pkg" || :`
691         [ -n "$origin" ] && { echo "$origin"; return; }
692         tmporigin=${TMPDIR}/pkgsys_init_pkg_orig_by_ambiguous_matching::origin
693         ambsuffix=
694         norigins=0
695         len_pkg=`echo -n "$pkg" | wc -c`
696         if [ $len_pkg -gt 0 ]
697         then
698                 while :
699                 do
700                         pkg_regexp=`str_escape_regexp "$pkg"`$ambsuffix
701                         grep -E "^${pkg_regexp}[[:space:]]" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
702                                 | cut -f 2 > $tmporigin
703                         norigins=`wc -l < $tmporigin`
704                         [ $norigins -gt 0 ] && break
705                         ambsuffix='[a-zA-Z0-9.,_+-]*'
706                         len_pkg=$(($len_pkg-1))
707                         [ $len_pkg -gt 0 ] || break
708                         pkg=`echo -n "$pkg" | head -c $len_pkg`
709                 done
710         fi
711         [ $norigins -eq 1 ] || return
712         cat "$tmporigin"
713 }
714
715 # ============= A part of message indicating tools for showing concerned issues in UPDATING =============
716 pkgsys_show_pkg_updating_commands ()
717 {
718         if [ "x$PKGSYS_USE_PKGNG" = xyes ]
719         then
720                 if which -s pkg_updating
721                 then
722                         echo 'pkg-updating(8) or pkg_updating(1)'
723                 else
724                         echo 'pkg-updating(8)'
725                 fi
726         elif which -s pkg_updating
727         then
728                 echo 'pkg_updating(1)'
729         fi
730 }
731
732 # ============= Evaluation of ports globs =============
733 pkgsys_eval_ports_glob ()
734 {
735         local pkglist origlist
736         pkglist=${DBDIR}/pkgsys_eval_ports_glob:pkg.lst
737         origlist=${DBDIR}/pkgsys_eval_ports_glob:origin.lst
738         if [ ! -r "$pkglist" ]
739         then
740                 if touch "$pkglist" 2>/dev/null
741                 then
742                         rm "$pkglist"
743                 else
744                         pkglist=${TMPDIR}/pkgsys_eval_ports_glob:pkg.lst
745                 fi
746         fi
747         if [ ! -r "$origlist" ]
748         then
749                 if touch "$origlist" 2>/dev/null
750                 then
751                         rm "$origlist"
752                 else
753                         origlist=${TMPDIR}/pkgsys_eval_ports_glob:origin.lst
754                 fi
755         fi
756         [ -f "$pkglist" ] \
757                 || cut -d \| -f 1 "${PORTS_INDEX_DB}" > $pkglist
758         [ -f "$origlist" ] \
759                 || cut -d \| -f 2 "${PORTS_INDEX_DB}" \
760                 | sed -E "s/^`str_escape_regexp "${PORTSDIR}"`\///" > $origlist
761         while [ $# -gt 0 ]
762         do
763                 glob=$1
764                 shift
765                 expr "x$glob" : '^x-' > /dev/null 2>&1 && continue
766                 glob_regexp=`str_convert_portsglob_to_regexp_pattern "$glob"`
767                 if expr "$glob" : '[^/][^/]*\/[^/][^/]*$' > /dev/null 2>&1
768                 then
769                         grep -E "$glob_regexp" "$origlist" 2>&1 || :
770                         {
771                                 pkg_info_qoa
772                                 cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null
773                         } | grep -E "$glob_regexp" 2>&1 || :
774                 else
775                         if expr "$glob" : '^[a-z][a-zA-Z0-9+-]*[a-zA-Z0-9+]$' > /dev/null 2>&1 && \
776                                 [ `expr "$glob" : '.*-[0-9]' 2>&1` -eq 0 ]
777                         then
778                                 glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'-[0-9]'
779                         else
780                                 glob_regexp2=$glob_regexp
781                         fi
782                         grep -n -E "$glob_regexp2" "$pkglist" 2>&1 | cut -d : -f 1 \
783                                 | while read index
784                         do
785                                 sed -n ${index}p "$origlist"
786                         done || :
787                         glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'[[:space:]]'
788                         { sed -n -E "/$glob_regexp2/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null || :; } \
789                                 | cut -f 2
790                         pkg_info_qoX "$glob_regexp" || :
791                 fi
792         done | sort -u
793 }
794
795 # ============= Create a back-up package archive =============
796 pkgsys_create_backup_pkg ()
797 {
798         local pkgname dstdir origin backup_pkg_old origin_regexp pkgname_ptn backup_pkg pkgpath
799         pkgname=$1
800         dstdir=$2
801         rm -rf "${TMPDIR}"/package.tmp
802         mkdir "${TMPDIR}"/package.tmp
803         origin=`pkg_info_qo "$pkgname"`
804         if backup_pkg_old=`pkgsys_get_backup_pkg "$origin"` \
805                 [ "$backup_pkg_old" -nt "${DBDIR}/requires/$origin/installed_timestamp" ]
806         then
807                 echo "$backup_pkg_old"
808                 return
809         fi
810         if ( cd "${TMPDIR}"/package.tmp && pkg_create_b "$pkgname" > /dev/null )
811         then
812                 pkgname_ptn=`str_escape_regexp "$pkgname"`
813                 backup_pkg=`ls "${TMPDIR}"/package.tmp | \
814                         grep -m 1 -E "^${pkgname_ptn}\.(txz|tbz|tgz|tar)$"` || :
815         fi
816         if [ -z "$backup_pkg" ]
817         then
818                 message_echo "WARNING: Failed to create backup package for $pkgname." >&2
819                 return 1
820         fi
821         [ -d "$dstdir" ] || mkdir -p "$dstdir"
822         mv "${TMPDIR}/package.tmp/$backup_pkg" "$dstdir"
823         pkgpath=$dstdir/$backup_pkg
824         origin_regexp=`str_escape_regexp "$origin"`
825         cat "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null | \
826                 while read origin_cur pkgpath_cur
827                 do
828                         [ "$pkgpath_cur" = "$pkgpath" ] && continue
829                         if [ "$origin_cur" = "$origin" ]
830                         then
831                                 rm -f "$pkgpath_cur"
832                         else
833                                 printf '%s\t%s\n' "$origin_cur" "$pkgpath_cur"
834                         fi
835                 done > ${DBDIR}/backup_pkgarcs.lst.tmp
836         printf '%s\t%s\n' "$origin" "$pkgpath" >> ${DBDIR}/backup_pkgarcs.lst.tmp
837         mv "${DBDIR}/backup_pkgarcs.lst.tmp" "${DBDIR}/backup_pkgarcs.lst"
838         echo "$pkgpath"
839 }
840
841 # ============= Delete a back-up package archive for a port origin =============
842 pkgsys_delete_backup_pkg ()
843 {
844         local origin origin_regexp
845         origin=$1
846         origin_regexp=`str_escape_regexp "$origin"`
847         grep -E "^${origin_regexp}[[:space:]]" "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null \
848                 | cut -f 2 | while read pkgpath_cur
849                 do
850                         rm -f "$pkgpath_cur"
851                 done
852         grep -v -E "^${origin_regexp}[[:space:]]" "${DBDIR}/backup_pkgarcs.lst" \
853                 2> /dev/null > ${DBDIR}/backup_pkgarcs.lst.tmp || :
854         mv "${DBDIR}/backup_pkgarcs.lst.tmp" "${DBDIR}/backup_pkgarcs.lst"
855 }
856
857 # ============= Get an existing package archive path for a port origin =============
858 pkgsys_get_backup_pkg ()
859 {
860         local origin origin_regexp
861         origin=$1
862         tmpnewest=${TMPDIR}/pkgsys_get_backup_pkg::newest
863         origin_regexp=`str_escape_regexp "$origin"`
864         rm -f "$tmpnewest"
865         grep -E "^${origin_regexp}[[:space:]]" "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null \
866                 | cut -f 2 | while read pkgpath
867         do
868                 pkgpath_newest=`cat "$tmpnewest" 2> /dev/null` || :
869                 [ -e "$pkgpath" ] || continue
870                 [ -z "$pkgpath_newest" -o "$pkgpath" -nt "$pkgpath_newest" ] || continue
871                 echo "$pkgpath" > $tmpnewest
872         done
873         cat "$tmpnewest" 2> /dev/null
874 }
875
876 # ============= Get a package name from a package archive file name =============
877 pkgsys_pkgarc_to_pkgname ()
878 {
879         local pkgfile_path
880         pkgfile_path=$1
881         basename "$pkgfile_path" | sed -E 's/\.(txz|tbz|tgz|tar)$//'
882 }
883
884 # ============= Get the file name of an existing package archive for a package name =============
885 pkgsys_pkgname_to_pkgarc ()
886 {
887         local pkgdir pkgname pkgname_ptn pkgnode
888         pkgdir=$1
889         pkgname=$2
890         [ -n "$pkgname" ] || return 1
891         [ -d "$pkgdir" ] || return 1
892         if [ "x$PKGSYS_USE_PKGNG" = xyes ]
893         then
894                 pkgname_ptn=`str_escape_regexp "$pkgname"`
895                 pkgnode=`ls "$pkgdir" 2> /dev/null | grep -m 1 -E "^${pkgname_ptn}\.(txz|tbz|tgz|tar)$"` || :
896         elif [ -e "$pkgdir/$pkgname.tbz" ]
897         then
898                 pkgnode=$pkgname.tbz
899         fi
900         [ -n "$pkgnode" ] || return 1
901         echo "$pkgdir/$pkgnode"
902 }
903
904 # ============= Get port origins matching a glob pattern even if nonexistent =============
905 pkgsys_eval_ports_glob_even_if_nonexistent ()
906 {
907         local glob_pattern
908         glob_pattern=$1
909         {
910                 pkgsys_eval_ports_glob "$glob_pattern" 2> /dev/null || :
911                 echo "$glob_pattern" | grep '^[a-z][a-z]*/[a-zA-Z0-9_+-][a-zA-Z0-9_+-]*$' || :
912         } | grep -v -e '^$' | sort -u
913 }
914
915 # ============= Evaluate glob patterns and add/remove non-existing/existing ones of them to/from a file =============
916 pkgsys_register_evaluated_globs ()
917 {
918         local mode listpath dirpath tmp_evaluated
919         mode=$1
920         listpath=$2
921         shift 2
922         dirpath=`dirname "$listpath"`
923         tmp_evaluated=${TMPDIR}/pkgsys_register_evaluated_globs:pkgsys_eval_ports_glob
924         echo "$@" | sed -E 's/[ :]+/\
925 /g' | grep -v '^$' | sort -u | while read glob
926         do
927                 pkgsys_eval_ports_glob "$glob" > $tmp_evaluated
928                 [ `wc -l < $tmp_evaluated` -ge 1 ] || \
929                 {
930                         message_echo "WARNING: No matching ports/package glob [$glob]." >&2
931                         continue
932                 }
933                 cat "$tmp_evaluated"
934         done | while read origin
935         do
936                 [ -d "$dirpath" ] || mkdir -p "$dirpath"
937                 case $mode in
938                 remove) fileedit_rm_a_line "$origin" "$listpath";;
939                 add)    fileedit_add_a_line_if_new "$origin" "$listpath";;
940                 esac
941         done
942 }
943
944 # ============= Evaluate glob patterns for installed packages =============
945 pkgsys_eval_installed_pkgs_globs ()
946 {
947         local tmp_evaluated
948         tmp_evaluated=${TMPDIR}/pkgsys_eval_installed_pkgs_globs:origins
949         rm -f "$tmp_evaluated"
950         pkgsys_register_evaluated_globs add "$tmp_evaluated" "$@"
951         [ -e "$tmp_evaluated" ] || return 0
952         while read origin
953         do
954                 pkgsys_pkg_info_eO "$origin" || echo "$origin"
955         done < $tmp_evaluated
956 }
957
958 # ============= Get glob patterns of conflicting packages of a port =============
959 pkgsys_get_conflicting_pkgs_patterns ()
960 {
961         local mode origin conflicts
962         mode=$1
963         origin=$2
964         conflicts=`database_query_get_makevar_val "$origin" CONFLICTS`
965         case $mode in
966         build)
967                 conflicts=$conflicts' '`database_query_get_makevar_val "$origin" CONFLICTS_BUILD`
968                 ;;
969         install)
970                 conflicts=$conflicts' '`database_query_get_makevar_val "$origin" CONFLICTS_INSTALL`
971                 ;;
972         esac
973         echo "$conflicts" | tr ' ' '\n' | grep -v '^$' || :
974 }       
975
976 # ============= Get conflicting installed packages of a port =============
977 pkgsys_get_conflicting_installed_pkgs ()
978 {
979         local mode origin tmp_conflicts
980         mode=$1
981         origin=$2
982         tmp_conflicts=${TMPDIR}/pkgsys_get_conflicting_installed_pkgs::conflicts
983         pkg_info_Eg `pkgsys_get_conflicting_pkgs_patterns "$mode" "$origin"` > $tmp_conflicts || :
984         cat "$tmp_conflicts"
985         [ `wc -l < $tmp_conflicts` -gt 0 ]
986 }       
987
988 # ============= Check whether a package conflicts with a port =============
989 pkgsys_chk_conflict_by_a_pkg ()
990 {
991         local mode origin pkg tmp_conflicts_ptn
992         mode=$1
993         origin=$2
994         pkg=$3
995         tmp_conflicts_ptn=${TMPDIR}/pkgsys_chk_conflict_by_a_pkg::conflicts_ptn
996         pkgsys_get_conflicting_pkgs_patterns "$mode" "$origin" \
997                 | str_convert_glob_to_regexp_pattern > $tmp_conflicts_ptn
998         echo "$pkg" | grep -q -E -f "$tmp_conflicts_ptn"
999 }       
1000
1001 # ============= Check whether installed files are lost or broken for a package =============
1002 pkgsys_sanitychk_pkgcontents ()
1003 {
1004         local pkg var_is_reinstall_encouraged _is_reinstall_encouraged tmp_sanity nlines iline src filename icol filename_esc pkg_owner origin
1005         pkg=$1
1006         var_is_reinstall_encouraged=$2
1007         tmp_sanity=${TMPDIR}/pkgsys_sanitychk_pkgcontents:sanity
1008         pkg_check_sanity "$pkg" > $tmp_sanity || :
1009         eval "$var_is_reinstall_encouraged=no"
1010         [ `wc -l < $tmp_sanity` -eq 0 ] && return
1011         nlines=`wc -l < $tmp_sanity`
1012         iline=1
1013         _is_reinstall_encouraged=no
1014         while [ $iline -le $nlines ]
1015         do
1016                 src=`sed -n ${iline}p "$tmp_sanity"`
1017                 iline=$(($iline+1))
1018                 filename=`echo "$src" | cut -d ' ' -f 1`
1019                 icol=2
1020                 until [ -e "$filename" -o "$filename" = "$src" ]
1021                 do
1022                         filename="$filename "`echo "$src" | cut -d ' ' -f $icol`
1023                 done
1024                 [ -e "$filename" ] || continue
1025                 if expr "$filename" : '.*/include/.*' > /dev/null
1026                 then
1027                         _is_reinstall_encouraged=yes
1028                         break
1029                 fi
1030                 filename_esc=`str_escape_regexp "$filename"`
1031                 if file "$filename" | sed -E "s/^$filename_esc:[[:space:]]//" | grep -q '^ELF '
1032                 then
1033                         _is_reinstall_encouraged=yes
1034                         break
1035                 fi
1036                 pkg_owner=`pkg_which "$filename"`
1037                 if [ "$pkg" != "$pkg_owner" ]
1038                 then
1039                         _is_reinstall_encouraged=yes
1040                         break
1041                 fi
1042         done
1043         eval "$var_is_reinstall_encouraged=\$_is_reinstall_encouraged"
1044         origin=`pkg_info_qo "$pkg"`
1045         if [ $opt_batch_mode = no ]
1046         then
1047                 message_echo "[$pkg ($origin)]"
1048                 sed 's/^/  /' "$tmp_sanity"
1049                 message_echo
1050         else
1051                 pkg_replace=`str_escape_replaceval "$pkg"`
1052                 origin_replace=`str_escape_replaceval "$origin"`
1053                 sed "s/^/$pkg_replace\\\\$origin_replace\\\\$_is_reinstall_encouraged\\\\/" "$tmp_sanity" | tr '\\' '\t'
1054         fi
1055         return 1
1056 }