aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Unit 193 <unit193@ubuntu.com>2018-03-20 22:56:16 -0400
committerLibravatar Unit 193 <unit193@ubuntu.com>2018-03-20 22:56:16 -0400
commitd929c8cbc09732337fb4805accbf3564e9cca0bb (patch)
tree27f71b63f26cdf0ef957ce2d7390f5991561b839
downloadarch-install-scripts-d929c8cbc09732337fb4805accbf3564e9cca0bb.tar.bz2
arch-install-scripts-d929c8cbc09732337fb4805accbf3564e9cca0bb.tar.xz
arch-install-scripts-d929c8cbc09732337fb4805accbf3564e9cca0bb.tar.zst
Import Upstream version 18upstream/18
-rw-r--r--COPYING339
-rw-r--r--Makefile43
-rw-r--r--README.md15
-rw-r--r--arch-chroot.in78
-rw-r--r--common252
-rw-r--r--genfstab.in230
-rw-r--r--pacstrap.in119
-rw-r--r--test/common45
-rwxr-xr-xtest/test_mangle8
-rwxr-xr-xtest/test_option_twiddling55
-rwxr-xr-xtest/test_valid_number_of_base15
-rw-r--r--zsh-completion164
12 files changed, 1363 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6824f3f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+VER=18
+
+PREFIX = /usr/local
+
+BINPROGS = \
+ arch-chroot \
+ genfstab \
+ pacstrap
+
+BASH = bash
+
+all: $(BINPROGS)
+
+V_GEN = $(_v_GEN_$(V))
+_v_GEN_ = $(_v_GEN_0)
+_v_GEN_0 = @echo " GEN " $@;
+
+edit = $(V_GEN) m4 -P $@.in >$@ && chmod go-w,+x $@
+
+%: %.in common
+ $(edit)
+
+clean:
+ $(RM) $(BINPROGS)
+
+check: all
+ @for f in $(BINPROGS); do bash -O extglob -n $$f; done
+ @r=0; for t in test/test_*; do $(BASH) $$t || { echo $$t fail; r=1; }; done; exit $$r
+
+install: all
+ install -dm755 $(DESTDIR)$(PREFIX)/bin
+ install -m755 $(BINPROGS) $(DESTDIR)$(PREFIX)/bin
+ install -Dm644 zsh-completion $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_archinstallscripts
+
+uninstall:
+ for f in $(BINPROGS); do $(RM) $(DESTDIR)$(PREFIX)/bin/$$f; done
+ $(RM) $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_archinstallscripts
+
+dist:
+ git archive --format=tar --prefix=arch-install-scripts-$(VER)/ v$(VER) | gzip -9 > arch-install-scripts-$(VER).tar.gz
+ gpg --detach-sign --use-agent arch-install-scripts-$(VER).tar.gz
+
+.PHONY: all clean install uninstall dist
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..34aff43
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# Arch Install Scripts
+
+This is a small suite of scripts aimed at automating some menial
+tasks when installing [Arch Linux](https://www.archlinux.org).
+
+## Requirements
+
+* GNU coreutils (>= v8.15)
+* util-linux (>= 2.23)
+* POSIX awk
+* bash (>= 4.1)
+
+## License
+
+See COPYING for details.
diff --git a/arch-chroot.in b/arch-chroot.in
new file mode 100644
index 0000000..a954953
--- /dev/null
+++ b/arch-chroot.in
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+shopt -s extglob
+
+m4_include(common)
+
+usage() {
+ cat <<EOF
+usage: ${0##*/} chroot-dir [command]
+
+ -h Print this help message
+ -u <user>[:group] Specify non-root user and optional group to use
+
+If 'command' is unspecified, ${0##*/} will launch /bin/bash.
+
+EOF
+}
+
+chroot_add_resolv_conf() {
+ local chrootdir=$1 resolv_conf=$1/etc/resolv.conf
+
+ # Handle resolv.conf as a symlink to somewhere else.
+ if [[ -L $chrootdir/etc/resolv.conf ]]; then
+ # readlink(1) should always give us *something* since we know at this point
+ # it's a symlink. For simplicity, ignore the case of nested symlinks.
+ resolv_conf=$(readlink "$chrootdir/etc/resolv.conf")
+ if [[ $resolv_conf = /* ]]; then
+ resolv_conf=$chrootdir$resolv_conf
+ else
+ resolv_conf=$chrootdir/etc/$resolv_conf
+ fi
+
+ # ensure file exists to bind mount over
+ if [[ ! -f $resolv_conf ]]; then
+ install -Dm644 /dev/null "$resolv_conf" || return 1
+ fi
+ elif [[ ! -e $chrootdir/etc/resolv.conf ]]; then
+ # The chroot might not have a resolv.conf.
+ return 0
+ fi
+
+ chroot_add_mount /etc/resolv.conf "$resolv_conf" --bind
+}
+
+while getopts ':hu:' flag; do
+ case $flag in
+ h)
+ usage
+ exit 0
+ ;;
+ u)
+ userspec=$OPTARG
+ ;;
+ :)
+ die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
+ ;;
+ ?)
+ die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
+ ;;
+ esac
+done
+shift $(( OPTIND - 1 ))
+
+(( EUID == 0 )) || die 'This script must be run with root privileges'
+(( $# )) || die 'No chroot directory specified'
+chrootdir=$1
+shift
+
+[[ -d $chrootdir ]] || die "Can't create chroot on non-directory %s" "$chrootdir"
+
+chroot_setup "$chrootdir" || die "failed to setup chroot %s" "$chrootdir"
+chroot_add_resolv_conf "$chrootdir" || die "failed to setup resolv.conf"
+
+chroot_args=()
+[[ $userspec ]] && chroot_args+=(--userspec "$userspec")
+chroot_args+=("$chrootdir" "$@")
+
+SHELL=/bin/bash unshare --fork --pid chroot "${chroot_args[@]}"
diff --git a/common b/common
new file mode 100644
index 0000000..65f3362
--- /dev/null
+++ b/common
@@ -0,0 +1,252 @@
+# generated from util-linux source: libmount/src/utils.c
+declare -A pseudofs_types=([anon_inodefs]=1
+ [autofs]=1
+ [bdev]=1
+ [binfmt_misc]=1
+ [cgroup]=1
+ [cgroup2]=1
+ [configfs]=1
+ [cpuset]=1
+ [debugfs]=1
+ [devfs]=1
+ [devpts]=1
+ [devtmpfs]=1
+ [dlmfs]=1
+ [fuse.gvfs-fuse-daemon]=1
+ [fusectl]=1
+ [hugetlbfs]=1
+ [mqueue]=1
+ [nfsd]=1
+ [none]=1
+ [pipefs]=1
+ [proc]=1
+ [pstore]=1
+ [ramfs]=1
+ [rootfs]=1
+ [rpc_pipefs]=1
+ [securityfs]=1
+ [sockfs]=1
+ [spufs]=1
+ [sysfs]=1
+ [tmpfs]=1)
+
+# generated from: pkgfile -vbr '/fsck\..+' | awk -F. '{ print $NF }' | sort
+declare -A fsck_types=([cramfs]=1
+ [exfat]=1
+ [ext2]=1
+ [ext3]=1
+ [ext4]=1
+ [ext4dev]=1
+ [jfs]=1
+ [minix]=1
+ [msdos]=1
+ [reiserfs]=1
+ [vfat]=1
+ [xfs]=1)
+
+out() { printf "$1 $2\n" "${@:3}"; }
+error() { out "==> ERROR:" "$@"; } >&2
+msg() { out "==>" "$@"; }
+msg2() { out " ->" "$@";}
+die() { error "$@"; exit 1; }
+
+ignore_error() {
+ "$@" 2>/dev/null
+ return 0
+}
+
+in_array() {
+ local i
+ for i in "${@:2}"; do
+ [[ $1 = "$i" ]] && return 0
+ done
+ return 1
+}
+
+chroot_add_mount() {
+ mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}")
+}
+
+chroot_maybe_add_mount() {
+ local cond=$1; shift
+ if eval "$cond"; then
+ chroot_add_mount "$@"
+ fi
+}
+
+chroot_setup() {
+ CHROOT_ACTIVE_MOUNTS=()
+ [[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap'
+ trap 'chroot_teardown' EXIT
+
+ chroot_add_mount proc "$1/proc" -t proc -o nosuid,noexec,nodev &&
+ chroot_add_mount sys "$1/sys" -t sysfs -o nosuid,noexec,nodev,ro &&
+ ignore_error chroot_maybe_add_mount "[[ -d '$1/sys/firmware/efi/efivars' ]]" \
+ efivarfs "$1/sys/firmware/efi/efivars" -t efivarfs -o nosuid,noexec,nodev &&
+ chroot_add_mount udev "$1/dev" -t devtmpfs -o mode=0755,nosuid &&
+ chroot_add_mount devpts "$1/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec &&
+ chroot_add_mount shm "$1/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev &&
+ chroot_add_mount run "$1/run" -t tmpfs -o nosuid,nodev,mode=0755 &&
+ chroot_add_mount tmp "$1/tmp" -t tmpfs -o mode=1777,strictatime,nodev,nosuid
+}
+
+chroot_teardown() {
+ umount "${CHROOT_ACTIVE_MOUNTS[@]}"
+ unset CHROOT_ACTIVE_MOUNTS
+}
+
+try_cast() (
+ _=$(( $1#$2 ))
+) 2>/dev/null
+
+valid_number_of_base() {
+ local base=$1 len=${#2} i=
+
+ for (( i = 0; i < len; i++ )); do
+ try_cast "$base" "${2:i:1}" || return 1
+ done
+
+ return 0
+}
+
+mangle() {
+ local i= chr= out=
+ local {a..f}= {A..F}=
+
+ for (( i = 0; i < ${#1}; i++ )); do
+ chr=${1:i:1}
+ case $chr in
+ [[:space:]\\])
+ printf -v chr '%03o' "'$chr"
+ out+=\\
+ ;;
+ esac
+ out+=$chr
+ done
+
+ printf '%s' "$out"
+}
+
+unmangle() {
+ local i= chr= out= len=$(( ${#1} - 4 ))
+ local {a..f}= {A..F}=
+
+ for (( i = 0; i < len; i++ )); do
+ chr=${1:i:1}
+ case $chr in
+ \\)
+ if valid_number_of_base 8 "${1:i+1:3}" ||
+ valid_number_of_base 16 "${1:i+1:3}"; then
+ printf -v chr '%b' "${1:i:4}"
+ (( i += 3 ))
+ fi
+ ;;
+ esac
+ out+=$chr
+ done
+
+ printf '%s' "$out${1:i}"
+}
+
+optstring_match_option() {
+ local candidate pat patterns
+
+ IFS=, read -ra patterns <<<"$1"
+ for pat in "${patterns[@]}"; do
+ if [[ $pat = *=* ]]; then
+ # "key=val" will only ever match "key=val"
+ candidate=$2
+ else
+ # "key" will match "key", but also "key=anyval"
+ candidate=${2%%=*}
+ fi
+
+ [[ $pat = "$candidate" ]] && return 0
+ done
+
+ return 1
+}
+
+optstring_remove_option() {
+ local o options_ remove=$2 IFS=,
+
+ read -ra options_ <<<"${!1}"
+
+ for o in "${!options_[@]}"; do
+ optstring_match_option "$remove" "${options_[o]}" && unset 'options_[o]'
+ done
+
+ declare -g "$1=${options_[*]}"
+}
+
+optstring_normalize() {
+ local o options_ norm IFS=,
+
+ read -ra options_ <<<"${!1}"
+
+ # remove empty fields
+ for o in "${options_[@]}"; do
+ [[ $o ]] && norm+=("$o")
+ done
+
+ # avoid empty strings, reset to "defaults"
+ declare -g "$1=${norm[*]:-defaults}"
+}
+
+optstring_append_option() {
+ if ! optstring_has_option "$1" "$2"; then
+ declare -g "$1=${!1},$2"
+ fi
+
+ optstring_normalize "$1"
+}
+
+optstring_prepend_option() {
+ local options_=$1
+
+ if ! optstring_has_option "$1" "$2"; then
+ declare -g "$1=$2,${!1}"
+ fi
+
+ optstring_normalize "$1"
+}
+
+optstring_get_option() {
+ local opts o
+
+ IFS=, read -ra opts <<<"${!1}"
+ for o in "${opts[@]}"; do
+ if optstring_match_option "$2" "$o"; then
+ declare -g "$o"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+optstring_has_option() {
+ local "${2%%=*}"
+
+ optstring_get_option "$1" "$2"
+}
+
+dm_name_for_devnode() {
+ read dm_name <"/sys/class/block/${1#/dev/}/dm/name"
+ if [[ $dm_name ]]; then
+ printf '/dev/mapper/%s' "$dm_name"
+ else
+ # don't leave the caller hanging, just print the original name
+ # along with the failure.
+ print '%s' "$1"
+ error 'Failed to resolve device mapper name for: %s' "$1"
+ fi
+}
+
+fstype_is_pseudofs() {
+ (( pseudofs_types["$1"] ))
+}
+
+fstype_has_fsck() {
+ (( fsck_types["$1"] ))
+}
diff --git a/genfstab.in b/genfstab.in
new file mode 100644
index 0000000..1e8a2c8
--- /dev/null
+++ b/genfstab.in
@@ -0,0 +1,230 @@
+#!/bin/bash
+
+shopt -s extglob
+
+m4_include(common)
+
+write_source() {
+ local src=$1 spec= label= uuid= comment=()
+
+ label=$(lsblk -rno LABEL "$1" 2>/dev/null)
+ uuid=$(lsblk -rno UUID "$1" 2>/dev/null)
+
+ # bind mounts do not have a UUID!
+
+ case $bytag in
+ '')
+ [[ $uuid ]] && comment=("UUID=$uuid")
+ [[ $label ]] && comment+=("LABEL=$(mangle "$label")")
+ ;;
+ LABEL)
+ spec=$label
+ [[ $uuid ]] && comment=("$src" "UUID=$uuid")
+ ;;
+ UUID)
+ spec=$uuid
+ comment=("$src")
+ [[ $label ]] && comment+=("LABEL=$(mangle "$label")")
+ ;;
+ *)
+ [[ $uuid ]] && comment=("$1" "UUID=$uuid")
+ [[ $label ]] && comment+=("LABEL=$(mangle "$label")")
+ [[ $bytag ]] && spec=$(lsblk -rno "$bytag" "$1" 2>/dev/null)
+ ;;
+ esac
+
+ [[ $comment ]] && printf '# %s\n' "${comment[*]}"
+
+ if [[ $spec ]]; then
+ printf '%-20s' "$bytag=$(mangle "$spec")"
+ else
+ printf '%-20s' "$(mangle "$src")"
+ fi
+}
+
+optstring_apply_quirks() {
+ local varname=$1 fstype=$2
+
+ # SELinux displays a 'seclabel' option in /proc/self/mountinfo. We can't know
+ # if the system we're generating the fstab for has any support for SELinux (as
+ # one might install Arch from a Fedora environment), so let's remove it.
+ optstring_remove_option "$varname" seclabel
+
+ # Prune 'relatime' option for any pseudofs. This seems to be a rampant
+ # default which the kernel often exports even if the underlying filesystem
+ # doesn't support it. Example: https://bugs.archlinux.org/task/54554.
+ if awk -v fstype="$fstype" '$1 == fstype { exit 1 }' /proc/filesystems; then
+ optstring_remove_option "$varname" relatime
+ fi
+
+ case $fstype in
+ f2fs)
+ # These are Kconfig options for f2fs. Kernels supporting the options will
+ # only provide the negative versions of these (e.g. noacl), and vice versa
+ # for kernels without support.
+ optstring_remove_option "$varname" noacl,acl,nouser_xattr,user_xattr
+ ;;
+ vfat)
+ # Before Linux v3.8, "cp" is prepended to the value of the codepage.
+ if optstring_get_option "$varname" codepage && [[ $codepage = cp* ]]; then
+ optstring_remove_option "$varname" codepage
+ optstring_append_option "$varname" "codepage=${codepage#cp}"
+ fi
+ ;;
+ esac
+}
+
+usage() {
+ cat <<EOF
+usage: ${0##*/} [options] root
+
+ Options:
+ -L Use labels for source identifiers (shortcut for -t LABEL)
+ -p Exclude pseudofs mounts (default behavior)
+ -P Include pseudofs mounts
+ -t TAG Use TAG for source identifiers
+ -U Use UUIDs for source identifiers (shortcut for -t UUID)
+
+ -h Print this help message
+
+genfstab generates output suitable for addition to an fstab file based on the
+devices mounted under the mountpoint specified by the given root.
+
+EOF
+}
+
+if [[ -z $1 || $1 = @(-h|--help) ]]; then
+ usage
+ exit $(( $# ? 0 : 1 ))
+fi
+
+while getopts ':LPpt:U' flag; do
+ case $flag in
+ L)
+ bytag=LABEL
+ ;;
+ U)
+ bytag=UUID
+ ;;
+ P)
+ pseudofs=1
+ ;;
+ p)
+ pseudofs=0
+ ;;
+ t)
+ bytag=${OPTARG^^}
+ ;;
+ :)
+ die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
+ ;;
+ ?)
+ die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
+ ;;
+ esac
+done
+shift $(( OPTIND - 1 ))
+
+(( $# )) || die "No root directory specified"
+root=$(realpath -mL "$1"); shift
+
+if ! mountpoint -q "$root"; then
+ die "$root is not a mountpoint"
+fi
+
+# handle block devices
+findmnt -Recvruno SOURCE,TARGET,FSTYPE,OPTIONS,FSROOT "$root" |
+ while read -r src target fstype opts fsroot; do
+ if (( !pseudofs )) && fstype_is_pseudofs "$fstype"; then
+ continue
+ fi
+
+ # default 5th and 6th columns
+ dump=0 pass=2
+
+ src=$(unmangle "$src")
+ target=$(unmangle "$target")
+ target=${target#$root}
+
+ if (( !foundroot )) && findmnt "$src" "$root" >/dev/null; then
+ # this is root. we can't possibly have more than one...
+ pass=1 foundroot=1
+ fi
+
+ # if there's no fsck tool available, then only pass=0 makes sense.
+ if ! fstype_has_fsck "$fstype"; then
+ pass=0
+ fi
+
+ if [[ $fsroot != / ]]; then
+ if [[ $fstype = btrfs ]]; then
+ opts+=,subvol=${fsroot#/}
+ else
+ # it's a bind mount
+ src=$(findmnt -funcevo TARGET "$src")$fsroot
+ if [[ $src -ef $target ]]; then
+ # hrmm, this is weird. we're probably looking at a file or directory
+ # that was bound into a chroot from the host machine. Ignore it,
+ # because this won't actually be a valid mount. Worst case, the user
+ # just re-adds it.
+ continue
+ fi
+ fstype=none
+ opts+=,bind
+ pass=0
+ fi
+ fi
+
+ # filesystem quirks
+ case $fstype in
+ fuseblk)
+ # well-behaved FUSE filesystems will report themselves as fuse.$fstype.
+ # this is probably NTFS-3g, but let's just make sure.
+ if ! newtype=$(lsblk -no FSTYPE "$src") || [[ -z $newtype ]]; then
+ # avoid blanking out fstype, leading to an invalid fstab
+ error 'Failed to derive real filesystem type for FUSE device on %s' "$target"
+ else
+ fstype=$newtype
+ fi
+ ;;
+ esac
+
+ optstring_apply_quirks "opts" "$fstype"
+
+ # write one line
+ write_source "$src"
+ printf '\t%-10s' "/$(mangle "${target#/}")" "$fstype" "$opts"
+ printf '\t%s %s' "$dump" "$pass"
+ printf '\n\n'
+done
+
+# handle swaps devices
+{
+ # ignore header
+ read
+
+ while read -r device type _ _ prio; do
+ options=defaults
+ if [[ $prio != -1 ]]; then
+ options+=,pri=$prio
+ fi
+
+ # skip files marked deleted by the kernel
+ [[ $device = *'\040(deleted)' ]] && continue
+
+ if [[ $type = file ]]; then
+ printf '%-20s' "$device"
+ elif [[ $device = /dev/dm-+([0-9]) ]]; then
+ # device mapper doesn't allow characters we need to worry
+ # about being mangled, and it does the escaping of dashes
+ # for us in sysfs.
+ write_source "$(dm_name_for_devnode "$device")"
+ else
+ write_source "$(unmangle "$device")"
+ fi
+
+ printf '\t%-10s\t%-10s\t%-10s\t0 0\n\n' 'none' 'swap' "$options"
+ done
+} </proc/swaps
+
+# vim: et ts=2 sw=2 ft=sh:
diff --git a/pacstrap.in b/pacstrap.in
new file mode 100644
index 0000000..72f2809
--- /dev/null
+++ b/pacstrap.in
@@ -0,0 +1,119 @@
+#!/bin/bash
+
+#
+# Assumptions:
+# 1) User has partitioned, formatted, and mounted partitions on /mnt
+# 2) Network is functional
+# 3) Arguments passed to the script are valid pacman targets
+# 4) A valid mirror appears in /etc/pacman.d/mirrorlist
+#
+
+shopt -s extglob
+
+m4_include(common)
+
+hostcache=0
+copykeyring=1
+copymirrorlist=1
+
+usage() {
+ cat <<EOF
+usage: ${0##*/} [options] root [packages...]
+
+ Options:
+ -C config Use an alternate config file for pacman
+ -c Use the package cache on the host, rather than the target
+ -G Avoid copying the host's pacman keyring to the target
+ -i Avoid auto-confirmation of package selections
+ -M Avoid copying the host's mirrorlist to the target
+
+ -h Print this help message
+
+pacstrap installs packages to the specified new root directory. If no packages
+are given, pacstrap defaults to the "base" group.
+
+EOF
+}
+
+if [[ -z $1 || $1 = @(-h|--help) ]]; then
+ usage
+ exit $(( $# ? 0 : 1 ))
+fi
+
+(( EUID == 0 )) || die 'This script must be run with root privileges'
+
+while getopts ':C:cdGiM' flag; do
+ case $flag in
+ C)
+ pacman_config=$OPTARG
+ ;;
+ d)
+ # retired flag. does nothing.
+ ;;
+ c)
+ hostcache=1
+ ;;
+ i)
+ interactive=1
+ ;;
+ G)
+ copykeyring=0
+ ;;
+ M)
+ copymirrorlist=0
+ ;;
+ :)
+ die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
+ ;;
+ ?)
+ die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
+ ;;
+ esac
+done
+shift $(( OPTIND - 1 ))
+
+(( $# )) || die "No root directory specified"
+newroot=$1; shift
+pacman_args=("${@:-base}")
+
+if (( ! hostcache )); then
+ pacman_args+=(--cachedir="$newroot/var/cache/pacman/pkg")
+fi
+
+if (( ! interactive )); then
+ pacman_args+=(--noconfirm)
+fi
+
+if [[ $pacman_config ]]; then
+ pacman_args+=(--config="$pacman_config")
+fi
+
+[[ -d $newroot ]] || die "%s is not a directory" "$newroot"
+
+# create obligatory directories
+msg 'Creating install root at %s' "$newroot"
+mkdir -m 0755 -p "$newroot"/var/{cache/pacman/pkg,lib/pacman,log} "$newroot"/{dev,run,etc}
+mkdir -m 1777 -p "$newroot"/tmp
+mkdir -m 0555 -p "$newroot"/{sys,proc}
+
+# mount API filesystems
+chroot_setup "$newroot" || die "failed to setup chroot %s" "$newroot"
+
+msg 'Installing packages to %s' "$newroot"
+if ! pacman -r "$newroot" -Sy "${pacman_args[@]}"; then
+ die 'Failed to install packages to new root'
+fi
+
+if (( copykeyring )); then
+ # if there's a keyring on the host, copy it into the new root, unless it exists already
+ if [[ -d /etc/pacman.d/gnupg && ! -d $newroot/etc/pacman.d/gnupg ]]; then
+ cp -a /etc/pacman.d/gnupg "$newroot/etc/pacman.d/"
+ fi
+fi
+
+if (( copymirrorlist )); then
+ # install the host's mirrorlist onto the new root
+ cp -a /etc/pacman.d/mirrorlist "$newroot/etc/pacman.d/"
+fi
+
+# vim: et ts=2 sw=2 ft=sh:
diff --git a/test/common b/test/common
new file mode 100644
index 0000000..8773077
--- /dev/null
+++ b/test/common
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+fail=0
+testcount=0
+
+EXPECT_success() {
+ (( ++testcount ))
+ if ! "$@"; then
+ (( ++fail ))
+ printf 'expectation failed: did not succeed: %s\n' "$*" >&2
+ fi
+}
+
+EXPECT_failure() {
+ (( ++testcount ))
+ if "$@"; then
+ (( ++fail ))
+ printf 'expectation failed: did not fail: %s\n' "$*" >&2
+ fi
+}
+
+TEST_exit() {
+ local result
+
+ trap -- EXIT
+
+ (( fail == 0 )) && result=PASS || result=FAIL
+
+ printf '%s: %s\n' "$result" "$1"
+
+ exit $(( fail != 0 ))
+}
+
+ASSERT_streq() {
+ if [[ $1 != "$2" ]]; then
+ printf 'assertion failed [line %d]: [[ %s = "%s" ]]\n' "$BASH_LINENO" "$1" "$2" >&2
+ fi
+}
+
+TEST_start() {
+ trap "TEST_exit '$1'" EXIT
+}
+
+TEST_start "${0##*/test_}"
+
diff --git a/test/test_mangle b/test/test_mangle
new file mode 100755
index 0000000..d9b61b1
--- /dev/null
+++ b/test/test_mangle
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+. "${1:-./common}"
+. ./test/common
+
+ASSERT_streq ' deleted' "$(unmangle "$(mangle ' deleted')")"
+ASSERT_streq '\040deleted' "$(mangle "$(unmangle '\040deleted')")"
+ASSERT_streq 'foo\011\040\011bar' "$(mangle $'foo\t \tbar')"
diff --git a/test/test_option_twiddling b/test/test_option_twiddling
new file mode 100755
index 0000000..214a63c
--- /dev/null
+++ b/test/test_option_twiddling
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+. "${1:-./common}"
+. ./test/common
+
+optstring=rw,relatime,fd=29,pgrp=1,timeout=300,minproto=5,maxproto=5,direct
+optstring_remove_option optstring fd
+optstring_remove_option optstring pgrp=400
+ASSERT_streq "$optstring" 'rw,relatime,pgrp=1,timeout=300,minproto=5,maxproto=5,direct'
+
+optstring_append_option optstring pgrp=400
+optstring_append_option optstring pgrp=400
+optstring_append_option optstring pgrp=400
+ASSERT_streq "$optstring" 'rw,relatime,pgrp=1,timeout=300,minproto=5,maxproto=5,direct,pgrp=400'
+
+optstring_prepend_option optstring pgrp=600
+optstring_prepend_option optstring pgrp=600
+optstring_prepend_option optstring pgrp=600
+ASSERT_streq "$optstring" 'pgrp=600,rw,relatime,pgrp=1,timeout=300,minproto=5,maxproto=5,direct,pgrp=400'
+
+EXPECT_success optstring_has_option optstring pgrp=400
+EXPECT_success optstring_has_option optstring pgrp=1
+EXPECT_success optstring_has_option optstring pgrp
+EXPECT_failure optstring_has_option optstring maxproto=6
+EXPECT_success optstring_has_option optstring maxproto
+
+EXPECT_failure optstring_get_option optstring proto
+EXPECT_success optstring_get_option optstring maxproto
+ASSERT_streq "$maxproto" "5"
+EXPECT_success optstring_get_option optstring timeout
+ASSERT_streq "$timeout" "300"
+
+optstring_remove_option optstring pgrp
+ASSERT_streq "$optstring" 'rw,relatime,timeout=300,minproto=5,maxproto=5,direct'
+
+optstring_remove_option optstring minproto,relatime
+ASSERT_streq "$optstring" 'rw,timeout=300,maxproto=5,direct'
+
+optstring_remove_option optstring ro,direct
+ASSERT_streq "$optstring" 'rw,timeout=300,maxproto=5'
+
+optstring=,,,,,,defaults,,,,rw,,,,,,minproto=5,,,
+optstring_normalize optstring
+ASSERT_streq "$optstring" 'defaults,rw,minproto=5'
+
+
+optstring=
+optstring_normalize optstring
+ASSERT_streq "$optstring" 'defaults'
+
+
+EXPECT_success optstring_match_option key key=val
+EXPECT_success optstring_match_option key=val key=val
+EXPECT_failure optstring_match_option key=val key=val2
+EXPECT_failure optstring_match_option 'key=*' key=val2
diff --git a/test/test_valid_number_of_base b/test/test_valid_number_of_base
new file mode 100755
index 0000000..5afdc59
--- /dev/null
+++ b/test/test_valid_number_of_base
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. "${1:-./common}"
+. ./test/common
+
+EXPECT_success valid_number_of_base 16 feedfacebeef
+EXPECT_failure valid_number_of_base 16 feedsfacebeef
+EXPECT_success valid_number_of_base 16 1234567890
+
+EXPECT_success valid_number_of_base 10 1234567890
+EXPECT_failure valid_number_of_base 10 1234.567890
+EXPECT_failure valid_number_of_base 10 1234567890abcdef
+
+EXPECT_success valid_number_of_base 18 1234567890abcdefgh
+EXPECT_failure valid_number_of_base 18 1234567890abcdefghi
diff --git a/zsh-completion b/zsh-completion
new file mode 100644
index 0000000..bc4e4d3
--- /dev/null
+++ b/zsh-completion
@@ -0,0 +1,164 @@
+#compdef pacstrap genfstab arch-chroot
+
+_pacstrap_args=(
+ '-h[display help]'
+)
+
+_pacstrap_args_nonh=(
+ '(-h --help)-c[Use the package cache on the host, rather than the target]'
+ '(-h --help)-d[Allow installation to a non-mountpoint directory]'
+ '(--help -h)-i[Avoid auto-confirmation of package selections]'
+)
+
+
+# builds command for invoking pacman in a _call_program command - extracts
+# relevant options already specified (config file, etc)
+# $cmd must be declared by calling function
+_pacman_get_command() {
+ # this is mostly nicked from _perforce
+ cmd=( "pacman" "2>/dev/null")
+ integer i
+ for (( i = 2; i < CURRENT - 1; i++ )); do
+ if [[ ${words[i]} = "--config" || ${words[i]} = "--root" ]]; then
+ cmd+=( ${words[i,i+1]} )
+ fi
+ done
+}
+
+# provides completions for packages available from repositories
+# these can be specified as either 'package' or 'repository/package'
+_pacman_completions_all_packages() {
+ local -a cmd packages repositories packages_long
+ _pacman_get_command
+
+ if compset -P1 '*/*'; then
+ packages=( $(_call_program packages $cmd[@] -Sql ${words[CURRENT]%/*}) )
+ typeset -U packages
+ _wanted repo_packages expl "repository/package" compadd ${(@)packages}
+ else
+ packages=( $(_call_program packages $cmd[@] -Sql) )
+ typeset -U packages
+ _wanted packages expl "packages" compadd - "${(@)packages}"
+
+ repositories=(${(o)${${${(M)${(f)"$(</etc/pacman.conf)"}:#\[*}/\[/}/\]/}:#options})
+ typeset -U repositories
+ _wanted repo_packages expl "repository/package" compadd -S "/" $repositories
+ fi
+}
+
+_pacstrap_none(){
+ _arguments -s : \
+ "$_pacstrap_args[@]" \
+ "$_longopts[@]" \
+}
+
+_genfstab_args=(
+ '-h[display help]'
+)
+_genfstab_args_nonh=(
+ '(--help -h)-p[Avoid printing pseudofs mounts]'
+ '(-U --help -h)-L[Use labels for source identifiers]'
+ '(-L --help -h)-U[Use UUIDs for source identifiers]'
+)
+
+_arch_chroot_args=( '-h[display help]' )
+
+_longopts=( '--help[display help]' )
+
+_pacstrap(){
+ if [[ -z ${(M)words:#--help} && -z ${(M)words:#-h} ]]; then
+ case $words[CURRENT] in
+ -c*|-d*|-i*)
+ _arguments -s "$_pacstrap_args_nonh[@]"
+ ;;
+ -*)
+ _arguments -s : \
+ "$_pacstrap_args[@]" \
+ "$_pacstrap_args_nonh[@]" \
+ "$_longopts[@]"
+ ;;
+ --*)
+ _arguments -s : \
+ "$_longopts[@]"
+ ;;
+ *)
+ _arguments -s : \
+ "$_pacstrap_args[@]" \
+ "$_pacstrap_args_nonh[@]" \
+ "$_longopts[@]" \
+ ":*:_path_files -/" \
+ ":*:_pacman_completions_all_packages"
+ ;;
+ esac
+ else
+ return 1
+ fi
+}
+
+_genfstab(){
+ if [[ -z ${(M)words:#--help} && -z ${(M)words:#-*h} ]]; then
+ case $words[CURRENT] in
+ -p*|-L*|-U*)
+ _arguments -s : \
+ "$_genfstab_args_nonh[@]"
+ ;;
+ -*)
+ _arguments -s : \
+ "$_genfstab_args[@]" \
+ "$_genfstab_args_nonh[@]" \
+ "$_longopts[@]"
+ ;;
+ --*)
+ _arguments -s : \
+ "$_longopts[@]"
+ ;;
+ *)
+ _arguments \
+ "$_genfstab_args[@]" \
+ "$_genfstab_args_nonh[@]" \
+ "$_longopts[@]" \
+ ":*:_path_files -/"
+ ;;
+ esac
+ else
+ return 1
+ fi
+}
+
+_arch_chroot(){
+ if [[ -z ${(M)words:#--help} && -z ${(M)words:#-*h} ]]; then
+ case $words[CURRENT] in
+ -*)
+ _arguments -s : \
+ "$_arch_chroot_args[@]" \
+ "$_longopts[@]" \
+ ;;
+ --*)
+ _arguments -s : \
+ "$_longopts[@]"
+ ;;
+ *)
+ _arguments \
+ ':*:_path_files -/'
+ ;;
+ esac
+ else
+ return 1
+ fi
+}
+
+_install_scripts(){
+ case "$service" in
+ pacstrap)
+ _pacstrap "$@"
+ ;;
+ genfstab)
+ _genfstab "$@";;
+ arch-chroot)
+ _arch_chroot "$@";;
+ *)
+ _message "Error";;
+ esac
+}
+
+_install_scripts "$@"