aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormerakor <cem@ckyln.com>2020-12-21 11:13:51 +0000
committermerakor <cem@ckyln.com>2020-12-21 11:13:51 +0000
commit440af4f3ebfecd68dabf8ce5524fd3f953e81c71 (patch)
treed7ceaf1d040bad60822c87ad78ca30de76df1342
parent36308f68ddd95984c1909c5ca00a6ab70544d15b (diff)
downloadcpt-440af4f3ebfecd68dabf8ce5524fd3f953e81c71.tar.gz
cpt: remove cpt-stat and cpt-readlink, add _stat() and _readlinkf
cpt-readlink and cpt-stat were unnecessary additions for mundane tasks. Since they were binaries instead of scripts, they added an extra layer of complexity to the library. These functions are now included inside the package manager library with the names _readlinkf() and _stat(). FossilOrigin-Name: 7e15e2b57ddcb834c4286c8d1ac0a28031ae4f5d39f3c6a99f5b3aa0e9a83d43
-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