From cd4ebcade22c8f86264be07adcb6f8085aceadfc Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Fri, 16 May 2025 04:28:44 +0800
Subject: [PATCH 17/17] Restore support for 10.4

Reverts https://github.com/macports/macports-base/commit/fe87793b8e5bb4a05bc432a3c3b17b3fb870b0c7
---
 Makefile.in                           |  8 +++
 configure                             | 12 +++-
 configure.ac                          |  8 +--
 doc/Makefile.in                       | 18 ++++-
 portmgr/dmg/InstallationCheck.strings |  2 +-
 portmgr/dmg/postflight.in             | 15 ++++
 src/config.h.in                       |  3 +
 src/cregistry/registry.c              |  9 ++-
 src/cregistry/sql.c                   | 99 +++++++++++++++++++++++++++
 src/machista1.0/libmachista.c         | 32 ++++++++-
 src/macports1.0/macports.tcl          |  5 ++
 src/package1.0/portdmg.tcl            |  2 +-
 src/package1.0/portmdmg.tcl           |  2 +-
 src/package1.0/portpkg.tcl            | 10 ++-
 src/pextlib1.0/curl.c                 | 39 +++++++++++
 src/pextlib1.0/sha256cmd.c            |  9 +++
 src/port/Makefile.in                  |  2 +
 src/port1.0/portconfigure.tcl         |  7 +-
 src/port1.0/portstartupitem.tcl       | 12 +++-
 src/port1.0/portutil.tcl              | 14 +++-
 20 files changed, 287 insertions(+), 21 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index efc1e1333..0da158d9a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -87,6 +87,14 @@ ifeq ($(DESTDIR),)
                         echo "    ${DSCL} -q . -create \"/Users/${RUNUSR}\" NFSHomeDirectory \"${localstatedir}/macports/home\"" ; \
                     fi ; \
                 fi ; \
+                if test "@OS_MAJOR@" -eq 8 -a `id -u` -eq 0; then \
+                    GID=`${DSCL} -q . -read "/Groups/${RUNUSR}" PrimaryGroupID | /usr/bin/awk '{print $$2}'` ; \
+                    if test "`${DSCL} -q . -read "/Users/${RUNUSR}" PrimaryGroupID 2>/dev/null | /usr/bin/awk '{print $$2}'`" != "$$GID"; then \
+                        echo "Fixing PrimaryGroupID for user \"${RUNUSR}\"" ; \
+                        ${DSCL} -q . -create "/Users/${RUNUSR}" PrimaryGroupID $$GID ; \
+                        ${DSCL} -q . -create "/Users/${RUNUSR}" RealName MacPorts ; \
+                    fi ; \
+                fi ; \
             fi ; \
         else \
             echo "Can't find ${DSCL} / ${DSEDITGROUP}, not creating user \"${RUNUSR}\"" ; \
diff --git a/configure b/configure
index 1311a1f7d..7222ee59d 100755
--- a/configure
+++ b/configure
@@ -3113,10 +3113,10 @@ printf "%s\n" "$MACOSX_VERSION" >&6; }
 fi
 
 case "$MACOSX_VERSION" in
-  10.[0-4]|10.[0-4].*)
-    as_fn_error $? "MacPorts requires Mac OS X 10.5 or later." "$LINENO" 5
+  10.[0-3]|10.[0-3].*)
+    as_fn_error $? "MacPorts requires Mac OS X 10.4 or later." "$LINENO" 5
     ;;
-  10.5|10.5.[1-7]|10.6|10.6.[1-7]|10.7|10.7.[1-4])
+  10.4|10.4.[1-9]|10.4.10|10.5|10.5.[1-7]|10.6|10.6.[1-7]|10.7|10.7.[1-4])
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: This version of Mac OS X is out of date" >&5
 printf "%s\n" "$as_me: WARNING: This version of Mac OS X is out of date" >&2;}
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Please run Software Update to update it" >&5
@@ -7683,6 +7683,12 @@ if test "x$ac_cv_func_flock" = xyes
 then :
   printf "%s\n" "#define HAVE_FLOCK 1" >>confdefs.h
 
