1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
#!/bin/sh
# $NetBSD: _NetBSD-pkgdb,v 1.1 2020/12/28 01:18:27 gdt Exp $
# Copyright The NetBSD Foundation 2020
# This script is for NetBSD only.
# This script is intended to help with the process of migration of
# PKG_DBDIR from /var/db/pkg to /usr/pkg/pkgdb on NetBSD. It can:
#
# "check" the system, changing nothing
#
# "fix" the system, leaving PKG_DBDIR as is and setting config files
# to point to it. Thus, one can easily postpone migration.
#
# "migrate" the system, moving the contents of PKG_DBDIR to the new
# location, and then setting pointers.
#
# In all cases, the script attempts to check assumptions it makes, and
# avoid trouble if those assumptions are not true.
# Note that PKG_DBDIR can be set in multiple places:
# /etc/pkg_install.conf (base tools)
# /usr/pkg/etc/pkg_install.conf (pkg tools)
# /etc/mk.conf (variable when buidling)
# /usr/pkgsrc/mk/ (default value of variable)
# This script takes the position that the PKG_DBDIR should be
# explicitly configured in pkg_install.conf in all cases, even if this
# is provably not necessary. The theory is that a bit of explicit
# config is much less work than mysterious debugging. If you don't
# like this, you are welcome to undo it, only use "check", or do the
# migration (or not) by hand.
# This script is aimed at the common case where the database was in
# /var/db/pkg and is moving to /usr/pkg/pkgdb, and sources are in
# /usr/pkgsrc (or a place that /usr/pkgsrc is symlinked to).
# This script should work to fix/migrate even on systems with older
# pkgsrc, e.g. if one wanted to stay on 2020Q3 on a system where the
# base system tools were updated. "Fix" will set variables so
# everything should work correctly.
# The script is designed to do incremental fixes, so if you migrate by
# hand but do not patch up the refcount directory, or set variables,
# it should (NB: This is UNTESTED!) do those steps when run.
# The script is intentionally written to be easy to understand (as
# long as one is comfortable with shell functions), rather than
# compact, avoid repeated code, or elegant.
# This script assumes:
# NetBSD 8 or newer
# pkgsrc after about 2020-12-20 (including 2020Q4)
# pkgsrc PREFIX as /usr/pkg
# old PKG_DBDIR as /var/db/pkg
# new/future PKG_DBDIR as /usr/pkg
# no symlinks in old or new PKG_DBDIR location
# base pkg_install may be old, or may be after the 2020-12 commit/pullups
# pkgsrc sources, if they exist, are in /usr/pkgsrc (perhaps a symlink)
# Set pathnames. Do not expect to set these differently without
# significant testing and thought.
OLDDB=/var/db/pkg
NEWDB=/usr/pkg/pkgdb
CONF_BASE=/etc/pkg_install.conf
CONF_PKG=/usr/pkg/etc/pkg_install.conf
PKGSRC=/usr/pkgsrc
# Shell functions to print messages of varying severity. (We choose
# to avoid fancy formatting entirely in this script.)
msg () {
echo "$*" >&2
}
warn () {
echo "WARNING: $*" >&2
}
fatal () {
echo "FATAL: $*" >&2
exit 1
}
usage () {
msg "_NetBSD-pkgdb: Usage:"
msg " check Check pkgdb status and explain it."
msg " fix Point config files at pkgdb location (don't move it)."
msg " migrate Check if migration can be done automatically, and if so do it."
exit 1
}
# Count problems. (Be sure not to use subshells when calling this.)
problems=0
problem_pp () {
problems=`expr $problems + 1`
}
problem_count () {
echo $problems
}
dir_exists () {
if [ ! -h "$1" -a -d "$1" ]; then
echo true
else
echo false
fi
}
# require_match string bool1 bool2
require_match () {
if [ "$2" != "$3" ]; then
fatal "mismatch $1"
problem_pp
fi
}
# Read pkg_install.conf PKG_DBDIR. One arg: config file
get_pkg_install_conf_DBDIR () {
CONF=$1
if [ "${CONF}" = "" ]; then
fatal "missing argument"
# dead code, left in case error is removed
echo ""
elif [ ! -f ${CONF} ]; then
warn "${CONF} does not exist"
echo ""
else
line=`egrep "^PKG_DBDIR.*=" ${CONF}`
if [ "$line" = "" ]; then
warn "${CONF} does not set PKG_DBDIR"
echo ""
else
value=`echo $line | awk -F= '{print $2}'`
echo $value
fi
fi
}
# Ensure prerequisites.
do_prereq () {
if [ `uname` != "NetBSD" ];then
fatal "OS is not NetBSD"
fi
# Check a subdir, in case /usr/pkg is a symlink.
if [ ! -d /usr/pkg/bin ]; then
fatal "/usr/pkg/bin is not a directory"
fi
}
# Check and maybe fix or migrate, depending on if fix=true or
# migrate=true. migrate=true and fix=false is not allowed.
do_steps () {
## STEP 0: Check if it is ok to operate at all.
do_prereq
## STEP 1: Sanity check database and figure out where it is.
# See if old or new exists, and check that they are in pairs.
OLD_DB1=`dir_exists ${OLDDB}`
OLD_DB2=`dir_exists ${OLDDB}.refcount`
require_match "$OLDDB directory pair" $OLD_DB1 $OLD_DB2
NEW_DB1=`dir_exists ${NEWDB}`
NEW_DB2=`dir_exists ${NEWDB}.refcount`
require_match "$NEWDB directory pair" $NEW_DB1 $NEW_DB2
# Check that we have one PKG_DBDIR, not zero and not two
if [ "$OLD_DB1" = false -a "$NEW_DB1" = false ]; then
fatal "No PKG_DBDIR found"
problem_pp
fi
if [ "$OLD_DB1" = true -a "$NEW_DB1" = true ]; then
fatal "TWO copies of PKG_DBDIR found"
problem_pp
fi
# Set a variable to the DBDIR we should be using, and the one we aren't.
if [ "$OLD_DB1" = true ]; then
PKG_DBDIR=$OLDDB
PKG_DBDIR_NOT=$NEWDB
elif [ "$NEW_DB1" = true ]; then
PKG_DBDIR=$NEWDB
PKG_DBDIR_NOT=$OLDDB
else
fatal "LOGIC ERROR IN SCRIPT 001"
exit 1
fi
unset OLD_DB1
unset OLD_DB2
unset NEW_DB1
unset OLD_DB2
echo "Found PKG_DBDIR as $PKG_DBDIR."
## Step 2a: check migrate/fix prereqs
if [ "$fix" = true ]; then
warn "THIS SCRIPT IS NOT YET ADEQUATELY TESTED."
warn "Hit ^C NOW if you do not have a good backup."
warn "Proceeding in 10 seconds..."
sleep 10
if [ `id -u` != 0 ]; then
fatal "Not root: will not be able to fix or migrate"
fi
fi
## Step 2: migrate if requested
if [ "$migrate" = true ]; then
if [ "$fix" != true ]; then
fatal "LOGIC ERROR IN SCRIPT 002"
fi
if [ "$PKG_DBDIR" = "${NEWDB}" ]; then
warn "migrate requested when already done"
# This is not really an error.
else
msg "Doing migration..."
msg "NB: refcount will have many fixups; this is normal."
# Actual migration is easy.
mv $OLDDB $NEWDB
mv $OLDDB.refcount $NEWDB.refcount
# Change our tracking variables so that later fixups do
# the right thing.
PKG_DBDIR=$NEWDB
PKG_DBDIR_NOT=$OLDDB
msg "Migration done, except for refcount fixups."
fi
fi
## Step 3: Check/fix refcount
if [ "$fix" = true ]; then
# Check all files, even though only some have paths.
find ${PKG_DBDIR}.refcount -type f | while read file; do
if egrep $PKG_DBDIR_NOT $file > /dev/null; then
echo WRONG PATH $file
sed -i -e "s,${PKG_DBDIR_NOT},${PKG_DBDIR}," $file
problem_pp
fi
done
fi
## Step 4: Check PKG_DBDIR variables and fix if requested.
# Check that both pkg_install configs point to the actual PKG_DBDIR.
conf_base_DBDIR=`get_pkg_install_conf_DBDIR $CONF_BASE`
if [ "$conf_base_DBDIR" != "${PKG_DBDIR}" ]; then
warn "$CONF_BASE does not set PKG_DBDIR to ${PKG_DBDIR}"
if [ "$fix" = true ]; then
[ -f ${CONF_BASE} ] && cp -p ${CONF_BASE} ${CONF_BASE}.pre-migration
sed -i -e '/^PKG_DBDIR=/d' ${CONF_BASE}
echo "PKG_DBDIR=${PKG_DBDIR}" >> ${CONF_BASE}
fi
problem_pp
fi
conf_pkg_DBDIR=`get_pkg_install_conf_DBDIR $CONF_PKG`
if [ "$conf_pkg_DBDIR" != "${PKG_DBDIR}" ]; then
warn "$CONF_PKG does not set PKG_DBDIR to ${PKG_DBDIR}"
if [ "$fix" = true ]; then
[ -f ${CONF_PKG} ] && cp -p ${CONF_PKG} ${CONF_PKG}.pre-migration
sed -i -e '/^PKG_DBDIR=/d' ${CONF_PKG}
echo "PKG_DBDIR=${PKG_DBDIR}" >> ${CONF_PKG}
fi
problem_pp
fi
# Check mk.conf via pkgsrc. Really, check that the variable is
# set when running in an example package, because it is relatively
# normal to use .include and we decline to re-implement make.
if [ -d ${PKGSRC}/mk ]; then
# Avoid a subshell so problem_pp works.
SAVE=`pwd`
cd $PKGSRC
PKGSRC_DBDIR=`cd devel/m4 && make show-var VARNAME=PKG_DBDIR`
if [ "$PKGSRC_DBDIR" != "${PKG_DBDIR}" ]; then
warn "$PKG_DBDIR via pkgsrc/mk does not set PKG_DBDIR to ${PKG_DBDIR}"
# This may have failed for other reasons, but if so running again won't
# fix it.
if [ "$fix" = true ]; then
sed -i -e '/^PKG_DBDIR=/d' /etc/mk.conf
echo "PKG_DBDIR=${PKG_DBDIR}" >> /etc/mk.conf
fi
problem_pp
fi
cd $SAVE
unset SAVE
else
msg "NB: Did not find ${PKGSRC} -- did not check mk.conf"
msg " If your system does not have sources, this is ok. If it does, symlink"
msg " ${PKGSRC} to the sources and rerun the check."
fi
}
main() {
if [ "$#" != 1 ]; then
usage
fi
case "$1" in
check)
do_steps
;;
fix)
fix=true;
do_steps
;;
migrate)
fix=true
migrate=true;
do_steps
;;
*)
warn Unknown option $1
usage
;;
esac
count=`problem_count`
if [ "$count" = 0 ]; then
msg "No problems found."
else
msg "TOTAL PROBLEMS FOUND: $count"
msg "Re-run script until there are no problems!"
fi
}
main $*
|