1#! /bin/sh
2
3# $NetBSD: mkpkgs,v 1.1 2012/01/15 02:01:02 agc Exp $
4
5# Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org>
6# All rights reserved.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions
10# are met:
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in the
15#    documentation and/or other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28
29# find next available vnd device, from kre
30next_avail ()
31{
32          local dev="$1"
33          local N=$(( ${#dev} + 1 ))
34          local unit units
35
36          units=$(
37                    sysctl -n hw.disknames                  |
38                              tr ' ' '\012'                 |
39                              grep '^'"${dev}"'[0-9]'       |
40                              sort -n -k 1.$N                         )
41
42          test -z "${units}" && {
43                    test -e "/dev/${dev}0a" || {
44                              echo >&2 "No ${dev}s available!"
45                              return 1
46                    }
47                    echo "${dev}0"
48                    return
49          }
50
51          N=0
52          for unit in ${units}
53          do
54                    if [ "${unit}" = "${dev}${N}" ]
55                    then
56                              N=$(( N + 1 ))
57                    else
58                              echo "${dev}${N}"
59                              return
60                    fi
61          done
62
63          test -e /dev/"${dev}${N}a" || {
64                    echo >&2 "All ${dev}s in use"
65                    return 1
66          }
67
68          echo "${dev}${N}"
69}
70
71# find the size of the gzipped files in a .tgz archive
72sizeone() {
73        case "$1" in
74        *.tgz|*.tar.gz)
75                tar tvzf "$1" | awk '{ tot += $5 } END { print tot }'
76                ;;
77        *.tbz|*.tar.bz2)
78                tar tvjf "$1" | awk '{ tot += $5 } END { print tot }'
79                ;;
80        *)
81                echo 0
82                ;;
83        esac
84}
85
86pkgdir=/usr/pkgsrc/packages/All
87size=0    # in MB
88image=pkgs.img
89pkgs="digest screen sudo"
90bar="==="
91
92while [ $# -gt 0 ]; do
93          case "$1" in
94          -S)       pkgdir=$2; shift ;;
95          -o)       image=$2; shift ;;
96          -s)       size=$2; shift ;;
97          -x)       set -x ;;
98          *)        break ;;
99          esac
100          shift
101done
102
103while [ $# -gt 0 ]; do
104          # take the next argument as being the image name
105          pkgs="${pkgs} $1"
106          shift
107done
108
109# find the size of the fs needed
110total=0
111for p in ${pkgs}; do
112          total=$(expr $total + $(sizeone ${pkgdir}/${p}-*.tgz))
113done
114total=$(expr \( $total / 1000000 \) + 2)
115if [ $size -eq 0 ]; then
116          # auto-size the pkgs fs
117          size=${total}
118else
119          # check that we've been given enough space
120          if [ ${total} -gt ${size} ]; then
121                    echo "File system size given as ${size} MB, but it needs ${total} MB" >&2
122                    exit 1
123          fi
124fi
125
126echo "${bar} making a new ${size} MB image in ${image} ${bar}"
127dd if=/dev/zero of=${image} bs=1m count=${size}
128
129vnddev=$(next_avail vnd)
130echo "${bar} mounting image via vnd ${vnddev} ${bar}"
131sudo vnconfig ${vnddev} ${image}
132sudo newfs /dev/r${vnddev}a
133sudo mount /dev/${vnddev}a /mnt
134
135echo "${bar} installing packages ${bar}"
136sudo mkdir -p /mnt/usr/pkg/.dbdir
137for p in ${pkgs}; do
138          echo "${bar} Installing ${p} ${bar}"
139          sudo pkg_add -K /usr/pkg/.dbdir -P /mnt -v ${pkgdir}/${p}-*.tgz
140done
141
142df /mnt
143
144sudo umount /mnt
145sudo vnconfig -u ${vnddev}
146
147exit 0
148