diff options
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | bin/all.do | 2 | ||||
-rw-r--r-- | bin/clean.do | 2 | ||||
-rw-r--r-- | bin/cpt-readlink.c | 47 | ||||
-rw-r--r-- | bin/cpt-stat.c | 41 | ||||
-rw-r--r-- | bin/test.do | 11 | ||||
-rw-r--r-- | clean.do | 2 | ||||
-rw-r--r-- | config.rc | 2 | ||||
-rwxr-xr-x | contrib/cpt-owns | 3 | ||||
-rw-r--r-- | default.do | 13 | ||||
-rw-r--r-- | man/cpt-contrib.1 | 10 | ||||
-rwxr-xr-x | src/cpt | 4 | ||||
-rwxr-xr-x | src/cpt-checksum | 3 | ||||
-rw-r--r-- | src/cpt-lib.in | 64 | ||||
-rwxr-xr-x | src/cpt-list | 12 |
16 files changed, 74 insertions, 156 deletions
@@ -1,9 +1,3 @@ -### Binaries/Objects ### -cpt-lib -cpt-stat -cpt-readlink -*.o - ### Emacs ### \#*\# *~ @@ -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 @@ -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 -- {} + @@ -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. @@ -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> @@ -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 |