OSDN Git Service

Version MYVERSION=3.0.0+toward_3.1.0_20130607223126
[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=no     # 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"
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                 fetchedMD5=`md5 "${PKGREPOSITORY}/$pkg.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
151                 if [ "x$fetchedMD5" = "x$validMD5" ]
152                 then
153                         needs_fetch=no
154                 else
155                         mv "${PKGREPOSITORY}/$pkg.tbz" "${PKGREPOSITORY}/$pkg.md5=$fetchedMD5.tbz"
156                 fi
157         fi
158         if [ $needs_fetch = yes ]
159         then
160                 itrial=$PKGSYS_AVR_REFETCH_TIMES_FOR_CHKSUMERR
161                 while [ $itrial -ge 1 ]
162                 do
163                         if pkgsys_fetch_from_mirrors "${PACKAGEROOTS}" "${PACKAGEDIR}" \
164                                 "$pkg.tbz" "$tmp_work"
165                         then
166                                 fetchedMD5=`md5 "$tmp_work/$pkg.tbz" | sed -E "s/^[^=]*=[[:space:]]*(.*)/\1/"`
167                                 [ "x$fetchedMD5" = "x$validMD5" ] && break
168                                 message_echo "WARNING: Check sum mismatches for $pkg.tbz." >&2
169                         fi
170                         itrial=$(($itrial-1))
171                 done
172                 [ $itrial -ge 1 ] || return
173                 mv "$tmp_work/$pkg.tbz" "${PKGREPOSITORY}"
174         fi
175         echo "${PKGREPOSITORY}/$pkg.tbz" > $tmp_pkgpath
176 }
177
178 # ============= Get the location of a package fetched by pkgsys_fetch_legacy_remote =============
179 pkgsys_fetch_legacy_remote__fetched_pkg ()
180 {
181         cat "${TMPDIR}/pkgsys_fetch_legacy_remote:pkgpath"
182 }
183
184 # ============= Check whether the dependency of a legacy package is the latest =============
185 pkg_is_dependency_of_a_legacypkg_latest ()
186 {
187         local pkgarc tmp_extract tmp_contents tmp_origin tmp_pkg pkg nlines iline origin_req pkg_req pkg_new
188         pkgarc=$1
189         tmp_extract=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:extract
190         tmp_contents=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:contents
191         tmp_origin=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:origin
192         tmp_pkg=${TMPDIR}/pkgng:pkg_is_dependency_of_a_legacypkg_latest:pkg
193         pkg=`pkgsys_pkgarc_to_pkgname "$pkgarc"`
194         [ -e "$pkgarc" ] || return
195         rm -rf "$tmp_extract"
196         mkdir "$tmp_extract"
197         tar xf "$pkgarc" -C "$tmp_extract" +CONTENTS
198         grep -e '^@pkgdep[[:space:]]' -e '^@comment[[:space:]]*DEPORIGIN:' "$tmp_extract/+CONTENTS" \
199                 | sed 's/^@pkgdep[[:space:]]*//;s/^@comment[[:space:]]*DEPORIGIN://' > $tmp_contents
200         nlines=`wc -l < $tmp_contents`
201         iline=1
202         while [ $iline -le $nlines ]
203         do
204                 origin_req=`sed -n ${iline}p "$tmp_contents"`
205                 pkg_req=`sed -n $(($iline+1))p "$tmp_contents"`
206                 iline=$(($iline+2))
207                 pkg_new=`cat "${DBDIR}/requires/$origin_req/new_version" 2> /dev/null` || :
208                 if [ -z "$pkg_new" -o "$pkg_new" != "$pkg_req" ]
209                 then
210                         message_echo "WARNING: Requirements of remote package $pkg are not the latest." >&2
211                         return 1
212                 fi
213         done
214         :
215 }
216
217 # ============= Define wrapper commands for hiding the differences between pkg_* tools and pkgng =============
218 pkgsys_def_pkgtools ()
219 {
220         if [ "${DBDIR}/WITH_PKGNG" -nt /etc/make.conf ]
221         then
222                 PKGSYS_USE_PKGNG=`cat "${DBDIR}/WITH_PKGNG"`
223         else
224                 PKGSYS_USE_PKGNG=`pkgsys_sysvar WITH_PKGNG | tr '[:upper:]' '[:lower:]'`
225                 if [ -d "${DBDIR}" ]
226                 then
227                         echo "$PKGSYS_USE_PKGNG" > ${DBDIR}/WITH_PKGNG.tmp
228                         mv "${DBDIR}/WITH_PKGNG.tmp" "${DBDIR}/WITH_PKGNG"
229                 fi
230         fi
231         if [ "x$PKGSYS_USE_PKGNG" = xyes ]
232         then
233                 export WITH_PKGNG=yes
234                 PKGSYS_CMD_PKG_INFO='pkg info'
235                 PKGSYS_CMD_PKG_CREATE='pkg create'
236                 PKGSYS_CMD_PKG_DELETE='pkg delete'
237                 PKGSYS_CMD_PKG_ADD='pkg add'
238                 pkg_is_tool_available ()
239                 {
240                         which -a pkg | grep -v '^/usr/sbin/pkg$' | grep -q '/sbin/pkg$'
241                 }
242                 pkg_info_qoa ()
243                 {
244                         pkg info -qoa 2> /dev/null
245                 }
246 #               pkg_info_qox ()
247 #               {
248 #                       pkg info -qox "$@" 2> /dev/null
249 #               }
250                 pkg_info_qoX ()
251                 {
252                         pkg info -qoX "$@" 2> /dev/null
253                 }
254                 pkg_info_qO ()
255                 {
256                         pkg info -qO "$@" 2> /dev/null
257                 }
258                 pkg_info_qo ()
259                 {
260                         pkg info -qo "$@" 2> /dev/null
261                 }
262                 pkg_info_qr ()
263                 {
264                         pkg info -qd "$@" 2> /dev/null
265                 }
266                 pkg_info_e ()
267                 {
268                         pkg info -e "$@" 2> /dev/null
269                 }
270                 pkg_info_eO ()
271                 {
272                         pkg info -eO "$1" 2> /dev/null
273                 }
274                 pkg_info_Eg ()
275                 {
276                         pkg info -Eg "$@" 2> /dev/null
277                 }
278                 pkg_info_qR ()
279                 {
280                         pkg info -qr "$@" 2> /dev/null
281                 }
282                 pkg_info_Ex ()
283                 {
284                         pkg info -Ex "$@" 2> /dev/null
285                 }
286                 pkg_info_gen_pkg_origin_table ()
287                 {
288                         pkg query -g '%n-%v\t%o' \* 2> /dev/null > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
289                 }
290                 pkg_create_b ()
291                 {
292                         pkg create "$@"
293                 }
294                 pkg_delete_f ()
295                 {
296                         pkg delete -fqy "$@"
297                 }
298                 pkg_add_tools ()
299                 {
300                         local pkgarc tmp_extract prefix prefix_parent pkg
301                         pkgarc=$1
302                         tmp_extract=${TMPDIR}/pkgng:pkg_add_tools:extract
303                         rm -rf "$tmp_extract"
304                         mkdir "$tmp_extract"
305                         tar xf "$pkgarc" -C "$tmp_extract"
306                         prefix=`grep -m 1 '^prefix: ' "$tmp_extract/+MANIFEST" | sed 's/^prefix: *//'`
307                         prefix_parent=`dirname "$prefix"`
308                         cp -Rp "$tmp_extract/$prefix" "$prefix_parent"/
309                         pkg=`pkgsys_pkgarc_to_pkgname "$pkgarc"`
310                         message_echo "INFO: Contents of $pkg are temporarily installed by simple copy."
311                         if env ASSUME_ALWAYS_YES=YES pkg add "$pkgarc"
312                         then
313                                 message_echo "INFO: $pkg is successfully registered."
314                         else
315                                 message_echo "WARNING: Failed to register $pkg, but the process is continued." >&2
316                         fi
317                 }
318                 pkg_add_f ()
319                 {
320                         local pkgarc pkg pkg_tool pkg_gen
321                         pkg_tool=
322                         pkg_gen=
323                         for pkgarc in "$@"
324                         do
325                                 pkg=`basename "$pkgarc"`
326                                 if expr "$pkg" : '^pkg-[0-9][0-9]*\..*' > /dev/null
327                                 then
328                                         pkg_tool=$pkgarc
329                                 else
330                                         pkg_gen="$pkg_gen $pkgarc"
331                                 fi
332                         done
333                         [ -n "$pkg_tool" ] && pkg_add_tools "$pkg_tool"
334                         [ -n "$pkg_gen" ] && env ASSUME_ALWAYS_YES=YES pkg add $pkg_gen
335                 }
336                 pkg_add_fF ()
337                 {
338                         pkg_add_f "$@"
339                 }
340                 pkg_inst_remote_fetch ()
341                 {
342                         local pkg mode pkgarc
343                         pkg=$1
344                         mode=$2
345                         tmp_extract=${TMPDIR}/pkgng:pkg_inst_remote:extract
346                         pkg fetch -yU "$pkg" || return
347                         pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}/All" "$pkg"` || return
348                         [ "x$mode" = xnodepschk ] && return
349                         rm -rf "$tmp_extract"
350                         mkdir "$tmp_extract"
351                         tar xf "$pkgarc" -C "$tmp_extract" +MANIFEST
352                         sed -E '1,/^deps:/d;/^[^[:space:]]/,$d;s/^[[:space:]]*([^:]+):[[:space:]]*\{origin:[[:space:]]*([^,]+),[[:space:]]*version:[[:space:]]*([^}]+)\}/\2\\\1-\3/' "$tmp_extract/+MANIFEST" \
353                                 | tr '\\' '\t' | while read origin_req pkg_req
354                         do
355                                 pkg_new=`cat "${DBDIR}/requires/$origin_req/new_version" 2> /dev/null` || :
356                                 if [ -z "$pkg_new" -o "$pkg_new" != "$pkg_req" ]
357                                 then
358                                         message_echo "WARNING: Requirements of remote package $pkg are not latest." >&2
359                                         return 1
360                                 fi
361                         done
362                         :
363                 }
364                 pkg_inst_remote ()
365                 {
366                         local pkg mode pkgarc
367                         pkg=$1
368                         mode=$2
369                         pkg_inst_remote_fetch "$pkg" "$mode" || return
370                         pkgarc=`pkgsys_pkgname_to_pkgarc "${PKGNG_PKG_CACHEDIR}/All" "$pkg"` || return
371                         env ASSUME_ALWAYS_YES=YES pkg add "$pkgarc"
372                 }
373                 pkg_inst_remote_wild_fetch ()
374                 {
375                         local pkg mode pkgarc
376                         pkg=$1
377                         mode=$2
378                         if pkg_is_tool_available
379                         then
380                                 pkg_inst_remote "$pkg" "$mode" && return
381                         fi
382                         message_echo "INFO: Trying to use a legacy package and convert it to pkgng."
383                         pkgsys_fetch_legacy_remote "$pkg" || return
384                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
385                         [ "x$mode" = xnodepschk ] && return
386                         pkg_is_dependency_of_a_legacypkg_latest "$pkgarc"
387                 }
388                 pkg_inst_remote_wild ()
389                 {
390                         local pkg mode pkgarc
391                         pkg=$1
392                         mode=$2
393                         pkg_inst_remote_wild_fetch "$pkg" "$mode" || return
394                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
395                         pkg_add -ifF "$pkgarc" || return
396                         message_echo "INFO: Trying to convert the installed legacy package to pkgng."
397                         pkg2ng || :
398                         message_echo "INFO: Checking whether the conversion is successful."
399                         pkg info -e "$pkg"
400                 }
401                 pkg_loadconf ()
402                 {
403                         local pkg_conf
404                         # Deafult configuration for pkg(1)
405                         PKGNG_PACKAGESITE='http://pkg.freebsd.org/${ABI}/latest'
406                         PKGNG_SRV_MIRRORS=YES
407                         PKGNG_PKG_DBDIR=/var/db/pkg
408                         PKGNG_PKG_CACHEDIR=/var/cache/pkg
409                         PKGNG_PORTSDIR=/usr/ports
410                         PKGNG_PUBKEY=/etc/ssl/pkg.conf
411                         PKGNG_HANDLE_RC_SCRIPTS=NO
412                         PKGNG_PKG_MULTIREPOS=NO
413                         PKGNG_ASSUME_ALWAYS_YES=NO
414                         PKGNG_SYSLOG=YES
415                         PKGNG_SHLIBS=NO
416                         PKGNG_AUTODEPS=NO
417                         PKGNG_PORTAUDIT_SITE='http=//portaudit.FreeBSD.org/auditfile.tbz'
418                         # Load configuration for pkg(1)
419                         pkg_conf=`pkg query %Fp pkg | grep '/etc/pkg\.conf\.sample$' | sed 's/\.sample$//'`
420                         grep -v -e '^[[:space:]]*#' -e '^[[:space:]]*$' "$pkg_conf" 2> /dev/null \
421                                 | grep -e '^[[:space:]]*[A-Z0-9_]*[[:space:]]*:[[:space:]]*.*' \
422                                 | while read srcline
423                         do
424                                 var=`expr "$srcline" : '^[[:space:]]*\([A-Z0-9_]*\)[[:space:]]*:.*'` || :
425                                 val=`expr "$srcline" : '^[[:space:]]*[A-Z0-9_]*[[:space:]]*:[[:space:]]*\(.*\)'` || :
426                                 eval PKGNG_$var=\$val
427                                 misc_get_all_vardefs | grep -E "^PKGNG_$var="
428                         done > ${TMPDIR}/pkgsys_def_pkgtools:pkg.conf.sh
429                         . "${TMPDIR}/pkgsys_def_pkgtools:pkg.conf.sh"
430                 }
431                 pkg_rescue_tools ()
432                 {
433                         local packagepath checksumpath pkgname
434                         packagepath=`pkgsys_get_backup_pkg ports-mgmt/pkg` && \
435                                 pkg_add_tools "$packagepath" && return
436                         [ -x /usr/local/sbin/pkg ] && return
437                         message_echo "WARNING: WITH_PKGNG is set, but pkgng is missing. It is installed now." >&2
438                         [ -x /usr/sbin/pkg ] && /usr/sbin/pkg && return
439                         pkgsys_ready_checksum_file || return
440                         checksumpath=`pkgsys_ready_checksum_file__fetched_file`
441                         pkgname=`sed 's/^MD5[[:space:]]*(//;s/\.tbz)[[:space:]]*=[^=]*$//' "$checksumpath" \
442                                 | grep -m 1 -E -e "^pkg-[0-9]"` || :
443                         [ -z "$pkgname" ] && pkg_inst_remote_wild "$pkgname" nodepschk && return
444                         make -C "${PORTSDIR}/ports-mgmt/pkg" install clean && return
445                         message_echo "ERROR: WITH_PKGNG is set, but pkgng is missing. It is installed now." >&2
446                         :
447                 }
448                 pkg_rescue_tools
449                 pkg_loadconf
450         else
451                 unset WITH_PKGNG
452                 PKGSYS_USE_PKGNG=no
453                 PKGSYS_CMD_PKG_INFO='pkg_info'
454                 PKGSYS_CMD_PKG_CREATE='pkg_create'
455                 PKGSYS_CMD_PKG_DELETE='pkg_delete'
456                 PKGSYS_CMD_PKG_ADD='pkg_add'
457                 pkg_is_tool_available ()
458                 {
459                         :
460                 }
461                 pkg_info_qoa ()
462                 {
463                         pkg_info -qoa 2> /dev/null
464                 }
465 #               pkg_info_qox ()
466 #               {
467 #                       pkg_info -qox "$@" 2> /dev/null
468 #               }
469                 pkg_info_qoX ()
470                 {
471                         pkg_info -qoX "$@" 2> /dev/null
472                 }
473                 pkg_info_qO ()
474                 {
475                         pkg_info -qO "$@" 2> /dev/null
476                 }
477                 pkg_info_qo ()
478                 {
479                         pkg_info -qo "$@" 2> /dev/null
480                 }
481                 pkg_info_qr ()
482                 {
483                         pkg_info -qr "$@" | grep '^@pkgdep ' | sed 's/^@pkgdep[[:space:]]*//' 2> /dev/null
484                 }
485                 pkg_info_e ()
486                 {
487                         pkg_info -e "$@" 2> /dev/null
488                 }
489                 pkg_info_eO ()
490                 {
491                         [ `pkg_info -qO "$1" 2> /dev/null | wc -l` -gt 0 ]
492                 }
493                 pkg_info_Eg ()
494                 {
495                         pkg_info -E "$@" 2> /dev/null
496                 }
497                 pkg_info_qR ()
498                 {
499                         pkg_info -qR "$@" | grep -v '^$' 2> /dev/null
500                 }
501                 pkg_info_Ex ()
502                 {
503                         pkg_info -Ex "$@" 2> /dev/null
504                 }
505                 pkg_info_gen_pkg_origin_table ()
506                 {
507                         pkg_info -aE 2> /dev/null | while read pkg
508                         do
509                                 origin=`pkg_info -qo "$pkg" 2> /dev/null`
510                                 printf '%s\t%s\n' "$pkg" "$origin"
511                         done > ${DBDIR}/installed_ports:pkg_vs_origin.tbl
512                 }
513                 pkg_create_b ()
514                 {
515                         pkg_create -b "$@"
516                 }
517                 pkg_delete_f ()
518                 {
519                         pkg_delete -f "$@"
520                 }
521                 pkg_add_f ()
522                 {
523                         pkg_add -if "$@"
524                 }
525                 pkg_add_fF ()
526                 {
527                         pkg_add -ifF "$@"
528                 }
529                 pkg_inst_remote_fetch ()
530                 {
531                         local pkg mode pkgarc
532                         pkg=$1
533                         mode=$2
534                         pkgsys_fetch_legacy_remote "$pkg" || return
535                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
536                         [ "x$mode" = xnodepschk ] && return
537                         pkg_is_dependency_of_a_legacypkg_latest "$pkgarc"
538                 }
539                 pkg_inst_remote ()
540                 {
541                         local pkg mode pkgarc
542                         pkg=$1
543                         mode=$2
544                         pkg_inst_remote_fetch "$pkg" "$mode" || return
545                         pkgarc=`pkgsys_fetch_legacy_remote__fetched_pkg`
546                         pkg_add "$pkgarc" || return
547                 }
548                 pkg_inst_remote_wild_fetch ()
549                 {
550                         pkg_inst_remote_fetch "$1" "$2"
551                 }
552                 pkg_inst_remote_wild ()
553                 {
554                         pkg_inst_remote "$1" "$2"
555                 }
556                 pkg_loadconf () { :; }
557                 pkg_rescue_tools () { :; }
558         fi
559 }
560
561 # ============= Check existence of initially or currently installed package for an origin =============
562 pkgsys_pkg_info_eO ()
563 {
564         local origin origin_regexp
565         origin=$1
566         origin_regexp=`str_escape_regexp "$origin"`
567         cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
568                 | grep -q -E "^$origin_regexp$" && return
569         pkg_info_eO "$origin"
570 }
571
572 # ============= Get the name of an initially installed package for an origin =============
573 pkgsys_pkg_info_qO_init ()
574 {
575         local origin tmppkg origin_regexp npkgs
576         origin=$1
577         tmppkg=${TMPDIR}/pkgsys_pkg_info_qO_init::pkg
578         origin_regexp=`str_escape_regexp "$origin"`
579         { sed -n -E "/[[:space:]]$origin_regexp$/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null || :; } \
580                 | cut -f 1 > $tmppkg
581         npkgs=`wc -l < $tmppkg`
582         if [ $npkgs -gt 0 ]
583         then
584                 cat "$tmppkg"
585         else
586                 pkg_info_qO "$origin"
587         fi
588 }
589
590 # ============= Get the package name of this utility =============
591 pkgsys_get_my_current_pkg ()
592 {
593         pkg_info_Ex "${APPNAME}-[0-9].*"
594 }
595
596 # ============= Get the origin of this utility =============
597 pkgsys_get_my_origin ()
598 {
599         pkg_info_qo "`pkgsys_get_my_current_pkg`"
600 }
601
602 # ============= Get the origin of an initially installed package by ambiguous matching =============
603 pkgsys_init_pkg_orig_by_ambiguous_matching ()
604 {
605         local pkg origin tmporigin ambsuffix len_pkg pkg_regexp norigins
606         pkg=$1
607         origin=`pkg_info_qo "$pkg" || :`
608         [ -n "$origin" ] && { echo "$origin"; return; }
609         tmporigin=${TMPDIR}/pkgsys_init_pkg_orig_by_ambiguous_matching::origin
610         ambsuffix=
611         norigins=0
612         len_pkg=`echo -n "$pkg" | wc -c`
613         while [ $len_pkg -gt 0 ]
614         do
615                 pkg_regexp=`str_escape_regexp "$pkg"`$ambsuffix
616                 grep -E "^${pkg_regexp}[[:space:]]" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null \
617                         | cut -f 2 > $tmporigin
618                 norigins=`wc -l < $tmporigin`
619                 [ $norigins -gt 0 ] && break
620                 len_pkg=$(($len_pkg-1))
621                 pkg=`echo -n "$pkg" | head -c $len_pkg`
622                 ambsuffix='[a-zA-Z0-9.,_+-]*'
623         done
624         [ $norigins -eq 1 ] || return
625         cat "$tmporigin"
626 }
627
628 # ============= A part of message indicating tools for showing concerned issues in UPDATING =============
629 pkgsys_show_pkg_updating_commands ()
630 {
631         if [ "x$PKGSYS_USE_PKGNG" = xyes ]
632         then
633                 if which -s pkg_updating
634                 then
635                         echo 'pkg-updating(8) or pkg_updating(1)'
636                 else
637                         echo 'pkg-updating(8)'
638                 fi
639         elif which -s pkg_updating
640         then
641                 echo 'pkg_updating(1)'
642         fi
643 }
644
645 # ============= Evaluation of ports globs =============
646 pkgsys_eval_ports_glob ()
647 {
648         local pkglist origlist
649         pkglist=${DBDIR}/pkgsys_eval_ports_glob:pkg.lst
650         origlist=${DBDIR}/pkgsys_eval_ports_glob:origin.lst
651         if [ ! -r "$pkglist" ]
652         then
653                 if touch "$pkglist" 2>/dev/null
654                 then
655                         rm "$pkglist"
656                 else
657                         pkglist=${TMPDIR}/pkgsys_eval_ports_glob:pkg.lst
658                 fi
659         fi
660         if [ ! -r "$origlist" ]
661         then
662                 if touch "$origlist" 2>/dev/null
663                 then
664                         rm "$origlist"
665                 else
666                         origlist=${TMPDIR}/pkgsys_eval_ports_glob:origin.lst
667                 fi
668         fi
669         [ -f "$pkglist" ] \
670                 || cut -d \| -f 1 "${PORTS_INDEX_DB}" > $pkglist
671         [ -f "$origlist" ] \
672                 || cut -d \| -f 2 "${PORTS_INDEX_DB}" \
673                 | sed -E "s/^`str_escape_regexp "${PORTSDIR}"`\///" > $origlist
674         while [ $# -gt 0 ]
675         do
676                 glob=$1
677                 shift
678                 expr "x$glob" : '^x-' > /dev/null 2>&1 && continue
679                 glob_regexp=`str_convert_portsglob_to_regexp_pattern "$glob"`
680                 if expr "$glob" : '[^/][^/]*\/[^/][^/]*$' > /dev/null 2>&1
681                 then
682                         grep -E "$glob_regexp" "$origlist" 2>&1 || :
683                         {
684                                 pkg_info_qoa
685                                 cut -f 2 "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null
686                         } | grep -E "$glob_regexp" 2>&1 || :
687                 else
688                         if expr "$glob" : '^[a-z][a-zA-Z0-9+-]*[a-zA-Z0-9+]$' > /dev/null 2>&1 && \
689                                 [ `expr "$glob" : '.*-[0-9]' 2>&1` -eq 0 ]
690                         then
691                                 glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'-[0-9]'
692                         else
693                                 glob_regexp2=$glob_regexp
694                         fi
695                         grep -n -E "$glob_regexp2" "$pkglist" 2>&1 | cut -d : -f 1 \
696                                 | while read index
697                         do
698                                 sed -n ${index}p "$origlist"
699                         done || :
700                         glob_regexp2=`expr "$glob_regexp" : '\(.*\)\$$' 2>&1`'[[:space:]]'
701                         { sed -n -E "/$glob_regexp2/p" "${DBDIR}/installed_ports:pkg_vs_origin.tbl" 2> /dev/null || :; } \
702                                 | cut -f 2
703                         pkg_info_qoX "$glob_regexp" || :
704                 fi
705         done | sort -u
706 }
707
708 # ============= Create a back-up package archive =============
709 pkgsys_create_backup_pkg ()
710 {
711         local pkgname dstdir origin backup_pkg_old origin_regexp pkgname_ptn backup_pkg pkgpath
712         pkgname=$1
713         dstdir=$2
714         rm -rf "${TMPDIR}"/package.tmp
715         mkdir "${TMPDIR}"/package.tmp
716         origin=`pkg_info_qo "$pkgname"`
717         if backup_pkg_old=`pkgsys_get_backup_pkg "$origin"` \
718                 [ "$backup_pkg_old" -nt "${DBDIR}/requires/$origin/installed_timestamp" ]
719         then
720                 echo "$backup_pkg_old"
721                 return
722         fi
723         if ( cd "${TMPDIR}"/package.tmp && pkg_create_b "$pkgname" > /dev/null )
724         then
725                 pkgname_ptn=`str_escape_regexp "$pkgname"`
726                 backup_pkg=`ls "${TMPDIR}"/package.tmp | \
727                         grep -m 1 -E "^${pkgname_ptn}\.(txz|tbz|tgz|tar)$"` || :
728         fi
729         if [ -z "$backup_pkg" ]
730         then
731                 message_echo "WARNING: Failed to create backup package for $pkgname." >&2
732                 return 1
733         fi
734         [ -d "$dstdir" ] || mkdir -p "$dstdir"
735         mv "${TMPDIR}/package.tmp/$backup_pkg" "$dstdir"
736         pkgpath=$dstdir/$backup_pkg
737         origin_regexp=`str_escape_regexp "$origin"`
738         cat "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null | \
739                 while read origin_cur pkgpath_cur
740                 do
741                         [ "$pkgpath_cur" = "$pkgpath" ] && continue
742                         if [ "$origin_cur" = "$origin" ]
743                         then
744                                 rm -f "$pkgpath_cur"
745                         else
746                                 printf '%s\t%s\n' "$origin_cur" "$pkgpath_cur"
747                         fi
748                 done > ${DBDIR}/backup_pkgarcs.lst.tmp
749         printf '%s\t%s\n' "$origin" "$pkgpath" >> ${DBDIR}/backup_pkgarcs.lst.tmp
750         mv "${DBDIR}/backup_pkgarcs.lst.tmp" "${DBDIR}/backup_pkgarcs.lst"
751         echo "$pkgpath"
752 }
753
754 # ============= Delete a back-up package archive for a port origin =============
755 pkgsys_delete_backup_pkg ()
756 {
757         local origin origin_regexp
758         origin=$1
759         origin_regexp=`str_escape_regexp "$origin"`
760         grep -E "^${origin_regexp}[[:space:]]" "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null \
761                 | cut -f 2 | while read pkgpath_cur
762                 do
763                         rm -f "$pkgpath_cur"
764                 done
765         grep -v -E "^${origin_regexp}[[:space:]]" "${DBDIR}/backup_pkgarcs.lst" \
766                 2> /dev/null > ${DBDIR}/backup_pkgarcs.lst.tmp || :
767         mv "${DBDIR}/backup_pkgarcs.lst.tmp" "${DBDIR}/backup_pkgarcs.lst"
768 }
769
770 # ============= Get an existing package archive path for a port origin =============
771 pkgsys_get_backup_pkg ()
772 {
773         local origin origin_regexp
774         origin=$1
775         tmpnewest=${TMPDIR}/pkgsys_get_backup_pkg::newest
776         origin_regexp=`str_escape_regexp "$origin"`
777         rm -f "$tmpnewest"
778         grep -E "^${origin_regexp}[[:space:]]" "${DBDIR}/backup_pkgarcs.lst" 2> /dev/null \
779                 | cut -f 2 | while read pkgpath
780         do
781                 pkgpath_newest=`cat "$tmpnewest" 2> /dev/null` || :
782                 [ -e "$pkgpath" ] || continue
783                 [ -z "$pkgpath_newest" -o "$pkgpath" -nt "$pkgpath_newest" ] || continue
784                 echo "$pkgpath" > $tmpnewest
785         done
786         cat "$tmpnewest" 2> /dev/null
787 }
788
789 # ============= Get a package name from a package archive file name =============
790 pkgsys_pkgarc_to_pkgname ()
791 {
792         local pkgfile_path
793         pkgfile_path=$1
794         basename "$pkgfile_path" | sed -E 's/\.(txz|tbz|tgz|tar)$//'
795 }
796
797 # ============= Get the file name of an existing package archive for a package name =============
798 pkgsys_pkgname_to_pkgarc ()
799 {
800         local pkgdir pkgname pkgname_ptn pkgnode
801         pkgdir=$1
802         pkgname=$2
803         [ -n "$pkgname" ] || return 1
804         [ -d "$pkgdir" ] || return 1
805         if [ "x$PKGSYS_USE_PKGNG" = xyes ]
806         then
807                 pkgname_ptn=`str_escape_regexp "$pkgname"`
808                 pkgnode=`ls "$pkgdir" 2> /dev/null | grep -m 1 -E "^${pkgname_ptn}\.(txz|tbz|tgz|tar)$"` || :
809         elif [ -e "$pkgdir/$pkgname.tbz" ]
810         then
811                 pkgnode=$pkgname.tbz
812         fi
813         [ -n "$pkgnode" ] || return 1
814         echo "$pkgdir/$pkgnode"
815 }
816
817 # ============= Get port origins matching a glob pattern even if nonexistent =============
818 pkgsys_eval_ports_glob_even_if_nonexistent ()
819 {
820         local glob_pattern
821         glob_pattern=$1
822         {
823                 pkgsys_eval_ports_glob "$glob_pattern" 2> /dev/null || :
824                 echo "$glob_pattern" | grep '^[a-z][a-z]*/[a-zA-Z0-9_+-][a-zA-Z0-9_+-]*$' || :
825         } | grep -v -e '^$' | sort -u
826 }
827
828 # ============= Evaluate glob patterns and add/remove non-existing/existing ones of them to/from a file =============
829 pkgsys_register_evaluated_globs ()
830 {
831         local mode listpath dirpath tmp_evaluated
832         mode=$1
833         listpath=$2
834         shift 2
835         dirpath=`dirname "$listpath"`
836         tmp_evaluated=${TMPDIR}/pkgsys_register_evaluated_globs:pkgsys_eval_ports_glob
837         echo "$@" | sed -E 's/[ :]+/\
838 /g' | grep -v '^$' | sort -u | while read glob
839         do
840                 pkgsys_eval_ports_glob "$glob" > $tmp_evaluated
841                 [ `wc -l < $tmp_evaluated` -ge 1 ] || \
842                 {
843                         message_echo "WARNING: No matching ports/package glob [$glob]." >&2
844                         continue
845                 }
846                 cat "$tmp_evaluated"
847         done | while read origin
848         do
849                 [ -d "$dirpath" ] || mkdir -p "$dirpath"
850                 case $mode in
851                 remove) fileedit_rm_a_line "$origin" "$listpath";;
852                 add)    fileedit_add_a_line_if_new "$origin" "$listpath";;
853                 esac
854         done
855 }
856
857 # ============= Evaluate glob patterns for installed packages =============
858 pkgsys_eval_installed_pkgs_globs ()
859 {
860         local tmp_evaluated
861         tmp_evaluated=${TMPDIR}/pkgsys_eval_installed_pkgs_globs:origins
862         rm -f "$tmp_evaluated"
863         pkgsys_register_evaluated_globs add "$tmp_evaluated" "$@"
864         [ -e "$tmp_evaluated" ] || return 0
865         while read origin
866         do
867                 pkgsys_pkg_info_eO "$origin" || echo "$origin"
868         done < $tmp_evaluated
869 }
870
871 # ============= Get conflicting packages of a port =============
872 pkgsys_get_conflicting_pkgs ()
873 {
874         local origin mode conflicts
875         mode=$1
876         origin=$2
877         conflicts=`database_query_get_makevar_val "$origin" CONFLICTS`
878         case $mode in
879         build)
880                 conflicts=$conflicts' '`database_query_get_makevar_val "$origin" CONFLICTS_BUILD`
881                 ;;
882         install)
883                 conflicts=$conflicts' '`database_query_get_makevar_val "$origin" CONFLICTS_INSTALL`
884                 ;;
885         esac
886         pkg_info_Eg $conflicts > ${TMPDIR}/pkgsys_get_conflicting_pkgs::conflicts || :
887         cat "${TMPDIR}/pkgsys_get_conflicting_pkgs::conflicts"
888         [ `wc -l < ${TMPDIR}/pkgsys_get_conflicting_pkgs::conflicts` -gt 0 ]
889 }