+fi
+ac_fn_c_check_func "$LINENO" "fls" "ac_cv_func_fls"
+if test "x$ac_cv_func_fls" = xyes
+then :
+  printf "%s\n" "#define HAVE_FLS 1" >>confdefs.h
+
 fi
 ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy"
 if test "x$ac_cv_func_getentropy" = xyes
diff --git a/configure.ac b/configure.ac
index 510d82672..d9ec24e2e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,10 +28,10 @@ if test "x$SW_VERS" != "x"; then
 fi
 
 case "$MACOSX_VERSION" in
-  10.[[0-4]]|10.[[0-4]].*)
-    AC_MSG_ERROR([MacPorts requires Mac OS X 10.5 or later.])
+  10.[[0-3]]|10.[[0-3]].*)
+    AC_MSG_ERROR([MacPorts requires Mac OS X 10.4 or later.])
     ;;
-  10.5|10.5.[[1-7]]|10.6|10.6.[[1-7]]|10.7|10.7.[[1-4]])
+  10.4|10.4.[[1-9]]|10.4.10|10.5|10.5.[[1-7]]|10.6|10.6.[[1-7]]|10.7|10.7.[[1-4]])
     AC_MSG_WARN([This version of Mac OS X is out of date])
     AC_MSG_WARN([Please run Software Update to update it])
     ;;
@@ -258,7 +258,7 @@ AC_SUBST(HAVE_DECL_RPP_STDIN, $ac_cv_have_decl_RPP_STDIN)
 # Checks for library functions.
 AC_CHECK_FUNCS([OSAtomicCompareAndSwap32 OSAtomicCompareAndSwap64 \
 	OSAtomicCompareAndSwapPtr __getdirentries64 arc4random_buf clearenv \
-	clonefile copyfile _dyld_shared_cache_contains_path flock \
+	clonefile copyfile _dyld_shared_cache_contains_path flock fls \
 	getentropy kqueue posix_spawn setmode sysctlbyname timingsafe_bcmp])
 
 # For vendor/signify
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 653514fcc..c6208abc5 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -162,7 +162,20 @@ distclean: clean
 %.html: %.soelim
 	ln -sf $(shell basename $$(awk '{print $$2}' < $<)).html $@
 
-HAVE_DOCS_REQS= $(and $(ASCIIDOC),$(XSLTPROC),$(DOCBOOK_XSL))
+# Define these rules only if asciidoc, xsltproc, and docbook_zsl are
+# all available. GNU Make 3.80 (MacOSX 10.4) 'and' does not work, so
+# do the check manually. 'and' works in GNU Make 3.81 (MacOSX 10.5+).
+ifeq ("$(MAKE_VERSION)","3.80")
+ ifneq ($(ASCIIDOC),)
+  ifneq ($(XSLTPROC),)
+   ifneq ($(DOCBOOK_XSL),)
+    HAVE_DOCS_REQS= 1
+   endif
+  endif
+ endif
+else
+ HAVE_DOCS_REQS= $(and $(ASCIIDOC),$(XSLTPROC),$(DOCBOOK_XSL))
+endif
 ifneq ($(HAVE_DOCS_REQS),)
 %: %.xml manpage.xsl
 	$(XSLTPROC) $(XSLTFLAGS) manpage.xsl $<
@@ -193,8 +206,11 @@ install: all
 	< prefix.mtree $(MTREE) -U -e -p "${DESTDIR}${INSTALLDIR}" > /dev/null
 	< base.mtree $(MTREE) -U -e -p "${DESTDIR}${INSTALLDIR}" > /dev/null
 ifeq (darwin,@OS_PLATFORM@)
+ifneq (8,@OS_MAJOR@)
+# Tiger's chmod doesn't accept -h
 # mtree with umask 0077 doesn't get the permissions of the symlink right
 	chmod -h 755 "${DESTDIR}${INSTALLDIR}/man"
+endif
 endif
 
 	for f in ${CONF}; do \
