From 440af4f3ebfecd68dabf8ce5524fd3f953e81c71 Mon Sep 17 00:00:00 2001 From: merakor Date: Mon, 21 Dec 2020 11:13:51 +0000 Subject: 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 --- .gitignore | 6 ----- README | 8 +++---- bin/all.do | 2 -- bin/clean.do | 2 -- bin/cpt-readlink.c | 47 --------------------------------------- bin/cpt-stat.c | 41 ---------------------------------- bin/test.do | 11 ---------- clean.do | 2 +- config.rc | 2 +- contrib/cpt-owns | 3 ++- default.do | 13 ++--------- man/cpt-contrib.1 | 10 --------- src/cpt | 4 ++-- src/cpt-checksum | 3 +-- src/cpt-lib.in | 64 ++++++++++++++++++++++++++++++++++++++++++------------ src/cpt-list | 12 ++++++++++ 16 files changed, 74 insertions(+), 156 deletions(-) delete mode 100644 bin/all.do delete mode 100644 bin/clean.do delete mode 100644 bin/cpt-readlink.c delete mode 100644 bin/cpt-stat.c delete mode 100644 bin/test.do 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 -#include -#include -#include -#include - -#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 -#include -#include -#include - -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. Checks which package has installed the given file. -.SH CPT-READLINK -.B cpt-readlink - - -A 'readlink -f' replacement to be used inside the package manager. .SH CPT-REPODEPENDS .B cpt-repodepends @@ -112,11 +107,6 @@ Prints the packages that depend on the given package. (Reverse dependencies) Prints the given package's size, and its individual files. -.SH CPT-STAT -.B cpt-stat - - -Outputs the owner name of a file/directory .SH CPT-WHICH .B cpt-which 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", + # , , , , + # , , , + # 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 -- cgit v1.2.3