diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 000000000..5b198ca12 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,55 @@ +name: build + +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: setup-msys2 + uses: msys2/setup-msys2@v2 + with: + msystem: MSYS + update: true + install: >- + msys2-devel + base-devel + asciidoc + doxygen + git + meson + ninja + gettext-devel + heimdal-devel + libarchive-devel + libcurl-devel + libgpgme-devel + libsqlite-devel + libunistring-devel + + - name: Build + shell: msys2 {0} + run: | + meson _build \ + --auto-features=enabled \ + --default-library=static \ + -Dbuildstatic=true \ + -Ddoxygen=enabled \ + -Dfile-seccomp=disabled + + meson compile -C _build + + - name: Install + shell: msys2 {0} + run: | + DESTDIR="$(pwd)"/_dest meson install -C _build + + - name: Upload + uses: actions/upload-artifact@v2 + with: + name: install + path: _dest/ diff --git a/doc/meson.build b/doc/meson.build index e84eddc0d..7cad0f9b1 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -59,7 +59,7 @@ foreach page : manpages '-f', 'manpage', '--xsltproc-opts', '-param man.endnotes.list.enabled 0 -param man.endnotes.are.numbered 0', '-D', '@OUTDIR@', - '--asciidoc-opts', ' '.join(asciidoc_opts), + '--asciidoc-opts=' + ' '.join(asciidoc_opts), '@INPUT@', ], input : input, diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 6d245ba90..c21c884de 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -266,6 +266,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, "filesystem: %o package: %o\n", filename, lsbuf.st_mode & mask, entrymode & mask); } +#ifndef __MSYS__ #if 0 /* Disable this warning until our user management in packages has improved. @@ -283,6 +284,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, } #endif +#endif _alpm_log(handle, ALPM_LOG_DEBUG, "extract: skipping dir extraction of %s\n", filename); archive_read_data_skip(archive); @@ -655,7 +657,10 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg, int _alpm_upgrade_packages(alpm_handle_t *handle) { size_t pkg_count, pkg_current; - int skip_ldconfig = 0, ret = 0; +#ifndef __MSYS__ + int skip_ldconfig = 0; +#endif + int ret = 0; alpm_list_t *targ; alpm_trans_t *trans = handle->trans; @@ -678,18 +683,22 @@ int _alpm_upgrade_packages(alpm_handle_t *handle) /* something screwed up on the commit, abort the trans */ trans->state = STATE_INTERRUPTED; handle->pm_errno = ALPM_ERR_TRANS_ABORT; +#ifndef __MSYS__ /* running ldconfig at this point could possibly screw system */ skip_ldconfig = 1; +#endif ret = -1; } pkg_current++; } +#ifndef __MSYS__ if(!skip_ldconfig) { /* run ldconfig if it exists */ _alpm_ldconfig(handle); } +#endif return ret; } diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index e7fc7bbfc..ee7b97cff 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -2852,6 +2852,15 @@ int alpm_trans_release(alpm_handle_t *handle); * @return 0 on success, -1 on error (pm_errno is set accordingly) */ int alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade); +#ifdef __MSYS__ +int alpm_sync_sysupgrade_core(alpm_handle_t *handle, int enable_downgrade); + +/** Informs whether a package is a core package. + * @param pkg the package to check + * @return non-zero if this is a core package, zero otherwise + */ +int alpm_pkg_is_core_package(const alpm_pkg_t *pkg); +#endif /** Add a package to the transaction. * If the package was loaded by alpm_pkg_load(), it will be freed upon diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index 38d28c6c3..6b531fc49 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -518,6 +518,32 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, _alpm_log(handle, ALPM_LOG_DEBUG, "checking possible conflict: %s\n", path); +#ifdef __MSYS__ + /* In case a file "foo.exe" gets renamed to "foo" the msys2 .exe + * interpolation makes pacman think an untracker file is replaced. + * In case foo and foo.exe are the same file and foo.exe existed + * in the old package version we can be sure it's handled by the + * old package and ignore the conflict */ + if(dbpkg) { + char path_exe[PATH_MAX]; + struct stat lsbuf2; + + strncpy(path_exe, path, sizeof(path_exe) - 4); + strcat(path_exe, ".exe"); + if(llstat(path, &lsbuf) == 0 && llstat(path_exe, &lsbuf2) == 0) { + int old_contains_exe = (alpm_filelist_contains(alpm_pkg_get_files(dbpkg), path_exe + rootlen) != NULL); + int same_file = (lsbuf.st_dev == lsbuf2.st_dev && lsbuf.st_ino == lsbuf2.st_ino); + + if(same_file && old_contains_exe) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "MSYS2 special case: Found %s which is the same file and included in the old package\n", + path_exe); + continue; + } + } + } +#endif + pfile_isdir = path[pathlen - 1] == '/'; if(pfile_isdir) { if(S_ISDIR(lsbuf.st_mode)) { diff --git a/lib/libalpm/filelist.c b/lib/libalpm/filelist.c index 13990671d..3d34e84f6 100644 --- a/lib/libalpm/filelist.c +++ b/lib/libalpm/filelist.c @@ -25,6 +25,43 @@ #include "filelist.h" #include "util.h" +#ifdef __MSYS__ + +#define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c)) + +static int _cmppath(const char *s1, const char *s2) +{ + int c1, c2; + + while(*s1 && *s2) + { + c1 = TOLOWER(*s1); + c2 = TOLOWER(*s2); + if(c1 != c2) + return c1 - c2; + s1++; + s2++; + } + + return *s1 - *s2; +} + +static int _cmpchar(char c1, char c2) +{ + return TOLOWER(c1) - TOLOWER(c2); +} +#else +static int _cmppath(const char *s1, const char *s2) +{ + return strcmp(s1, s2); +} + +static int _cmpchar(char c1, char c2) +{ + return c1 - c2; +} +#endif + /* Returns the difference of the provided two lists of files. * Pre-condition: both lists are sorted! * When done, free the list but NOT the contained data. @@ -39,7 +76,7 @@ alpm_list_t *_alpm_filelist_difference(alpm_filelist_t *filesA, char *strA = filesA->files[ctrA].name; char *strB = filesB->files[ctrB].name; - int cmp = strcmp(strA, strB); + int cmp = _cmppath(strA, strB); if(cmp < 0) { /* item only in filesA, qualifies as a difference */ ret = alpm_list_add(ret, strA); @@ -63,7 +100,7 @@ alpm_list_t *_alpm_filelist_difference(alpm_filelist_t *filesA, static int _alpm_filelist_pathcmp(const char *p1, const char *p2) { - while(*p1 && *p1 == *p2) { + while(*p1 && _cmpchar(*p1, *p2) == 0) { p1++; p2++; } @@ -75,7 +112,7 @@ static int _alpm_filelist_pathcmp(const char *p1, const char *p2) p1++; } - return *p1 - *p2; + return _cmpchar(*p1, *p2); } /* Returns the intersection of the provided two lists of files. @@ -115,7 +152,7 @@ static int _alpm_files_cmp(const void *f1, const void *f2) { const alpm_file_t *file1 = f1; const alpm_file_t *file2 = f2; - return strcmp(file1->name, file2->name); + return _cmppath(file1->name, file2->name); } alpm_file_t SYMEXPORT *alpm_filelist_contains(const alpm_filelist_t *filelist, @@ -137,7 +174,7 @@ void _alpm_filelist_sort(alpm_filelist_t *filelist) { size_t i; for(i = 1; i < filelist->count; i++) { - if(strcmp(filelist->files[i - 1].name, filelist->files[i].name) > 0) { + if(_cmppath(filelist->files[i - 1].name, filelist->files[i].name) > 0) { /* filelist is not pre-sorted */ qsort(filelist->files, filelist->count, sizeof(alpm_file_t), _alpm_files_cmp); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a294d6369..eda22b191 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -900,3 +900,21 @@ int _alpm_pkg_check_meta(alpm_pkg_t *pkg) return error_found; } + +#ifdef __MSYS__ +int SYMEXPORT alpm_pkg_is_core_package(const alpm_pkg_t *pkg) +{ + if (pkg == NULL) + return 0; + return + strcmp(pkg->name, "bash") == 0 || + strcmp(pkg->name, "filesystem") == 0 || + strcmp(pkg->name, "mintty") == 0 || + strcmp(pkg->name, "msys2-runtime") == 0 || + strcmp(pkg->name, "msys2-runtime-devel") == 0 || + strncmp(pkg->name, "msys2-runtime-", + strlen("msys2-runtime-")) == 0 || + strcmp(pkg->name, "pacman") == 0 || + strcmp(pkg->name, "pacman-mirrors") == 0; +} +#endif diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index f44eac7f1..48c6def91 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -767,18 +767,22 @@ int _alpm_remove_packages(alpm_handle_t *handle, int run_ldconfig) if(_alpm_remove_single_package(handle, pkg, NULL, targ_count, pkg_count) == -1) { handle->pm_errno = ALPM_ERR_TRANS_ABORT; +#ifndef __MSYS__ /* running ldconfig at this point could possibly screw system */ run_ldconfig = 0; +#endif ret = -1; } targ_count++; } +#ifndef __MSYS__ if(run_ldconfig) { /* run ldconfig if it exists */ _alpm_ldconfig(handle); } +#endif return ret; } diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 1653b4b29..294a4b93c 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -197,7 +197,13 @@ static alpm_list_t *check_replacers(alpm_handle_t *handle, alpm_pkg_t *lpkg, return replacers; } +/** Search for packages to upgrade and add them to the transaction. */ +#ifdef __MSYS__ +static +int SYMEXPORT do_alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade, int core_update) +#else int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) +#endif { alpm_list_t *i, *j; alpm_trans_t *trans; @@ -211,6 +217,13 @@ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) for(i = _alpm_db_get_pkgcache(handle->db_local); i; i = i->next) { alpm_pkg_t *lpkg = i->data; +#ifdef __MSYS__ + /* Skip regular packages in core update, and core packages in regular update */ + if(core_update != alpm_pkg_is_core_package(lpkg)) { + continue; + } +#endif + if(alpm_pkg_find(trans->remove, lpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is marked for removal -- skipping\n", lpkg->name); continue; @@ -252,6 +265,18 @@ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) return 0; } +#ifdef __MSYS__ +int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) +{ + return do_alpm_sync_sysupgrade(handle, enable_downgrade, 0); +} + +int SYMEXPORT alpm_sync_sysupgrade_core(alpm_handle_t *handle, int enable_downgrade) +{ + return do_alpm_sync_sysupgrade(handle, enable_downgrade, 1); +} +#endif + alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs, const char *name) { diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 83160f005..f09077cee 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -30,7 +30,9 @@ #include #include #include +#ifndef __MSYS__ #include +#endif #include #include #include @@ -471,6 +473,9 @@ static int _alpm_chroot_write_to_child(alpm_handle_t *handle, int fd, _alpm_cb_io out_cb, void *cb_ctx) { ssize_t nwrite; +#ifdef __MSYS__ + struct sigaction newaction, oldaction; +#endif if(*buf_size == 0) { /* empty buffer, ask the callback for more */ @@ -480,7 +485,20 @@ static int _alpm_chroot_write_to_child(alpm_handle_t *handle, int fd, } } +#ifdef __MSYS__ + /* ignore SIGPIPE in case the pipe has been closed */ + newaction.sa_handler = SIG_IGN; + sigemptyset(&newaction.sa_mask); + newaction.sa_flags = 0; + sigaction(SIGPIPE, &newaction, &oldaction); + + nwrite = write(fd, buf, *buf_size); + + /* restore previous SIGPIPE handler */ + sigaction(SIGPIPE, &oldaction, NULL); +#else nwrite = send(fd, buf, *buf_size, MSG_NOSIGNAL); +#endif if(nwrite != -1) { /* write was successful, remove the written data from the buffer */ @@ -618,13 +636,21 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], /* Flush open fds before fork() to avoid cloning buffers */ fflush(NULL); +#ifdef __MSYS__ + if(pipe(child2parent_pipefd) == -1) { +#else if(socketpair(AF_UNIX, SOCK_STREAM, 0, child2parent_pipefd) == -1) { +#endif _alpm_log(handle, ALPM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); retval = 1; goto cleanup; } +#ifdef __MSYS__ + if(pipe(parent2child_pipefd) == -1) { +#else if(socketpair(AF_UNIX, SOCK_STREAM, 0, parent2child_pipefd) == -1) { +#endif _alpm_log(handle, ALPM_LOG_ERROR, _("could not create pipe (%s)\n"), strerror(errno)); retval = 1; goto cleanup; @@ -794,6 +820,7 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[], return retval; } +#ifndef __MSYS__ /** Run ldconfig in a chroot. * @param handle the context handle * @return 0 on success, 1 on error @@ -817,6 +844,7 @@ int _alpm_ldconfig(alpm_handle_t *handle) return 0; } +#endif /** Helper function for comparing strings using the alpm "compare func" * signature. diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c index 3f0de8d58..a58d9de48 100644 --- a/lib/libalpm/version.c +++ b/lib/libalpm/version.c @@ -50,7 +50,11 @@ static void parseEVR(char *evr, const char **ep, const char **vp, /* se points to version terminator */ se = strrchr(s, '-'); +#ifdef __MSYS__ + if(*s == '~') { +#else if(*s == ':') { +#endif epoch = evr; *s++ = '\0'; version = s; @@ -236,7 +240,7 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) return 0; } - /* Parse both versions into [epoch:]version[-release] triplets. We probably + /* Parse both versions into [epoch:|~]version[-release] triplets. We probably * don't need epoch and release to support all the same magic, but it is * easier to just run it all through the same code. */ full1 = strdup(a); diff --git a/scripts/libmakepkg/autodep/library_depends.sh.in b/scripts/libmakepkg/autodep/library_depends.sh.in index c088baff8..cb871bb07 100644 --- a/scripts/libmakepkg/autodep/library_depends.sh.in +++ b/scripts/libmakepkg/autodep/library_depends.sh.in @@ -23,7 +23,7 @@ LIBMAKEPKG_AUTODEP_LIBRARY_DEPENDS_SH=1 MAKEPKG_LIBRARY=${MAKEPKG_LIBRARY:-'@libmakepkgdir@'} -autodep_functions+=('library_depends') +# autodep_functions+=('library_depends') library_depends() { if check_option "autodeps" "y"; then diff --git a/scripts/libmakepkg/autodep/library_provides.sh.in b/scripts/libmakepkg/autodep/library_provides.sh.in index 374cc841a..ddacf4338 100644 --- a/scripts/libmakepkg/autodep/library_provides.sh.in +++ b/scripts/libmakepkg/autodep/library_provides.sh.in @@ -23,7 +23,7 @@ LIBMAKEPKG_AUTODEP_LIBRARY_PROVIDES_SH=1 MAKEPKG_LIBRARY=${MAKEPKG_LIBRARY:-'@libmakepkgdir@'} -autodep_functions+=('library_provides') +# autodep_functions+=('library_provides') library_provides() { if check_option "autodeps" "y"; then diff --git a/scripts/libmakepkg/buildenv.sh.in b/scripts/libmakepkg/buildenv.sh.in index 741080028..031ce4986 100644 --- a/scripts/libmakepkg/buildenv.sh.in +++ b/scripts/libmakepkg/buildenv.sh.in @@ -42,5 +42,5 @@ prepare_buildenv() { done # ensure all necessary build variables are exported - export ${buildenv_vars[@]} + export ${buildenv_vars[@]} CC CXX } diff --git a/scripts/libmakepkg/buildenv/lto.sh.in b/scripts/libmakepkg/buildenv/lto.sh.in index 7fc12a51e..fd3bb657a 100644 --- a/scripts/libmakepkg/buildenv/lto.sh.in +++ b/scripts/libmakepkg/buildenv/lto.sh.in @@ -35,5 +35,9 @@ buildenv_lto() { append_once CFLAGS "${LTOFLAGS:--flto}" append_once CXXFLAGS "${LTOFLAGS:--flto}" append_once LDFLAGS "${LTOFLAGS:--flto}" + if check_option "staticlibs" "y"; then + append_once CFLAGS "-ffat-lto-objects" + append_once CXXFLAGS "-ffat-lto-objects" + fi fi } diff --git a/scripts/libmakepkg/executable/meson.build b/scripts/libmakepkg/executable/meson.build index 5be72276c..535da5782 100644 --- a/scripts/libmakepkg/executable/meson.build +++ b/scripts/libmakepkg/executable/meson.build @@ -4,13 +4,10 @@ sources = [ 'ccache.sh.in', 'checksum.sh.in', 'distcc.sh.in', - 'fakeroot.sh.in', - 'debugedit.sh.in', 'gpg.sh.in', 'gzip.sh.in', 'pacman.sh.in', 'strip.sh.in', - 'sudo.sh.in', 'vcs.sh.in', ] diff --git a/scripts/libmakepkg/lint_package/build_references.sh.in b/scripts/libmakepkg/lint_package/build_references.sh.in index 5aea78ff1..a941e2f89 100644 --- a/scripts/libmakepkg/lint_package/build_references.sh.in +++ b/scripts/libmakepkg/lint_package/build_references.sh.in @@ -37,5 +37,13 @@ warn_build_references() { printf '%s\n' "${refs[@]#"$pkgdir/"}" >&2 fi done + + # Check for Windows-style MSYS2 root path + if find "${pkgdir}" -type f -print0 | xargs -0 grep -iFqI "$(cygpath -m /)" ; then + warning "$(gettext "Package contains reference to %s")" "\$(cygpath -m /)" + fi + if find "${pkgdir}" -type f -print0 | xargs -0 grep -iFqI "$(cygpath -w /)" ; then + warning "$(gettext "Package contains reference to %s")" "\$(cygpath -w /)" + fi return 0 } diff --git a/scripts/libmakepkg/meson.build b/scripts/libmakepkg/meson.build index 6e83a4a85..e6b945dff 100644 --- a/scripts/libmakepkg/meson.build +++ b/scripts/libmakepkg/meson.build @@ -9,6 +9,7 @@ libmakepkg_modules = [ { 'name' : 'reproducible', 'has_subdir' : true }, { 'name' : 'source', 'has_subdir' : true }, { 'name' : 'srcinfo', }, + { 'name' : 'utils_fixed_path', }, { 'name' : 'tidy', 'has_subdir' : true }, { 'name' : 'util', 'has_subdir' : true }, ] diff --git a/scripts/libmakepkg/tidy/staticlibs.sh.in b/scripts/libmakepkg/tidy/staticlibs.sh.in index 0315f7f6a..9d3338492 100644 --- a/scripts/libmakepkg/tidy/staticlibs.sh.in +++ b/scripts/libmakepkg/tidy/staticlibs.sh.in @@ -35,9 +35,9 @@ tidy_staticlibs() { msg2 "$(gettext "Removing static library files...")" local l while IFS= read -rd '' l; do - if [[ -f "${l%.a}.so" || -h "${l%.a}.so" ]]; then + if [[ -f "${l%.a}.dll.a" || -h "${l%.a}.dll.a" ]]; then rm "$l" fi - done < <(find . ! -type d -name "*.a" -print0) + done < <(find . ! -type d \( -name "*.a" ! -name "*.dll.a" \) -print0) fi } diff --git a/scripts/libmakepkg/tidy/strip.sh.in b/scripts/libmakepkg/tidy/strip.sh.in index db3591676..8918a0cb9 100644 --- a/scripts/libmakepkg/tidy/strip.sh.in +++ b/scripts/libmakepkg/tidy/strip.sh.in @@ -31,93 +31,55 @@ packaging_options+=('strip' 'debug') tidy_modify+=('tidy_strip') -build_id() { - LANG=C readelf -n "$1" | sed -n '/Build ID/ { s/.*: //p; q; }' -} - -source_files() { - # This function does two things: - # - # 1) rewrites source file locations for packages not respecting prefix- - # map switches. This ensures all source file references in debug - # info point to $dbgsrcdir. - # - # 2) outputs a list of files from the package source files to stdout - # while stripping the $dbgsrcdir prefix - - LANG=C debugedit --no-recompute-build-id \ - --base-dir "${srcdir}" \ - --dest-dir "${dbgsrcdir}" \ - --list-file /dev/stdout "$1" \ - | sort -zu | tr '\0' '\n' -} - -package_source_files() { - local binary=$1 - - local file dest t - while IFS= read -r t; do - file="${srcdir}/${t}" - dest="${dbgsrc}/${t}" - mkdir -p "${dest%/*}" - if [[ -f "$file" ]]; then - cp -- "$file" "$dest" - fi - done < <(source_files "$binary") -} - collect_debug_symbols() { local binary=$1; shift - if check_option "debug" "y"; then - local bid=$(build_id "$binary") - - # has this file already been stripped - if [[ -n "$bid" ]]; then - if [[ -f "$dbgdir/.build-id/${bid:0:2}/${bid:2}.debug" ]]; then + case "$(file -bi "$binary")" in + *application/x-dosexec* | *application/vnd.microsoft.portable-executable*) + if check_option "debug" "y"; then + if [[ -f "$dbgdir/$binary.debug" ]]; then return fi - elif [[ -f "$dbgdir/$binary.debug" ]]; then - return - fi - - # copy source files to debug directory - package_source_files "$binary" - # copy debug symbols to debug directory - mkdir -p "$dbgdir/${binary%/*}" + # copy debug symbols to debug directory + mkdir -p "$dbgdir/${binary%/*}" + msg2 "Separating debug info from $binary into $dbgdir/$binary.debug" + # create a dbg file with proper debug info: + objcopy --only-keep-debug "$binary" "$dbgdir/$binary.debug" + + msg2 "Creating a debuginfo link to $dbgdir/$binary.debug in $binary" + local tempfile=$(mktemp "$binary.XXXXXX") + objcopy --add-gnu-debuglink="$dbgdir/${binary#/}.debug" "$binary" "$tempfile" + cat "$tempfile" > "$binary" + rm "$tempfile" + + msg2 "Separating (again) debug info from $binary into $dbgdir/$binary.debug" + objcopy --only-keep-debug "$binary" "$dbgdir/$binary.debug" + + msg2 "Removing old .gnu_debuglink section from $binary" + objcopy --remove-section=.gnu_debuglink "$binary" + + # strip debug-info from the original file + objcopy --strip-debug "$binary" + msg2 "Creating (again) a debuginfo link to $dbgdir/$binary.debug in $binary" + tempfile=$(mktemp "$binary.XXXXXX") + objcopy --add-gnu-debuglink="$dbgdir/${binary#/}.debug" "$binary" "$tempfile" + cat "$tempfile" > "$binary" + rm "$tempfile" + # This way dbg file gets a .gnu_debuglink section (doesn't matter where + # it's pointing), and its contents pass the CRC32 check + + # create any needed hardlinks + while IFS= read -rd '' file ; do + if [[ "${binary}" -ef "${file}" && ! -f "$dbgdir/${file}.debug" ]]; then + mkdir -p "$dbgdir/${file%/*}" + ln "$dbgdir/${binary}.debug" "$dbgdir/${file}.debug" + fi + done < <(find . -type f -perm -u+w -print0 2>/dev/null) - # abandon processing files that are not a recognised format - if ! objcopy --only-keep-debug "$binary" "$dbgdir/$binary.debug" 2>/dev/null; then - return fi - - local tempfile=$(mktemp "$binary.XXXXXX") - objcopy --add-gnu-debuglink="$dbgdir/${binary#/}.debug" "$binary" "$tempfile" - cat "$tempfile" > "$binary" - rm "$tempfile" - - # create any needed hardlinks - while IFS= read -rd '' file ; do - if [[ "${binary}" -ef "${file}" && ! -f "$dbgdir/${file}.debug" ]]; then - mkdir -p "$dbgdir/${file%/*}" - ln "$dbgdir/${binary}.debug" "$dbgdir/${file}.debug" - fi - done < <(find . -type f -perm -u+w -print0 2>/dev/null) - - if [[ -n "$bid" ]]; then - local target - mkdir -p "$dbgdir/.build-id/${bid:0:2}" - - target="../../../../../${binary#./}" - target="${target/..\/..\/usr\/lib\/}" - target="${target/..\/usr\/}" - ln -s "$target" "$dbgdir/.build-id/${bid:0:2}/${bid:2}" - - target="../../${binary#./}.debug" - ln -s "$target" "$dbgdir/.build-id/${bid:0:2}/${bid:2}.debug" - fi - fi + ;; + esac } strip_file(){ @@ -148,21 +110,91 @@ tidy_strip() { [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S" if check_option "debug" "y"; then - dbgdir="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@/usr/lib/debug" + dbgdir="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@" dbgsrcdir="${DBGSRCDIR:-/usr/src/debug}/${pkgbase}" dbgsrc="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@$dbgsrcdir" mkdir -p "$dbgdir" "$dbgsrc" fi local binary strip_flags - find . -type f -perm -u+w -print0 2>/dev/null | LC_ALL=C sort -z | while IFS= read -rd '' binary ; do - # skip filepaths that cause stripping issues - ideally these should be temporary - # guile-2.2 - [[ "$binary" =~ .*/guile/.*\.go$ ]] && continue - - local STATICLIB=0 - case "$(LC_ALL=C readelf -h "$binary" 2>/dev/null)" in - *Type:*'DYN (Shared object file)'*) # Libraries (.so) or Relocatable binaries + # *.so: Apache2 modules, OCaml stublibs, Ruby modules + # *.oct: Octave modules + # *.cmxs: OCaml natdynlink modules: http://gallium.inria.fr/~frisch/ndl.txt + find * -type f ! -name '*.dll.a' ! -name '*.lib' \ + -a \( -name '*.a' -o -name '*.dll' -o -name '*.exe' -o -name '*.so' -o -name '*.so.*' -o -name '*.oct' -o -name '*.cmxs' \) -print0 \ + -o -type f -executable ! -name '*.dll' ! -name '*.exe' ! -name '*.so' ! -name '*.so.[0-9]*' ! -name '*.oct' ! -name '*.cmxs' ! -name '*.a' ! -name '*.la' ! -name '*.lib' ! -name '*.exe.manifest' ! -name '*.exe.config' ! -name '*.dll.config' ! -name '*.mdb' ! -name '*-config' ! -name '*.csh' ! -name '*.sh' ! -name '*.pl' ! -name '*.pm' ! -name '*.py' ! -name '*.rb' ! -name '*.tcl' -print0 | \ + while IFS= read -d $'\0' binary + do + local STRIPLTO=0 + # Skip thin archives from stripping + case "${binary##*/}" in + *.a) + if [ "$(head -c 7 "${binary}")" = '!' ] + then + continue + fi + ;; + esac + + # assure this is actually a binary object + if [ "$(head -c 2 "${binary}")" = '#!' ] + then + # sometimes .exe will be appended where it does not belong + case "${exe}" in + usr/lib/hevea/*.exe) ;; + *.exe) mv "${binary}" "${binary%.exe}" ;; + esac + continue + fi + + # OCaml bytecode must not be stripped + # Magic number is at end of file: + # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=256900#74 + # http://cygwin.com/ml/cygwin-apps/2010-10/msg00057.html + # + # Perl Archive (PAR) binaries must not be stripped + # https://rt.cpan.org/Public/Bug/Display.html?id=18536 + # http://cygwin.com/ml/cygwin-apps/2012-07/msg00088.html + case $(tail -c 12 "${binary}" | tr '\012\0' '%') in + %PAR\.pm%) continue ;; + Caml1999X0[0-9][0-9]) continue ;; + esac + + # Mono assemblies must not be stripped, but remove .mdb debug symbols, + # and make them non-executable so they're not launched by MS .NET + if LC_ALL=C file -b "${binary}" 2>&1 | grep -q "Mono/\.Net assembly" + then + chmod 0644 "${binary}" + rm -f "${binary}.mdb" + continue + fi + + # check for .exe from non-automake Makefile which install(1) didn't fix + # strip(1) used to take care of this, but not anymore + case ${CHOST} in + *-*-cygwin*|*-*-mingw*|*-*-msys*) + case "${binary##*/}" in + *.dll|*.exe|*.sfx|*.so|*.so.[0-9]*|*.oct|*.cmxs) ;; + # make sure this isn't some oddly named DLL + *) if LANG=en_US.UTF-8 LC_ALL=C objdump -f "${binary}" | grep -Eq '^start address 0x(0000000[01])?00401[0-9a-e][0-9a-e]0' + then + mv "${binary}" "${binary}.exe" + binary+=.exe + fi ;; + esac + ;; + esac + chmod 0755 "${binary}"; + + case "$(@FILECMD@ -bi "$binary")" in + *application/x-dosexec*) # Windows executables and dlls (file <=5.43) + strip_flags="$STRIP_SHARED";; + *application/vnd.microsoft.portable-executable*) # Windows executables and dlls (file >=5.44) + strip_flags="$STRIP_SHARED";; + *application/x-archive*) # Static and Import Libraries (*.a and *.dll.a) + strip_flags="$STRIP_STATIC" + STRIPLTO=1;; + *application/x-sharedlib*) # Libraries (.so) strip_flags="$STRIP_SHARED";; *Type:*'DYN (Position-Independent Executable file)'*) # Relocatable binaries strip_flags="$STRIP_SHARED";; diff --git a/scripts/libmakepkg/util/pkgbuild.sh.in b/scripts/libmakepkg/util/pkgbuild.sh.in index 9d9e59b6e..1fd903b2c 100644 --- a/scripts/libmakepkg/util/pkgbuild.sh.in +++ b/scripts/libmakepkg/util/pkgbuild.sh.in @@ -166,7 +166,11 @@ get_pkgbuild_all_split_attributes() { ## get_full_version() { if (( epoch > 0 )); then - printf "%s\n" "$epoch:$pkgver-$pkgrel" + if [[ -n $MSYSTEM ]]; then + printf "%s\n" "${epoch}~${pkgver}-${pkgrel}" + else + printf "%s\n" "$epoch:$pkgver-$pkgrel" + fi else printf "%s\n" "$pkgver-$pkgrel" fi diff --git a/scripts/libmakepkg/utils_fixed_path.sh.in b/scripts/libmakepkg/utils_fixed_path.sh.in new file mode 100644 index 000000000..e3a06bc10 --- /dev/null +++ b/scripts/libmakepkg/utils_fixed_path.sh.in @@ -0,0 +1,34 @@ +if [[ -n "$MSYSTEM" ]]; then + readonly -a UTILS_NAME=('bsdtar' + 'bzip2' + 'bzr' + 'cat' + 'ccache' + 'distcc' + 'git' + 'gpg' + 'gzip' + 'hg' + 'lzip' + 'lzop' + 'openssl' + 'svn' + 'tput' + 'uncompress' + 'xargs' + 'xz' + 'zstd' + ) + + for wrapper in ${UTILS_NAME[@]}; do + eval " + ${wrapper}"'() { + local UTILS_PATH="/usr/bin/" + if ! type -p ${UTILS_PATH}${FUNCNAME[0]} >/dev/null; then + error "$(gettext "Cannot find the %s binary required for makepkg.")" "${UTILS_PATH}${FUNCNAME[0]}" + exit 1 + fi + ${UTILS_PATH}${FUNCNAME[0]} "$@" + }' + done +fi diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 2c36681db..2e2c3b6c7 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # makepkg - make packages compatible for use with pacman # @@ -26,7 +26,7 @@ # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: -# awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils), +# awk, bsdtar (libarchive), bzip2, coreutils, file, find (findutils), # gettext, gpg, grep, gzip, sed, tput (ncurses), xz # gettext initialization @@ -59,7 +59,6 @@ FORCE=0 GENINTEG=0 HOLDVER=0 IGNOREARCH=0 -INFAKEROOT=0 INSTALL=0 LOGGING=0 NEEDED=0 @@ -105,10 +104,9 @@ done trap_exit() { local signal=$1; shift - if (( ! INFAKEROOT )); then - echo - error "$@" - fi + echo + error "$@" + [[ -n $srclinks ]] && rm -rf "$srclinks" # unset the trap for this signal, and then call the default handler @@ -123,11 +121,6 @@ trap_exit() { clean_up() { local EXIT_CODE=$? - if (( INFAKEROOT )); then - # Don't clean up when leaving fakeroot, we're not done yet. - return 0 - fi - if [[ -p $logpipe ]]; then rm "$logpipe" fi @@ -137,7 +130,7 @@ clean_up() { # If it's a clean exit and -c/--clean has been passed... msg "$(gettext "Cleaning up...")" - rm -rf "$pkgdirbase" "$srcdir" + rm -rf "$pkgdirbase" "$srcdir" "$destdir" if [[ -n $pkgbase ]]; then local fullver=$(get_full_version) # Can't do this unless the BUILDSCRIPT has been sourced. @@ -182,11 +175,6 @@ clean_up() { fi } -enter_fakeroot() { - msg "$(gettext "Entering %s environment...")" "fakeroot" - fakeroot -- bash -$- "${BASH_SOURCE[0]}" -F "${ARGLIST[@]}" || exit $? -} - # Automatically update pkgver variable if a pkgver() function is provided # Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver update_pkgver() { @@ -240,10 +228,6 @@ run_pacman() { else cmd=("${PACMAN_AUTH[@]}" "${cmd[@]}") fi - elif type -p sudo >/dev/null; then - cmd=(sudo "${cmd[@]}") - else - cmd=(su root -c "$cmdescape") fi local lockfile="$(pacman-conf DBPath)/db.lck" while [[ -f $lockfile ]]; do @@ -491,7 +475,6 @@ write_pkginfo() { generate_autodeps printf "# Generated by makepkg %s\n" "$makepkg_version" - printf "# using %s\n" "$(fakeroot -v)" write_kv_pair "pkgname" "$pkgname" write_kv_pair "pkgbase" "$pkgbase" @@ -624,7 +607,7 @@ create_package() { msg2 "$(gettext "Compressing package...")" # TODO: Maybe this can be set globally for robustness shopt -s -o pipefail - list_package_files | LANG=C bsdtar --no-fflags @BSDTAR_NO_READ_SPARSE@ -cnf - --null --files-from - | + list_package_files | LANG=C bsdtar --no-fflags @BSDTAR_NO_READ_SPARSE@ --no-xattrs --uid 1 --uname root --gid 1 --gname root -cnf - --null --files-from - | compress_as "$PKGEXT" > "${pkg_file}" || ret=$? shopt -u -o pipefail @@ -644,7 +627,7 @@ create_debug_package() { local pkgdir="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@" # check if we have any debug symbols to package - if dir_is_empty "$pkgdir/usr/lib/debug"; then + if dir_is_empty "$pkgdir"; then return 0 fi @@ -732,7 +715,7 @@ create_srcpackage() { # TODO: Maybe this can be set globally for robustness shopt -s -o pipefail - LANG=C bsdtar --no-fflags @BSDTAR_NO_READ_SPARSE@ -cLf - ${pkgbase} | compress_as "$SRCEXT" > "${pkg_file}" || ret=$? + LANG=C bsdtar --no-fflags @BSDTAR_NO_READ_SPARSE@ --uid 1 --uname root --gid 1 --gname root -cLf - ${pkgbase} | compress_as "$SRCEXT" > "${pkg_file}" || ret=$? shopt -u -o pipefail @@ -846,6 +829,11 @@ restore_package_variables() { run_single_packaging() { local pkgdir="$pkgdirbase/$pkgname" + # clean existing pkg directory + if [[ -d "$pkgdir" ]]; then + msg "$(gettext "Removing existing %s directory...")" "\$pkgdir/" + rm -rf "$pkgdir" + fi mkdir "$pkgdir" if [[ -n $1 ]] || (( PKGFUNC )); then run_package $1 @@ -942,12 +930,16 @@ if ! type -p gettext >/dev/null; then gettext() { printf "%s\n" "$@" } +else + gettext() { + /usr/bin/gettext "$@" + } fi ARGLIST=("$@") # Parse Command Line Options. -OPT_SHORT="AcCdD:efFghiLmop:rRsSV" +OPT_SHORT="AcCdD:efghiLmop:rRsSV" OPT_LONG=('allsource' 'check' 'clean' 'cleanbuild' 'config:' 'dir:' 'force' 'geninteg' 'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'noarchive' 'nobuild' 'nocolor' 'nocheck' 'nodeps' 'noextract' 'noprepare' 'nosign' 'packagelist' @@ -982,7 +974,6 @@ while true; do -D|--dir) shift; CHDIR=$1 ;; -e|--noextract) NOEXTRACT=1 ;; -f|--force) FORCE=1 ;; - -F) INFAKEROOT=1 ;; # generating integrity checks does not depend on architecture -g|--geninteg) BUILDPKG=0 GENINTEG=1 IGNOREARCH=1;; --holdver) HOLDVER=1 ;; @@ -1027,7 +1018,7 @@ while [[ $1 ]]; do shift done -if (( ! INFAKEROOT )) && [[ -n $CHDIR ]]; then +if [[ -n $CHDIR ]]; then cd_safe "$CHDIR" fi @@ -1104,19 +1095,6 @@ if (( LOGGING )) && ! ensure_writable_dir "LOGDEST" "$LOGDEST"; then exit $E_FS_PERMISSIONS fi -if (( ! INFAKEROOT )); then - if (( EUID == 0 )); then - error "$(gettext "Running %s as root is not allowed as it can cause permanent,\n\ -catastrophic damage to your system.")" "makepkg" - exit $E_ROOT - fi -else - if [[ -z $FAKEROOTKEY ]]; then - error "$(gettext "Do not use the %s option. This option is only for internal use by %s.")" "'-F'" "makepkg" - exit $E_INVALID_OPTION - fi -fi - unset pkgname "${pkgbuild_schema_strings[@]}" "${pkgbuild_schema_arrays[@]}" unset "${known_hash_algos[@]/%/sums}" unset -f pkgver verify prepare build check package "${!package_@}" @@ -1149,8 +1127,11 @@ fi pkgbase=${pkgbase:-${pkgname[0]}} -# check the PKGBUILD for some basic requirements -lint_pkgbuild || exit $E_PKGBUILD_ERROR +# MSYS2: lint_pkgbuild is very slow with cygwin bash, so make it opt-in +if (( MAKEPKG_LINT_PKGBUILD )); then + # check the PKGBUILD for some basic requirements + lint_pkgbuild || exit $E_PKGBUILD_ERROR +fi if (( !SOURCEONLY && !PRINTSRCINFO )); then merge_arch_attrs @@ -1227,29 +1208,6 @@ if (( ! PKGVERFUNC )); then check_build_status fi -# Run the bare minimum in fakeroot -if (( INFAKEROOT )); then - if (( SOURCEONLY )); then - create_srcpackage - msg "$(gettext "Leaving %s environment.")" "fakeroot" - exit $E_OK - fi - - prepare_buildenv - - chmod 755 "$pkgdirbase" - if (( ! SPLITPKG )); then - run_single_packaging - else - run_split_packaging - fi - - create_debug_package - - msg "$(gettext "Leaving %s environment.")" "fakeroot" - exit $E_OK -fi - # check we have the software required to process the PKGBUILD check_software || exit $E_MISSING_MAKEPKG_DEPS @@ -1289,7 +1247,7 @@ if (( SOURCEONLY )); then check_source_integrity all cd_safe "$startdir" - enter_fakeroot + create_srcpackage if [[ $SIGNPKG = 'y' ]]; then msg "$(gettext "Signing package...")" @@ -1338,6 +1296,9 @@ fi mkdir -p "$srcdir" chmod a-s "$srcdir" +export MINGW_CHOST MINGW_PREFIX MINGW_PACKAGE_PREFIX +export DXSDK_DIR ACLOCAL_PATH PKG_CONFIG_PATH + if (( !REPKG )); then if (( NOEXTRACT && ! VERIFYSOURCE )); then warning "$(gettext "Using existing %s tree")" "\$srcdir/" @@ -1393,15 +1354,23 @@ else cd_safe "$startdir" fi - enter_fakeroot + # if inhibiting archive creation, go no further + if (( NOARCHIVE )); then + msg "$(gettext "Package directory is ready.")" + exit $E_OK + fi + mkdir -p "$pkgdirbase" + chmod a-srwx "$pkgdirbase" + chmod 755 "$pkgdirbase" + if (( ! SPLITPKG )); then + run_single_packaging + else + run_split_packaging + fi - create_package_signatures || exit $E_PRETTY_BAD_PRIVACY -fi + create_debug_package -# if inhibiting archive creation, go no further -if (( NOARCHIVE )); then - msg "$(gettext "Package directory is ready.")" - exit $E_OK + create_package_signatures || exit $E_PRETTY_BAD_PRIVACY fi msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date +%c))" diff --git a/scripts/pacman-db-upgrade.sh.in b/scripts/pacman-db-upgrade.sh.in index 6942cede3..899abd8b0 100644 --- a/scripts/pacman-db-upgrade.sh.in +++ b/scripts/pacman-db-upgrade.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash -e +#!/usr/bin/env bash # # pacman-db-upgrade - upgrade the local pacman db to a newer format # @@ -18,6 +18,8 @@ # along with this program. If not, see . # +set -e + # Avoid creating world-unreadable files umask 022 @@ -78,9 +80,13 @@ resolve_dir() { # PROGRAM START # determine whether we have gettext; make it a no-op if we do not -if ! type gettext &>/dev/null; then +if ! type -p gettext >/dev/null; then + gettext() { + printf "%s\n" "$@" + } +else gettext() { - echo "$@" + /usr/bin/gettext "$@" } fi @@ -137,7 +143,7 @@ lockfile="${dbroot}/db.lck" # make sure pacman isn't running if [[ -f $lockfile ]]; then - die "$(gettext "Pacman lock file was found. Cannot run while pacman is running.")" + die "$(/bin/gettext "Pacman lock file was found. Cannot run while pacman is running.")" fi # do not let pacman run while we do this touch "$lockfile" diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index f68d07671..85ceda9ec 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # pacman-key - manages pacman's keyring # Based on apt-key, from Debian @@ -30,6 +30,7 @@ MAKEPKG_LIBRARY=${MAKEPKG_LIBRARY:-'@libmakepkgdir@'} # Import libmakepkg source "$MAKEPKG_LIBRARY"/util/message.sh source "$MAKEPKG_LIBRARY"/util/parseopts.sh +source "$MAKEPKG_LIBRARY"/utils_fixed_path.sh # Options ADD=0 @@ -266,7 +267,7 @@ check_keyring() { exit 1 fi - if (( (EXPORT || FINGER || LIST || VERIFY) && EUID != 0 )); then + if (( EXPORT || FINGER || LIST || VERIFY )); then if ! grep -q "^[[:space:]]*lock-never[[:space:]]*$" ${PACMAN_KEYRING_DIR}/gpg.conf &>/dev/null; then error "$(gettext "You do not have sufficient permissions to run this command.")" msg "$(gettext "Use '%s' to correct the keyring permissions.")" "pacman-key --init" @@ -318,7 +319,9 @@ populate_keyring() { # Add keys from requested keyrings for keyring in "${KEYRINGIDS[@]}"; do msg "$(gettext "Appending keys from %s.gpg...")" "$keyring" - "${GPG_PACMAN[@]}" --quiet --import "${KEYRING_IMPORT_DIR}/${keyring}.gpg" + # FIXME: --allow-weak-key-signatures is a workaround for + # https://github.com/msys2/MSYS2-keyring/issues/45 + "${GPG_PACMAN[@]}" --allow-weak-key-signatures --quiet --import "${KEYRING_IMPORT_DIR}/${keyring}.gpg" done # Read the trusted key IDs to an array. Because this is an ownertrust @@ -433,7 +436,7 @@ import_trustdb() { local ret=0 for importdir in "$@"; do if [[ -f "${importdir}/trustdb.gpg" ]]; then - gpg --homedir "${importdir}" --export-ownertrust | \ + /usr/bin/gpg --homedir "${importdir}" --export-ownertrust | \ "${GPG_PACMAN[@]}" --import-ownertrust - if (( PIPESTATUS )); then error "$(gettext "%s could not be imported.")" "${importdir}/trustdb.gpg" @@ -565,7 +568,9 @@ refresh_keys() { done # if no key was found, fall back to using the keyservers (with the key fingerprint instead) - if (( $? )) && ! "${GPG_PACMAN[@]}" --refresh-keys "$id"; then + # FIXME: --allow-weak-key-signatures is a workaround for + # https://github.com/msys2/MSYS2-keyring/issues/45 + if (( $? )) && ! "${GPG_PACMAN[@]}" --allow-weak-key-signatures --refresh-keys "$id"; then error "$(gettext "Could not update key: %s")" "$id" ret=1 fi @@ -616,10 +621,14 @@ updatedb() { fi } -# PROGRAM START -if ! type gettext &>/dev/null; then +# determine whether we have gettext; make it a no-op if we do not +if ! type -p gettext >/dev/null; then gettext() { - echo "$@" + printf "%s\n" "$@" + } +else + gettext() { + /usr/bin/gettext "$@" } fi @@ -694,11 +703,6 @@ if ! type -p gpg >/dev/null; then exit 1 fi -if (( (ADD || DELETE || EDITKEY || IMPORT || IMPORT_TRUSTDB || INIT || LSIGNKEY || POPULATE || RECEIVE || REFRESH || UPDATEDB) && EUID != 0 )); then - error "$(gettext "%s needs to be run as root for this operation.")" "pacman-key" - exit 1 -fi - CONFIG=${CONFIG:-@sysconfdir@/pacman.conf} if [[ ! -r "${CONFIG}" ]]; then error "$(gettext "%s configuration file '%s' not found.")" "pacman" "$CONFIG" diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in index bdd549d20..5d37307c3 100644 --- a/scripts/repo-add.sh.in +++ b/scripts/repo-add.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # repo-add - add a package to a given repo database file # repo-remove - remove a package entry from a given repo database file @@ -49,6 +49,7 @@ DB_MODIFIED=0 source "$MAKEPKG_LIBRARY"/util/compress.sh source "$MAKEPKG_LIBRARY"/util/message.sh source "$MAKEPKG_LIBRARY"/util/parseopts.sh +source "$MAKEPKG_LIBRARY"/utils_fixed_path.sh # ensure we have a sane umask set umask 0022 @@ -534,7 +535,7 @@ create_db() { warning "$(gettext "No packages remain, creating empty database.")" files=(-T /dev/null) fi - bsdtar -cf - "${files[@]}" | compress_as "$filename" > "$tempname" + bsdtar --uid 1 --uname root --gid 1 --gname root -cf - "${files[@]}" | compress_as "$filename" > "$tempname" popd >/dev/null create_signature "$tempname" @@ -566,9 +567,13 @@ clean_up() { # PROGRAM START # determine whether we have gettext; make it a no-op if we do not -if ! type gettext &>/dev/null; then +if ! type -p gettext &>/dev/null; then gettext() { - echo "$@" + printf "%s\n" "$@" + } +else + gettext() { + /usr/bin/gettext "$@" } fi diff --git a/scripts/wrapper.sh.in b/scripts/wrapper.sh.in index 31b18d159..6f6eaa7f6 100644 --- a/scripts/wrapper.sh.in +++ b/scripts/wrapper.sh.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # @PROGNAME@ - a wrapper for running the real @PROGNAME@ in the source tree # diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 76527e40a..b7b52bd6a 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -152,8 +152,11 @@ static int64_t get_update_timediff(int first_call) /* refactored from cb_trans_progress */ static void fill_progress(const int percent, const int proglen) { - /* 8 = 1 space + 1 [ + 1 ] + 5 for percent */ - const int hashlen = proglen > 8 ? proglen - 8 : 0; + /* 9 = 1 space + 1 [ + 1 ] + 5 for percent + 1 blank */ + /* Without the single blank at the end, carriage return wouldn't + * work properly on most windows terminals. + */ + const int hashlen = proglen > 9 ? proglen - 9 : 0; const int hash = percent * hashlen / 100; int i; @@ -464,7 +467,7 @@ void cb_question(void *ctx, alpm_question_t *question) /* print conflict only if it contains new information */ if(strcmp(alpm_pkg_get_name(q->conflict->package1), q->conflict->reason->name) == 0 || strcmp(alpm_pkg_get_name(q->conflict->package2), q->conflict->reason->name) == 0) { - q->remove = noyes(_("%s-%s%s%s and %s-%s%s%s are in conflict. Remove %s?"), + q->remove = yesno(_("%s-%s%s%s and %s-%s%s%s are in conflict. Remove %s?"), alpm_pkg_get_name(q->conflict->package1), colstr->faint, alpm_pkg_get_version(q->conflict->package1), @@ -475,7 +478,7 @@ void cb_question(void *ctx, alpm_question_t *question) colstr->nocolor, alpm_pkg_get_name(q->conflict->package2)); } else { - q->remove = noyes(_("%s-%s%s%s and %s-%s%s%s are in conflict (%s). Remove %s?"), + q->remove = yesno(_("%s-%s%s%s and %s-%s%s%s are in conflict (%s). Remove %s?"), alpm_pkg_get_name(q->conflict->package1), colstr->faint, alpm_pkg_get_version(q->conflict->package1), @@ -505,7 +508,7 @@ void cb_question(void *ctx, alpm_question_t *question) count)); list_display(" ", namelist, getcols()); printf("\n"); - q->skip = noyes(_n( + q->skip = yesno(_n( "Do you want to skip the above package for this upgrade?", "Do you want to skip the above packages for this upgrade?", count)); diff --git a/src/pacman/check.c b/src/pacman/check.c index 6a39681c2..3d981c59e 100644 --- a/src/pacman/check.c +++ b/src/pacman/check.c @@ -75,6 +75,7 @@ static int check_file_permissions(const char *pkgname, const char *filepath, int errors = 0; mode_t fsmode; +#ifndef __MSYS__ /* uid */ if(st->st_uid != archive_entry_uid(entry)) { errors++; @@ -92,6 +93,7 @@ static int check_file_permissions(const char *pkgname, const char *filepath, pkgname, filepath); } } +#endif /* mode */ fsmode = st->st_mode & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO); diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 6b64ffc73..46c8ef8b3 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -1117,7 +1117,9 @@ static void cl_to_log(int argc, char *argv[]) int main(int argc, char *argv[]) { int ret = 0; +#ifndef __MSYS__ uid_t myuid = getuid(); +#endif console_cursor_hide(); install_segv_handler(); @@ -1161,11 +1163,13 @@ int main(int argc, char *argv[]) cleanup(ret); } +#ifndef __MSYS__ /* check if we have sufficient permission for the requested operation */ if(myuid > 0 && needs_root()) { pm_printf(ALPM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n")); cleanup(EXIT_FAILURE); } +#endif /* we support reading targets from stdin if a cmdline parameter is '-' */ if(alpm_list_find_str(pm_targets, "-")) { @@ -1183,6 +1187,12 @@ int main(int argc, char *argv[]) if(line[nread - 1] == '\n') { /* remove trailing newline */ line[nread - 1] = '\0'; +#ifdef __MSYS__ + if (line[nread - 2] == '\r') { + /* remove trailing carriage returns */ + line[nread - 2] = '\0'; + } +#endif } if(line[0] == '\0') { /* skip empty lines */ diff --git a/src/pacman/remove.c b/src/pacman/remove.c index 98f85deec..645619b26 100644 --- a/src/pacman/remove.c +++ b/src/pacman/remove.c @@ -140,7 +140,7 @@ int pacman_remove(alpm_list_t *targets) holdpkg = 1; } } - if(holdpkg && (noyes(_("HoldPkg was found in target list. Do you want to continue?")) == 0)) { + if(holdpkg && (yesno(_("HoldPkg was found in target list. Do you want to continue?")) == 0)) { retval = 1; goto cleanup; } diff --git a/src/pacman/sighandler.c b/src/pacman/sighandler.c index 3e869a31a..fc2bac69a 100644 --- a/src/pacman/sighandler.c +++ b/src/pacman/sighandler.c @@ -21,6 +21,10 @@ #include #include +#ifdef __MSYS__ +#include +#endif + #include #include "conf.h" @@ -53,8 +57,11 @@ static void _reset_handler(int signum) */ static void soft_interrupt_handler(int signum) { - console_cursor_move_end(); +#ifdef __MSYS__ + struct termios term; +#endif + console_cursor_move_end(); if(signum == SIGINT) { const char msg[] = "\nInterrupt signal received\n"; xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1); @@ -69,6 +76,13 @@ static void soft_interrupt_handler(int signum) return; } alpm_unlock(config->handle); +#ifdef __MSYS__ + /* restore input printing possibly disabled by core update */ + if(tcgetattr(STDIN_FILENO, &term) == 0) { + term.c_lflag |= ECHO; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); + } +#endif /* output a newline to be sure we clear any line we may be on */ xwrite(STDOUT_FILENO, "\n", 1); _Exit(128 + signum); diff --git a/src/pacman/sync.c b/src/pacman/sync.c index 95340db11..03a307cce 100644 --- a/src/pacman/sync.c +++ b/src/pacman/sync.c @@ -28,6 +28,12 @@ #include #include +#ifdef __MSYS__ +#include +#include +#include +#endif + #include #include @@ -193,7 +199,7 @@ static int sync_cleancache(int level) } printf(_("removing old packages from cache...\n")); } else { - if(!noyes(_("Do you want to remove ALL files from cache?"))) { + if(!yesno(_("Do you want to remove ALL files from cache?"))) { printf("\n"); continue; } @@ -699,8 +705,134 @@ static int process_target(const char *target, int error) return ret; } +#ifdef __MSYS__ + +/* Tries to kill all cygwin processes except this one */ +static int kill_all_other_msys_processes() { + DIR *dir; + struct dirent *ent; + char self_winpid[50]; + int found_one = 0; + FILE *self = NULL; + size_t proc_entries = 0; + char **args = NULL; + size_t pos = 0; + + self = fopen("/proc/self/winpid", "r"); + if (self == NULL) + return -1; + fscanf(self, "%s", self_winpid); + fclose(self); + + dir = opendir("/proc"); + if (dir == NULL) + return -1; + + while ((ent = readdir(dir))) + proc_entries++; + seekdir(dir, 0); + + args = alloca(sizeof(char *) * (2 + (proc_entries * 2) + 1)); + args[pos++] = "taskkill"; + args[pos++] = "/F"; + + while ((ent = readdir (dir))) { + FILE *fp = NULL; + char winpid_path[PATH_MAX]; + + strcpy(winpid_path, "/proc/"); + strcat(winpid_path, ent->d_name); + strcat(winpid_path, "/winpid"); + + fp = fopen(winpid_path, "r"); + if (fp != NULL) { + char winpid[50]; + fscanf(fp, "%s", winpid); + + if (strcmp(winpid, self_winpid) != 0) { + args[pos++] = "/pid"; + char *pidarg = alloca(strlen(winpid) + 1); + strcpy(pidarg, winpid); + args[pos++] = pidarg; + found_one = 1; + } + + fclose(fp); + } + } + args[pos] = NULL; + closedir(dir); + + if (!found_one) + return 0; + + setenv("MSYS2_ARG_CONV_EXCL", "*", 1); + if (execvp(args[0], args) == -1) { + return -1; + } + + return 0; +} + +static int core_update(int *needed) +{ + int retval; + alpm_list_t *i; + alpm_list_t *core = NULL; + + colon_printf(_("Starting core system upgrade...\n")); + alpm_logaction(config->handle, PACMAN_CALLER_PREFIX, + "starting core system upgrade\n"); + + if(alpm_sync_sysupgrade_core(config->handle, config->op_s_upgrade >= 2) == -1) { + pm_printf(ALPM_LOG_ERROR, "%s\n", alpm_strerror(alpm_errno(config->handle))); + trans_release(); + return 1; + } + + *needed = 0; + for(i = alpm_trans_get_add(config->handle); i; i = i->next) { + alpm_pkg_t *pkg = i->data; + if (alpm_pkg_is_core_package(pkg)) { + core = alpm_list_add(core, pkg); + *needed = 1; + } + } + + if(!(*needed)) { + if (!config->print) { + printf(_(" there is nothing to do\n")); + } + return 0; + } + + /* hooks are most likely doomed to fail in a core upgrade, so disable them */ + alpm_option_set_hookdirs(config->handle, NULL); + + config->handle->trans->add = core; + pm_printf(ALPM_LOG_WARNING, _("terminate other MSYS2 programs before proceeding\n")); + retval = sync_prepare_execute(); + if(retval == 0) { + int response = 0; + do { + response = yesno(_("To complete this update all MSYS2 processes including this terminal will be closed. Confirm to proceed")); + } while(!response); + + if (kill_all_other_msys_processes() != 0) { + pm_printf(ALPM_LOG_WARNING, _("terminating MSYS2 processes failed\n")); + exit(1); + } + exit(0); + } + return retval; +} +#endif + static int sync_trans(alpm_list_t *targets) { +#ifdef __MSYS__ + int found_core_updates = 0; +#endif int retval = 0; alpm_list_t *i; @@ -723,6 +855,14 @@ static int sync_trans(alpm_list_t *targets) } if(config->op_s_upgrade) { +#ifdef __MSYS__ + if((retval = core_update(&found_core_updates))) { + return retval; + } + if(found_core_updates) { + return retval; + } +#endif if(!config->print) { colon_printf(_("Starting full system upgrade...\n")); alpm_logaction(config->handle, PACMAN_CALLER_PREFIX, diff --git a/test/pacman/ldconfig.stub b/test/pacman/ldconfig.stub deleted file mode 100755 index d261a04a2..000000000 --- a/test/pacman/ldconfig.stub +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# A simple stub to copy into the chroot to fake ldconfig. -# Simply appends a line to /etc/ld.so.cache if called. -echo "ldconfig called" >> /etc/ld.so.cache diff --git a/test/pacman/meson.build b/test/pacman/meson.build index c26ce0fab..5653b1cd3 100644 --- a/test/pacman/meson.build +++ b/test/pacman/meson.build @@ -80,9 +80,6 @@ pacman_tests = [ 'tests/ignore006.py', 'tests/ignore007.py', 'tests/ignore008.py', - 'tests/ldconfig001.py', - 'tests/ldconfig002.py', - 'tests/ldconfig003.py', 'tests/mode001.py', 'tests/mode002.py', 'tests/mode003.py', @@ -359,7 +356,6 @@ foreach input : pacman_tests join_paths(meson.current_source_dir(), 'pactest.py'), '--scriptlet-shell', get_option('scriptlet-shell'), '--bindir', meson.project_build_root(), - '--ldconfig', LDCONFIG, '--verbose', join_paths(meson.current_source_dir(), input) ] diff --git a/test/pacman/pactest.py b/test/pacman/pactest.py index c6add2330..d9f0445bd 100755 --- a/test/pacman/pactest.py +++ b/test/pacman/pactest.py @@ -104,9 +104,6 @@ def create_parser(): parser.add_option("--scriptlet-shell", type = "string", dest = "scriptletshell", default = "/bin/sh", help = "specify path to shell used for install scriptlets") - parser.add_option("--ldconfig", type = "string", - dest = "ldconfig", default = "/sbin/ldconfig", - help = "specify path to ldconfig") parser.add_option("--review", action = "store_true", dest = "review", default = False, help = "review test files, test output, and saved logs") @@ -146,7 +143,6 @@ def create_parser(): env.pacman["valgrind"] = opts.valgrind env.pacman["manual-confirm"] = opts.manualconfirm env.pacman["scriptlet-shell"] = opts.scriptletshell - env.pacman["ldconfig"] = opts.ldconfig env.config["gpg"] = not opts.missing_gpg env.config["nls"] = not opts.missing_nls env.config["curl"] = not opts.missing_curl diff --git a/test/pacman/pmtest.py b/test/pacman/pmtest.py index f5f033fa1..742db1a9d 100644 --- a/test/pacman/pmtest.py +++ b/test/pacman/pmtest.py @@ -134,12 +134,10 @@ def generate(self, pacman): logdir = os.path.join(self.root, os.path.dirname(util.LOGFILE)) etcdir = os.path.join(self.root, os.path.dirname(util.PACCONF)) bindir = os.path.join(self.root, "bin") - ldconfig = os.path.basename(pacman["ldconfig"]) - ldconfigdir = os.path.join(self.root, os.path.dirname(pacman["ldconfig"][1:])) shell = pacman["scriptlet-shell"][1:] shelldir = os.path.join(self.root, os.path.dirname(shell)) sys_dirs = [dbdir, cachedir, syncdir, tmpdir, logdir, etcdir, bindir, - ldconfigdir, shelldir] + shelldir] for sys_dir in sys_dirs: if not os.path.isdir(sys_dir): vprint("\t%s" % sys_dir[len(self.root)+1:]) @@ -148,10 +146,6 @@ def generate(self, pacman): shutil.copy("/bin/sh", bindir) if shell != "bin/sh": shutil.copy("/bin/sh", os.path.join(self.root, shell)) - shutil.copy(os.path.join(util.SELFPATH, "ldconfig.stub"), - os.path.join(ldconfigdir, ldconfig)) - ld_so_conf = open(os.path.join(etcdir, "ld.so.conf"), "w") - ld_so_conf.close() # Configuration file vprint(" Creating configuration file") @@ -240,21 +234,6 @@ def run(self, pacman): vprint("\tpacman %s" % self.args) cmd = [] - if os.geteuid() != 0: - # fakechroot must be called before fakeroot due to potential - # potential interactions when wrapping the same C functions - fakechroot = util.which("fakechroot") - if not fakechroot: - tap.diag("WARNING: fakechroot not found!") - else: - cmd.append("fakechroot") - - fakeroot = util.which("fakeroot") - if not fakeroot: - tap.diag("WARNING: fakeroot not found!") - else: - cmd.append("fakeroot") - if pacman["gdb"]: cmd.extend(["libtool", "execute", "gdb", "--args"]) if pacman["valgrind"]: @@ -297,8 +276,10 @@ def run(self, pacman): # Change to the tmp dir before running pacman, so that local package # archives are made available more easily. time_start = time.time() - self.retcode = subprocess.call(cmd, stdout=output, stderr=output, - cwd=os.path.join(self.root, util.TMPDIR), env={'LC_ALL': 'C'}) + self.retcode = subprocess.call(cmd, + cwd=os.path.join(self.root, util.TMPDIR), + env={'LC_ALL': 'C', 'PATH': os.environ['PATH']}, + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) time_end = time.time() vprint("\ttime elapsed: %.2fs" % (time_end - time_start)) diff --git a/test/pacman/tests/TESTS b/test/pacman/tests/TESTS index 74c8f6749..b29181bb6 100644 --- a/test/pacman/tests/TESTS +++ b/test/pacman/tests/TESTS @@ -78,9 +78,6 @@ TESTS += test/pacman/tests/ignore005.py TESTS += test/pacman/tests/ignore006.py TESTS += test/pacman/tests/ignore007.py TESTS += test/pacman/tests/ignore008.py -TESTS += test/pacman/tests/ldconfig001.py -TESTS += test/pacman/tests/ldconfig002.py -TESTS += test/pacman/tests/ldconfig003.py TESTS += test/pacman/tests/mode001.py TESTS += test/pacman/tests/mode002.py TESTS += test/pacman/tests/mode003.py diff --git a/test/pacman/tests/ldconfig001.py b/test/pacman/tests/ldconfig001.py deleted file mode 100644 index a97f28c18..000000000 --- a/test/pacman/tests/ldconfig001.py +++ /dev/null @@ -1,9 +0,0 @@ -self.description = "Make sure ldconfig runs on an upgrade operation" - -p = pmpkg("dummy") -self.addpkg(p) - -self.args = "-U %s" % p.filename() - -self.addrule("PACMAN_RETCODE=0") -self.addrule("FILE_EXIST=etc/ld.so.cache") diff --git a/test/pacman/tests/ldconfig002.py b/test/pacman/tests/ldconfig002.py deleted file mode 100644 index 07f2ec698..000000000 --- a/test/pacman/tests/ldconfig002.py +++ /dev/null @@ -1,13 +0,0 @@ -self.description = "Make sure ldconfig runs on an upgrade operation" - -lp = pmpkg("dummy") -self.addpkg2db("local", lp) - -p = pmpkg("dummy", "1.0-2") -self.addpkg(p) - -self.args = "-U %s" % p.filename() - -self.addrule("PACMAN_RETCODE=0") -self.addrule("PKG_VERSION=dummy|1.0-2") -self.addrule("FILE_EXIST=etc/ld.so.cache") diff --git a/test/pacman/tests/ldconfig003.py b/test/pacman/tests/ldconfig003.py deleted file mode 100644 index 9b2967e24..000000000 --- a/test/pacman/tests/ldconfig003.py +++ /dev/null @@ -1,9 +0,0 @@ -self.description = "Make sure ldconfig runs on a sync operation" - -sp = pmpkg("dummy") -self.addpkg2db("sync", sp) - -self.args = "-S %s" % sp.name - -self.addrule("PACMAN_RETCODE=0") -self.addrule("FILE_EXIST=etc/ld.so.cache")