aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--README8
-rw-r--r--bin/all.do2
-rw-r--r--bin/clean.do2
-rw-r--r--bin/cpt-readlink.c47
-rw-r--r--bin/cpt-stat.c41
-rw-r--r--bin/test.do11
-rw-r--r--clean.do2
-rw-r--r--config.rc2
-rwxr-xr-xcontrib/cpt-owns3
-rw-r--r--default.do13
-rw-r--r--man/cpt-contrib.110
-rwxr-xr-xsrc/cpt4
-rwxr-xr-xsrc/cpt-checksum3
-rw-r--r--src/cpt-lib.in64
-rwxr-xr-xsrc/cpt-list12
16 files changed, 74 insertions, 156 deletions
diff --git a/.gitignore b/.gitignore
index 45ab818..ea58743 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,3 @@
-### Binaries/Objects ###
-cpt-lib
-cpt-stat
-cpt-readlink
-*.o
-
### Emacs ###
\#*\#
*~
diff --git a/README b/README
index 6479e35..fb860fa 100644
--- a/README
+++ b/README
@@ -19,22 +19,20 @@ Dependencies
To build and use cpt, you need the following software.
-MAKE DEPENDS
-- C compiler
-- redo (the repository contains minimal/do)
-
RUNTIME DEPENDS
- rsync
- curl
- POSIX base utilities [coreutils, busybox, sbase, etc.]
- tar [GNU tar, busybox, toybox, libarchive, etc.]
+MAKE DEPENDS
+- redo (optional, the repository contains minimal/do)
+
Directory Structure
--------------------------------------------------------------------------------
/ -- README, LICENSE, CHANGELOG
- bin/ -- for C programs.
contrib/ -- for Shell scripts that wrap around cpt.
docs/ -- for documentation.
man/ -- for manual pages.
diff --git a/bin/all.do b/bin/all.do
deleted file mode 100644
index aceda74..0000000
--- a/bin/all.do
+++ /dev/null
@@ -1,2 +0,0 @@
-. ../config.rc
-redo-ifchange cpt-readlink cpt-stat
diff --git a/bin/clean.do b/bin/clean.do
deleted file mode 100644
index 6234248..0000000
--- a/bin/clean.do
+++ /dev/null
@@ -1,2 +0,0 @@
-. ../config.rc
-rm -f -- ./*.o cpt-readlink cpt-stat .dep.*
diff --git a/bin/cpt-readlink.c b/bin/cpt-readlink.c
deleted file mode 100644
index e7cfe50..0000000
--- a/bin/cpt-readlink.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* cpt-readlink --- a utility replacement for readlink
- * See LICENSE for copyright information.
- *
- * This is basically a 'readlink -f' command.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <string.h>
-#include <limits.h>
-
-#define DIR_MAX PATH_MAX - NAME_MAX - 1
-
-
-char *realpath(const char *path, char *resolved_path);
-
-int
-main(int argc, char *argv[])
-{
-
- char buf[PATH_MAX];
-
- /* We are going to use these if the file doesn't exist, but we can still
- * use directories above the file. We are using dname and bname so that
- * they don't clash with the functions with the same name.
- */
- char dname[DIR_MAX]; /* directory name */
- char bname[NAME_MAX]; /* base name */
- sprintf(bname, "%s", (basename(argv[1])));
-
- if (argc != 2 || strcmp(argv[1], "--help") == 0) {
- fprintf(stderr, "usage: %s [file]\n", argv[0]);
- return 1;
- }
-
- if (!realpath(argv[1], buf)) {
-
- if (!realpath(dirname(argv[1]), dname)) {
- perror(argv[0]);
- return 1;
- }
- sprintf(buf, "%s/%s", dname, bname);
- }
-
- printf("%s\n", buf);
- return 0;
-}
diff --git a/bin/cpt-stat.c b/bin/cpt-stat.c
deleted file mode 100644
index 584c2df..0000000
--- a/bin/cpt-stat.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* cpt-stat --- a utility for getting the user name of file owner
- * See LICENSE for copyright information
- *
- * The reason this simple tool exists is because 'stat' is not
- * portable and ls is not exactly stable enough for scripting.
- * This program is for outputting the owner name, and that's it.
- */
-
-#include <pwd.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-
-struct passwd *pw;
-struct stat sb;
-
-int
-main (int argc, char *argv[])
-{
- /* Exit if no or multiple arguments are given. */
- if (argc != 2 || strcmp(argv[1], "--help") == 0) {
- fprintf(stderr, "Usage: %s [pathname]\n", argv[0]);
- return 1;
- }
-
- /* Exit if file stat cannot be obtained. */
- if (lstat(argv[1], &sb) == -1) {
- perror(argv[0]);
- return 1;
- }
-
- /* Exit if name of the owner cannot be retrieved. */
- if (!getpwuid(sb.st_uid)) {
- return 1;
- }
-
- /* Print the user name of file owner. */
- pw = getpwuid(sb.st_uid);
- printf("%s\n", pw->pw_name);
- return 0;
-}
diff --git a/bin/test.do b/bin/test.do
deleted file mode 100644
index 4794751..0000000
--- a/bin/test.do
+++ /dev/null
@@ -1,11 +0,0 @@
-. ../config.rc
-redo all
-exec >&2
-
-./cpt-readlink .
-./cpt-readlink ..
-./cpt-readlink /bin
-./cpt-stat /bin
-./cpt-stat cpt-readlink.o
-
-PHONY
diff --git a/clean.do b/clean.do
index b30f907..57ab99f 100644
--- a/clean.do
+++ b/clean.do
@@ -1,5 +1,5 @@
. ./config.rc
-redo bin/clean src/clean
+redo src/clean
redo_clean
rm -f "cpt-$VERSION.tar.xz"
find docs -name '*.info' -exec rm -f -- {} +
diff --git a/config.rc b/config.rc
index 2f0733b..4b3876e 100644
--- a/config.rc
+++ b/config.rc
@@ -76,7 +76,7 @@ PHONY() {
getbin() {
# Function to get all executables
- find src contrib bin -name 'cpt-*' ! -name '*.in' ! -name '*.[coh]'
+ find src contrib -name 'cpt-*' ! -name '*.in'
}
diff --git a/contrib/cpt-owns b/contrib/cpt-owns
index 5f73674..9e3cccb 100755
--- a/contrib/cpt-owns
+++ b/contrib/cpt-owns
@@ -1,5 +1,6 @@
#!/bin/sh -e
# Check which package owns a file
+. cpt-lib
case "$1" in ''|--help|-h) printf '%s\n' "usage: ${0##*/} [file]" ; exit 0 ; esac
@@ -17,7 +18,7 @@ esac
# Strip 'CPT_ROOT' from the file path if passed and
# follow symlinks.
file="${1#$CPT_ROOT}"
-dirname=$(cpt-readlink "$CPT_ROOT/${file%/*}")
+dirname=$(_readlinkf "$CPT_ROOT/${file%/*}")
file="$dirname/${file##*/}"
# Check if the file exists and exit if it is not.
diff --git a/default.do b/default.do
index c16f5f8..cb45cd0 100644
--- a/default.do
+++ b/default.do
@@ -4,7 +4,7 @@
fn="${1%.*}"
case "$1" in
- all) redo-ifchange src/cpt-lib bin/all docs/all ;;
+ all) redo-ifchange src/cpt-lib docs/all ;;
dist)
redo clean
redo "cpt-$VERSION.tar.xz"
@@ -13,15 +13,6 @@ case "$1" in
redo-ifchange "$1.in"
sed "s|@VERSION@|$VERSION|g" < "$1.in" > "$3"
;;
- bin/cpt-readlink|bin/cpt-stat)
- redo-ifchange "$1.o"
- "$CC" -o "$3" $LDFLAGS "$1.o" $LIBS
- ;;
- *.o)
- [ -f "${1%.o}.c" ] || exit 99
- redo-ifchange "$fn.c"
- "$CC" -c -o "$3" $CFLAGS "$fn.c"
- ;;
"cpt-$VERSION.tar.xz")
redo docs/cpt.info
rm -rf -- "cpt-$VERSION"
@@ -38,7 +29,7 @@ case "$1" in
mv "$1" "$3"
;;
test)
- redo src/test bin/test
+ redo src/test
;;
src/clean)
rm -f src/cpt-lib
diff --git a/man/cpt-contrib.1 b/man/cpt-contrib.1
index 8a34364..ffc5e54 100644
--- a/man/cpt-contrib.1
+++ b/man/cpt-contrib.1
@@ -88,11 +88,6 @@ can be used to check if personal packages are outdated.
<file>
Checks which package has installed the given file.
-.SH CPT-READLINK
-.B cpt-readlink
-<file>
-
-A 'readlink -f' replacement to be used inside the package manager.
.SH CPT-REPODEPENDS
.B cpt-repodepends
<pkg>
@@ -112,11 +107,6 @@ Prints the packages that depend on the given package. (Reverse dependencies)
<pkg>
Prints the given package's size, and its individual files.
-.SH CPT-STAT
-.B cpt-stat
-<file>
-
-Outputs the owner name of a file/directory
.SH CPT-WHICH
.B cpt-which
<pkg>
diff --git a/src/cpt b/src/cpt
index ce4c70f..57e16b4 100755
--- a/src/cpt
+++ b/src/cpt
@@ -16,8 +16,8 @@ case "$arg" in
done
for path; do
- # These are the files to be ignored.
- contains "lib readlink stat" "$path" && continue
+ # Ignore the library.
+ [ lib = "$path" ] && continue
printf "%b->%b %-${max}s " "$colorb" "$colre" "${path#*/cpt-}"
sed -n 's/^# *//;2p' "$(command -v "cpt-$path")"
diff --git a/src/cpt-checksum b/src/cpt-checksum
index 0a83ae0..cd1fa4e 100755
--- a/src/cpt-checksum
+++ b/src/cpt-checksum
@@ -22,8 +22,7 @@ for pkg; do
tee "$repo_dir/checksums"
else
log "$pkg" "Need permissions to generate checksums"
-
- user=$(cpt-stat "$repo_dir") as_root tee "$repo_dir/checksums"
+ user=$(_stat "$repo_dir") as_root tee "$repo_dir/checksums"
fi
}
diff --git a/src/cpt-lib.in b/src/cpt-lib.in
index 3d2b2f4..34af54b 100644
--- a/src/cpt-lib.in
+++ b/src/cpt-lib.in
@@ -44,6 +44,48 @@ trap_set() {
esac
}
+_stat() (
+ _user=; eval set -- "$(ls -ld "$1")"
+ id -u "${_user:=$3}" >/dev/null 2>&1 || _user=root
+ printf '%s' "$_user"
+)
+
+_readlinkf() (
+ # Public domain POSIX sh readlink function by Koichi Nakashima
+ [ "${1:-}" ] || return 1
+ max_symlinks=40
+ CDPATH='' # to avoid changing to an unexpected directory
+
+ target=$1
+ [ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes
+ [ -d "${target:-/}" ] && target="$target/"
+
+ cd -P . 2>/dev/null || return 1
+ while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do
+ if [ ! "$target" = "${target%/*}" ]; then
+ case $target in
+ /*) cd -P "${target%/*}/" 2>/dev/null || break ;;
+ *) cd -P "./${target%/*}" 2>/dev/null || break ;;
+ esac
+ target=${target##*/}
+ fi
+
+ if [ ! -L "$target" ]; then
+ target="${PWD%/}${target:+/}${target}"
+ printf '%s\n' "${target:-/}"
+ return 0
+ fi
+
+ # `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n",
+ # <file mode>, <number of links>, <owner name>, <group name>,
+ # <size>, <date and time>, <pathname of link>, <contents of link>
+ # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
+ link=$(ls -dl -- "$target" 2>/dev/null) || break
+ target=${link#*" $target -> "}
+ done
+ return 1
+)
+
# This is the public domain getoptions shell library. It also forms a usage
# function.
# URL: https://github.com/ko1nksm/getoptions (v2.0.1)
@@ -1145,14 +1187,11 @@ pkg_conflicts() {
# Use $CPT_ROOT in filename so that we follow its symlinks.
file=$CPT_ROOT/${file#/}
- # We will only follow the symlinks of the directories, so we
- # reserve the directory name in this 'dirname' value. cpt-readlink
- # functions in a similar fashion to 'readlink -f', it makes sure
- # every component except for the first one to be available on
- # the directory structure. If we cannot find it in the system,
- # we don't need to make this much more complex by trying so
- # hard to find it. Simply use the original directory name.
- dirname="$(cpt-readlink "${file%/*}" 2>/dev/null)" ||
+ # We will only follow the symlinks of the directories, so we reserve the
+ # directory name in this 'dirname' value. If we cannot find it in the
+ # system, we don't need to make this much more complex by trying so hard
+ # to find it. Simply use the original directory name.
+ dirname="$(_readlinkf "${file%/*}" 2>/dev/null)" ||
dirname="${file%/*}"
@@ -1577,8 +1616,7 @@ pkg_fetch() {
# ownership of files and directories in the rare
# case that the repository is owned by a 3rd user.
(
- user=$(cpt-stat "$PWD") || user=root
- id -u "$user" >/dev/null 2>&1 || user=root
+ user=$(_stat "$PWD")
[ "$user" = root ] ||
log "Dropping permissions to $user for pull"
@@ -1614,8 +1652,7 @@ pkg_fetch() {
# We are going to do the same operation as above, to
# find the owner of the repository.
(
- user=$(cpt-stat "$PWD") || user=root
- id -u "$user" >/dev/null 2>&1 || user=root
+ user=$(_stat "$PWD")
[ "$user" = root ] ||
log "Dropping permissions to $user for pull"
@@ -1647,8 +1684,7 @@ pkg_fetch() {
# Similar to the git update, we find the owner of
# the repository and spawn rsync as that user.
(
- user=$(cpt-stat "$PWD") || user=root
- id -u "$user" >/dev/null 2>&1 || user=root
+ user=$(_stat "$PWD")
[ "$user" = root ] ||
log "Dropping permissions to $user for pull"
diff --git a/src/cpt-list b/src/cpt-list
index a161abf..363e22f 100755
--- a/src/cpt-list
+++ b/src/cpt-list
@@ -5,11 +5,23 @@ parser_definition() {
setup REST help:usage -- "usage: ${0##*/} [-c] [pkg...]"
msg -- '' 'Options:'
flag CURRENT -c --current -- "Use the current directory as a package"
+ param PKG --check label:" --check PKG TRUE FALSE" -- \
+ "Check if PKG exists and return the string of TRUE if"\
+ "it exists, and the string of FALSE if it doesn't." \
+ "Useful for optional packaging."
global_options
}
if [ -f ./cpt-lib ]; then . ./cpt-lib; else . cpt-lib; fi
+if [ "$PKG" ]; then
+ if pkg_list "$PKG" >/dev/null 2>&1; then
+ printf %s "$1"
+ else
+ printf %s "$2"
+ fi
+else
[ "$CURRENT" ] && set -- "${PWD##*/}"
pkg_list "$@"
+fi