diff --git a/portmgr/dmg/InstallationCheck.strings b/portmgr/dmg/InstallationCheck.strings
index 6a66f339f..314401125 100644
--- a/portmgr/dmg/InstallationCheck.strings
+++ b/portmgr/dmg/InstallationCheck.strings
@@ -1,4 +1,4 @@
 "16" = "Either uname or sed could not be found in PATH. Your system appears to be incomplete or misconfigured.";
-"17" = "Xcode is not installed, or was installed with UNIX Development deselected.";
+"17" = "Xcode is not installed, or was installed with UNIX Development (10.5+) or Command Line Support (10.4) deselected.";
 "18" = "This package is meant to be installed on Mac OS X __XVERS__.";
 "19" = "Your existing MacPorts or DarwinPorts installation is too old to be upgraded by this installer. Please install MacPorts 1.7.1 first.";
diff --git a/portmgr/dmg/postflight.in b/portmgr/dmg/postflight.in
index 1d7dc83ee..f846cac40 100755
--- a/portmgr/dmg/postflight.in
+++ b/portmgr/dmg/postflight.in
@@ -209,6 +209,14 @@ function create_run_user {
     RUNUSR_UID=$(${DSCL} -q . -read "/Users/${RUNUSR}" UniqueID | /usr/bin/awk '{print $2}')
     RUNUSR_NAME=$(${DSCL} -q . -read "/Users/${RUNUSR}" RealName | /usr/bin/awk '{print $2}')
     RUNUSR_SHELL=$(${DSCL} -q . -read "/Users/${RUNUSR}" UserShell | /usr/bin/awk '{print $2}')
+    if [[ "${OS_MAJOR}" -eq 8 ]]; then
+        GID=$(${DSCL} -q . -read "/Groups/${RUNUSR}" PrimaryGroupID | /usr/bin/awk '{print $2}')
+        if [[ "$(${DSCL} -q . -read "/Users/${RUNUSR}" PrimaryGroupID 2>/dev/null | /usr/bin/awk '{print $2}')" != "$GID" ]]; then
+            echo "Fixing PrimaryGroupID for user \"${RUNUSR}\""
+            ${DSCL} -q . -create "/Users/${RUNUSR}" PrimaryGroupID "$GID"
+            ${DSCL} -q . -create "/Users/${RUNUSR}" RealName MacPorts
+        fi
+    fi
     if test "$RUNUSR_UID" -gt 500 -a "$RUNUSR_SHELL" = "/usr/bin/false" -a "$RUNUSR_NAME" = "MacPorts"; then
         if [[ "$(${DSCL} -q . -read "/Users/${RUNUSR}" NFSHomeDirectory)" != "NFSHomeDirectory: ${PREFIX}/var/macports/home" ]]; then
             echo "Updating home directory location for user \"${RUNUSR}\""
@@ -319,6 +327,13 @@ if /usr/bin/su "${USER}" -l -c "/usr/bin/printenv MANPATH" > /dev/null; then
     fi
 fi
 
+# Adding a DISPLAY variable only if we're running on Tiger or less and if it doesn't already exist:
+if [[ "${OS_MAJOR}" -ge 9 ]] || /usr/bin/su "${USER}" -l -c "/usr/bin/printenv DISPLAY" > /dev/null; then
+    echo "Your shell already has the right DISPLAY environment variable for use with MacPorts!"
+else
+    write_setting DISPLAY ":0"
+fi
+
 # Postflight script is done with its job, update MacPorts and exit gracefully!
 update_macports
 echo "You have successfully installed the MacPorts system. Launch a terminal and try it out!"
diff --git a/src/config.h.in b/src/config.h.in
index e0ee49262..4106efea6 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -71,6 +71,9 @@
 /* Define to 1 if you have the 'flock' function. */
 #undef HAVE_FLOCK
 
+/* Define to 1 if you have the 'fls' function. */
+#undef HAVE_FLS
+
 /* Define if CoreFoundation framework is available */
 #undef HAVE_FRAMEWORK_COREFOUNDATION
 
diff --git a/src/cregistry/registry.c b/src/cregistry/registry.c
index a778e2daa..b280764d7 100644
--- a/src/cregistry/registry.c
+++ b/src/cregistry/registry.c
@@ -128,8 +128,13 @@ int reg_open(reg_registry** regPtr, reg_error* errPtr) {
         return 0;
     }
     if (sqlite3_open(NULL, &reg->db) == SQLITE_OK) {
-        /* Enable extended result codes, requires SQLite >= 3.3.8 */
-        sqlite3_extended_result_codes(reg->db, 1);
+        /* Enable extended result codes, requires SQLite >= 3.3.8
+         * Check added for compatibility with Tiger. */
+#if SQLITE_VERSION_NUMBER >= 3003008
+        if (sqlite3_libversion_number() >= 3003008) {
+            sqlite3_extended_result_codes(reg->db, 1);
+        }
+#endif
 
         sqlite3_busy_timeout(reg->db, 25);
 
diff --git a/src/cregistry/sql.c b/src/cregistry/sql.c
index 1995463b2..0ab2a9b58 100644
--- a/src/cregistry/sql.c
+++ b/src/cregistry/sql.c
@@ -346,8 +346,41 @@ int update_db(sqlite3* db, reg_error* errPtr) {
             /* we need to update to 1.1, add binary field and index to files
              * table */
             static char* version_1_1_queries[] = {
+#if SQLITE_VERSION_NUMBER >= 3002000
                 "ALTER TABLE registry.files ADD COLUMN binary BOOL",
+#else
+                /*
+                 * SQLite < 3.2.0 doesn't support ALTER TABLE ADD COLUMN
+                 * Unfortunately, Tiger ships with SQLite < 3.2.0 (#34463)
+                 * This is taken from http://www.sqlite.org/faq.html#q11
+                 */
+
+                /* Create a temporary table */
+                "CREATE TEMPORARY TABLE mp_files_backup (id INTEGER, path TEXT, "
+                    "actual_path TEXT, active INT, mtime DATETIME, md5sum TEXT, editable INT, "
+                    "FOREIGN KEY(id) REFERENCES ports(id))",
+
+                /* Copy all data into the temporary table */
+                "INSERT INTO mp_files_backup SELECT id, path, actual_path, active, mtime, "
+                    "md5sum, editable FROM registry.files",
+
+                /* Drop the original table and re-create it with the new structure */
+                "DROP TABLE registry.files",
+                "CREATE TABLE registry.files (id INTEGER, path TEXT, actual_path TEXT, "
+                    "active INT, mtime DATETIME, md5sum TEXT, editable INT, binary BOOL, "
+                    "FOREIGN KEY(id) REFERENCES ports(id))",
+                "CREATE INDEX registry.file_port ON files(id)",
+                "CREATE INDEX registry.file_path ON files(path)",
+                "CREATE INDEX registry.file_actual ON files(actual_path)",
+
+                /* Copy all data back from temporary table */
+                "INSERT INTO registry.files (id, path, actual_path, active, mtime, md5sum, "
+                    "editable) SELECT id, path, actual_path, active, mtime, md5sum, "
+                    "editable FROM mp_files_backup",
 
+                /* Remove temporary table */
+                "DROP TABLE mp_files_backup",
+#endif
                 "CREATE INDEX registry.file_binary ON files(binary)",
 
                 "UPDATE registry.metadata SET value = '1.100' WHERE key = 'version'",
@@ -634,8 +667,74 @@ int update_db(sqlite3* db, reg_error* errPtr) {
         if (sql_version(NULL, -1, version, -1, "1.204") < 0) {
             /* add */
             static char* version_1_204_queries[] = {
+#if SQLITE_VERSION_NUMBER >= 3002000
                 "ALTER TABLE registry.ports ADD COLUMN cxx_stdlib TEXT",
                 "ALTER TABLE registry.ports ADD COLUMN cxx_stdlib_overridden INTEGER",
+#else
+                /* Create a temporary table */
+                "CREATE TEMPORARY TABLE mp_ports_backup ("
+                "id INTEGER PRIMARY KEY"
+                ", name TEXT COLLATE NOCASE"
+                ", portfile TEXT"
+                ", location TEXT"
+                ", epoch INTEGER"
+                ", version TEXT COLLATE VERSION"
+                ", revision INTEGER"
+                ", variants TEXT"
+                ", negated_variants TEXT"
+                ", state TEXT"
+                ", date DATETIME"
+                ", installtype TEXT"
+                ", archs TEXT"
+                ", requested INTEGER"
+                ", os_platform TEXT"
+                ", os_major INTEGER"
+                ", UNIQUE (name, epoch, version, revision, variants)"
+                ")",
+
+                /* Copy all data into the temporary table */
+                "INSERT INTO mp_ports_backup SELECT id, name, portfile, location, epoch, "
+                    "version, revision, variants, negated_variants, state, date, installtype, "
+                    "archs, requested, os_platform, os_major FROM registry.ports",
+
+                /* Drop the original table and re-create it with the new structure */
+                "DROP TABLE registry.ports",
+                "CREATE TABLE registry.ports ("
+                "id INTEGER PRIMARY KEY"
+                ", name TEXT COLLATE NOCASE"
+                ", portfile TEXT"
+                ", location TEXT"
+                ", epoch INTEGER"
+                ", version TEXT COLLATE VERSION"
+                ", revision INTEGER"
+                ", variants TEXT"
+                ", negated_variants TEXT"
+                ", state TEXT"
+                ", date DATETIME"
+                ", installtype TEXT"
+                ", archs TEXT"
+                ", requested INTEGER"
+                ", os_platform TEXT"
+                ", os_major INTEGER"
+                ", cxx_stdlib TEXT"
+                ", cxx_stdlib_overridden INTEGER"
+                ", UNIQUE (name, epoch, version, revision, variants)"
+                ")",
+                "CREATE INDEX registry.port_name ON ports"
+                    "(name, epoch, version, revision, variants)",
+                "CREATE INDEX registry.port_state ON ports(state)",
+
+                /* Copy all data back from temporary table */
+                "INSERT INTO registry.ports (id, name, portfile, location, epoch, version, "
+                    "revision, variants, negated_variants, state, date, installtype, archs, "
+                    "requested, os_platform, os_major) SELECT id, name, portfile, location, "
+                    "epoch, version, revision, variants, negated_variants, state, date, "
+                    "installtype, archs, requested, os_platform, os_major "
+                    "FROM mp_ports_backup",
+
+                /* Remove temporary table */
+                "DROP TABLE mp_ports_backup",
+#endif
 
                 "UPDATE registry.metadata SET value = '1.204' WHERE key = 'version'",
                 "COMMIT",
diff --git a/src/machista1.0/libmachista.c b/src/machista1.0/libmachista.c
index b758d1400..17b09a5bb 100644
--- a/src/machista1.0/libmachista.c
+++ b/src/machista1.0/libmachista.c
@@ -63,6 +63,25 @@
 #include "hashmap.h"
 #include "strlcpy.h"
 
+#ifdef __MACH__
+/* Tiger compatibility */
+#ifndef LC_RPATH
+#define LC_RPATH       (0x1c | LC_REQ_DYLD)    /* runpath additions */
+/*
+ * The rpath_command contains a path which at runtime should be added to
+ * the current run path used to find @rpath prefixed dylibs.
+ */
+struct rpath_command {
+    uint32_t     cmd;       /* LC_RPATH */
+    uint32_t     cmdsize;   /* includes string */
+    union lc_str path;      /* path to add to run path */
+};
+#endif
+#ifndef LC_REEXPORT_DYLIB
+#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */
+#endif
+#endif /* __MACH__ */
+
 typedef struct macho_input {
     const void *data;
     size_t length;
@@ -533,7 +552,17 @@ void macho_destroy_handle(macho_handle_t *handle) {
 /* Returns string representation of the MACHO_* error code constants */
 const char *macho_strerror(int err) {
 #ifdef __MACH__
-    int num = fls(err);
+    int num;
+#ifdef HAVE_FLS
+    num = fls(err);
+#else
+    /* Tiger compatibility, see #42186 */
+    num = 0;
+    while (err > 0) {
+        err >>= 1;
+        num++;
+    }
+#endif
 
     static char *errors[] = {
         /* 0x00 */ "Success",
@@ -549,4 +578,3 @@ const char *macho_strerror(int err) {
     return "";
 #endif
 }
-
diff --git a/src/macports1.0/macports.tcl b/src/macports1.0/macports.tcl
index ba774c12d..b48fb5a29 100644
--- a/src/macports1.0/macports.tcl
+++ b/src/macports1.0/macports.tcl
@@ -6829,6 +6829,11 @@ proc macports::get_parallel_jobs {{mem_restrict yes}} {
 proc macports::get_compatible_xcode_versions {} {
     variable macos_version_major
     switch $macos_version_major {
+        10.4 {
+            set min 2.0
+            set ok 2.4.1
+            set rec 2.5
+        }
         10.5 {
             set min 3.0
             set ok 3.1
diff --git a/src/package1.0/portdmg.tcl b/src/package1.0/portdmg.tcl
index 83e167337..39ae1470a 100644
--- a/src/package1.0/portdmg.tcl
+++ b/src/package1.0/portdmg.tcl
@@ -71,7 +71,7 @@ proc portdmg::package_dmg {portname portversion portrevision} {
     }
 
     # partition for .dmg
-    if {${os.arch} in {arm i386}} {
+    if {${os.major} >= 9 && ${os.arch} eq "i386"} {
         # GUID_partition_scheme
         set subdev 1
     } else {
diff --git a/src/package1.0/portmdmg.tcl b/src/package1.0/portmdmg.tcl
index 369635156..885f4e7ec 100644
--- a/src/package1.0/portmdmg.tcl
+++ b/src/package1.0/portmdmg.tcl
@@ -71,7 +71,7 @@ proc portmdmg::package_mdmg {portname portversion portrevision} {
     }
 
     # partition for .dmg
-    if {${os.arch} in {arm i386}} {
+    if {${os.major} >= 9 && ${os.arch} eq "i386"} {
         # GUID_partition_scheme
         set subdev 1
     } else {
diff --git a/src/package1.0/portpkg.tcl b/src/package1.0/portpkg.tcl
index e7c2c1baf..3096a3d9e 100644
--- a/src/package1.0/portpkg.tcl
+++ b/src/package1.0/portpkg.tcl
@@ -101,7 +101,7 @@ proc portpkg::pkg_start {args} {
     write_welcome_html ${package.resources}/${language}.lproj/Welcome.html $subport $version $revision $pkg_long_description $pkg_description $pkg_homepage
     file copy -force -- [getportresourcepath $porturl "port1.0/package/background.tiff"] ${package.resources}/${language}.lproj/background.tiff
 
-    if {${package.flat}} {
+    if {${package.flat} && ${os.major} >= 9} {
         write_distribution "${workpath}/Distribution" $subport $version $revision
     }
 }
@@ -154,6 +154,7 @@ proc portpkg::package_pkg {portname portepoch portversion portrevision} {
 
     set using_pkgbuild [expr {$pkgbuild ne "" && ${package.flat}}]
     if {$using_pkgbuild || [file exists "$packagemaker"]} {
+      if {${os.major} >= 9} {
         if {${package.flat}} {
             set pkgtarget "10.5"
             set pkgresources " --scripts [shellescape ${package.scripts}]"
@@ -195,6 +196,11 @@ proc portpkg::package_pkg {portname portepoch portversion portrevision} {
             ui_debug "Running command line: $cmdline"
             system $cmdline
         }
+      } else {
+            write_info_plist ${workpath}/Info.plist $portname $portversion $portrevision
+            write_description_plist ${workpath}/Description.plist $portname $portversion $description
+            system "[shellescape $packagemaker] -build -f [shellescape ${destpath}] -p [shellescape ${pkgpath}] -r [shellescape ${package.resources}] -i [shellescape ${workpath}/Info.plist] -d [shellescape ${workpath}/Description.plist]"
+      }
 
         file delete ${workpath}/Info.plist \
                     ${workpath}/PackageInfo \
diff --git a/src/pextlib1.0/curl.c b/src/pextlib1.0/curl.c
index 948492f93..197911d0a 100644
--- a/src/pextlib1.0/curl.c
+++ b/src/pextlib1.0/curl.c
@@ -739,6 +739,45 @@ CurlFetchCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[])
 		(void) fclose(theFile);
 		theFile = NULL;
 
+#if LIBCURL_VERSION_NUM == 0x070d01 /* work around broken Tiger version of curl */
+		if (remotetime) {
+			FILE *fp;
+			char *tmp, *p;
+			char buf[BUFSIZ];
+			size_t size;
+
+			tmp = tmpnam(NULL);
+			fp = fopen(tmp, "w");
+			if (fp == NULL) {
+				Tcl_SetResult(interp, strerror(errno), TCL_VOLATILE);
+				theResult = TCL_ERROR;
+				break;
+			}
+			theFile = fopen(theFilePath, "r");
+			if (theFile == NULL) {
+				Tcl_SetResult(interp, strerror(errno), TCL_VOLATILE);
+				theResult = TCL_ERROR;
+				break;
+			}
+			if ((p = fgets(buf, BUFSIZ, theFile)) != NULL) {
+				/* skip stray header escaping into output */
+				if (strncmp(p, "Last-Modified:", 14) != 0)
+					rewind(theFile);
+			}
+			while ((size = fread(buf, 1, BUFSIZ, theFile)) > 0) {
+				fwrite(buf, 1, size, fp);
+			}
+			(void) fclose(theFile);
+			theFile = NULL;
+			fclose(fp);
+			if (rename(tmp, theFilePath) != 0) {
+				Tcl_SetResult(interp, strerror(errno), TCL_VOLATILE);
+				theResult = TCL_ERROR;
+				break;
+			}
+		}
+#endif
+
 		if (remotetime) {
 			theCurlCode = curl_easy_getinfo(theHandle, CURLINFO_FILETIME, &theFileTime);
 			if (theCurlCode == CURLE_OK && theFileTime > 0) {
diff --git a/src/pextlib1.0/sha256cmd.c b/src/pextlib1.0/sha256cmd.c
index 5a58a2e57..4a8650b42 100644
--- a/src/pextlib1.0/sha256cmd.c
+++ b/src/pextlib1.0/sha256cmd.c
@@ -48,6 +48,15 @@
 #define COMMON_DIGEST_FOR_OPENSSL
 #include <CommonCrypto/CommonDigest.h>
 
+/* Tiger compatibility */
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH            CC_SHA256_DIGEST_LENGTH
+#define SHA256_CTX                      CC_SHA256_CTX
+#define SHA256_Init(c)                  CC_SHA256_Init(c)
+#define SHA256_Update(c,d,l)            CC_SHA256_Update(c,d,l)
+#define SHA256_Final(m, c)              CC_SHA256_Final(m,c)
+#endif
+
 #include "md_wrappers.h"
 CHECKSUMEnd(SHA256_, SHA256_CTX, SHA256_DIGEST_LENGTH)
 CHECKSUMFile(SHA256_, SHA256_CTX)
diff --git a/src/port/Makefile.in b/src/port/Makefile.in
index 47a9746e4..842d9b872 100644
--- a/src/port/Makefile.in
+++ b/src/port/Makefile.in
@@ -40,8 +40,10 @@ install: all mkdirs
 	$(INSTALL)    -o "${DSTUSR}" -g "${DSTGRP}" -m 555 port portindex portmirror port-tclsh "${DESTDIR}${bindir}/"
 	$(LN_S) -f port "${DESTDIR}${bindir}/portf"
 ifeq (darwin,@OS_PLATFORM@)
+ifneq (8,@OS_MAJOR@)
 	chmod -h 555 "${DESTDIR}${bindir}/portf"
 endif
+endif
 
 codesign:: port-tclsh
 	../codesign.sh $?
diff --git a/src/port1.0/portconfigure.tcl b/src/port1.0/portconfigure.tcl
index 81eb21976..e2d0966e3 100644
--- a/src/port1.0/portconfigure.tcl
+++ b/src/port1.0/portconfigure.tcl
@@ -558,6 +558,11 @@ proc portconfigure::configure_get_sdkroot {sdk_version} {
         return {}
     }
 
+    # Special hack for Tiger/ppc, since the system libraries do not contain intel slices
+    if {${os.arch} eq "powerpc" && $macos_version_major eq "10.4" && [variant_exists universal] && [variant_isset universal]} {
+        return ${developer_dir}/SDKs/MacOSX10.4u.sdk
+    }
+
     # Use the DevSDK (eg: /usr/include) if present and the requested SDK version matches the host version
     if {${os.major} < 19 && $sdk_version eq $macos_version_major && [file exists /usr/include/sys/cdefs.h]} {
         return {}
@@ -1821,7 +1826,7 @@ proc portconfigure::configure_main {args} {
             append_to_environment_value configure "__CFPREFERENCES_AVOID_DAEMON" 1
         }
 
-        # add SDK flags if needed
+        # add SDK flags if cross-compiling (or universal on ppc tiger)
         if {${configure.sdkroot} ne "" && !${compiler.limit_flags}} {
             foreach env_var {CPPFLAGS CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS} {
                 append_to_environment_value configure $env_var -isysroot${configure.sdkroot}
diff --git a/src/port1.0/portstartupitem.tcl b/src/port1.0/portstartupitem.tcl
index 8772c0953..eb361fe9c 100644
--- a/src/port1.0/portstartupitem.tcl
+++ b/src/port1.0/portstartupitem.tcl
@@ -480,7 +480,11 @@ proc portstartupitem::startupitem_create_darwin_launchd {attrs} {
     puts ${plist} "</array>"
 
     puts ${plist} "<key>Disabled</key><true/>"
-    puts ${plist} "<key>KeepAlive</key><true/>"
+    if {$macosx_deployment_target ne "10.4"} {
+        puts ${plist} "<key>KeepAlive</key><true/>"
+    } else {
+        puts ${plist} "<key>OnDemand</key><false/>"
+    }
 
     if {$username ne ""} {
         puts ${plist} "<key>UserName</key><string>$username</string>"
@@ -559,10 +563,14 @@ proc portstartupitem::loaded {} {
             if {![catch {exec -ignorestderr $launchctl_path print ${domain}/${si_uniquename} >&/dev/null}]} {
                 lappend ret $si_name
             }
-        } else {
+        } elseif {${os.major} >= 9} {
             if {![catch {exec_as_uid $uid {system "$launchctl_path list ${si_uniquename} > /dev/null"}}]} {
                 lappend ret $si_name
             }
+        } else {
+            if {![catch {exec_as_uid $uid {system "$launchctl_path list | grep -F ${si_uniquename} > /dev/null"}}]} {
+                lappend ret $si_name
+            }
         }
     }
     return $ret
diff --git a/src/port1.0/portutil.tcl b/src/port1.0/portutil.tcl
index bf11e794f..c7fc2bc8c 100644
--- a/src/port1.0/portutil.tcl
+++ b/src/port1.0/portutil.tcl
@@ -2859,7 +2859,19 @@ proc extract_archive_metadata {archive_location archive_type metadata_types} {
     switch -- $archive_type {
         tbz -
         tbz2 {
-            set raw_contents [exec -ignorestderr [findBinary tar ${portutil::autoconf::tar_path}] -xOj${qflag}f $archive_location ./+CONTENTS]
+            global os.major os.platform
+            if {${os.major} == 8 && ${os.platform} eq "darwin"} {
+                # https://trac.macports.org/ticket/70622
+                set tar_cmd [string cat [findBinary tar ${portutil::autoconf::tar_path}] \
+                     " -xOj${qflag}f [shellescape $archive_location] ./+CONTENTS" \
+                     " 2>/dev/null || true"]
+                set raw_contents [exec -ignorestderr /bin/sh -c $tar_cmd]
+                if {$raw_contents eq ""} {
+                    error "extracting +CONTENTS from $archive_location failed"
+                }
+            } else {
+                set raw_contents [exec -ignorestderr [findBinary tar ${portutil::autoconf::tar_path}] -xOj${qflag}f $archive_location ./+CONTENTS]
+            }
         }
         tgz {
             set raw_contents [exec -ignorestderr [findBinary tar ${portutil::autoconf::tar_path}] -xOz${qflag}f $archive_location ./+CONTENTS]
-- 
2.49.0

