public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/hfsutils] rawhide: Port tclhfs.c and hfswish.c to the Tcl 9 result API
@ 2026-07-31 13:59 Michel Lind
  0 siblings, 0 replies; only message in thread
From: Michel Lind @ 2026-07-31 13:59 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/hfsutils
            Branch : rawhide
            Commit : 8fe66a9c2fb70500d291e871b669d1c097c437d2
            Author : Michel Lind <salimma@fedoraproject.org>
            Date   : 2026-07-20T16:02:34+01:00
            Stats  : +870/-2 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/hfsutils/c/8fe66a9c2fb70500d291e871b669d1c097c437d2?branch=rawhide

            Log:
            Port tclhfs.c and hfswish.c to the Tcl 9 result API

- Fix pointer-type mismatches with the Tcl 9 API and allocator pairing

Assisted-by: Claude Code:claude-fable-5
Signed-off-by: Michel Lind <salimma@fedoraproject.org>

---
diff --git a/hfsutils-3.2.6-tcl9-interp-result.patch b/hfsutils-3.2.6-tcl9-interp-result.patch
new file mode 100644
index 0000000..6451f47
--- /dev/null
+++ b/hfsutils-3.2.6-tcl9-interp-result.patch
@@ -0,0 +1,578 @@
+Port tclhfs.c and hfswish.c to the Tcl 9 result API
+
+Tcl 9.0 (Fedora 43+) made the Tcl_Interp struct fully opaque: the
+"result" field -- deprecated since Tcl 8.6 (TIP 330) and until now
+re-enabled with -DUSE_INTERP_RESULT -- no longer exists, so every
+direct interp->result access is a compile error.
+
+Replace them with the supported API, which exists in both Tcl 8 and 9:
+- static message assignments -> Tcl_SetResult(interp, msg, TCL_STATIC)
+- sprintf(interp->result, ...) -> sprintf into a local buffer +
+  Tcl_SetResult(interp, buf, TCL_VOLATILE) (the old code relied on the
+  interp's built-in result buffer, which is gone)
+- the generated "hfsfileN"/"hfsvolN" command names are now built in a
+  local buffer; an explicit Tcl_SetResult keeps them as the script-level
+  return value of "vol open", "vol create" and "hfs mount"
+- reading the result (Tcl_SplitList in "vol path", the error report in
+  hfswish's Tcl_AppInit) -> Tcl_GetStringResult
+
+--- hfsutils-3.2.6/tclhfs.c	1998-11-02 22:08:32.000000000 +0000
++++ hfsutils-3.2.6/tclhfs.c	2026-07-20 15:32:14.655282871 +0100
+@@ -239,7 +239,7 @@ int getdir(Tcl_Interp *interp, volref *v
+       str = direntstr(&ent);
+       if (str == 0)
+ 	{
+-	  interp->result = "out of memory";
++	  Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -284,7 +284,7 @@ int file_cmd(ClientData clientData, Tcl_
+   switch (argc)
+     {
+     case 1:
+-      interp->result = "missing command";
++      Tcl_SetResult(interp, "missing command", TCL_STATIC);
+       return TCL_ERROR;
+ 
+     case 2:
+@@ -297,12 +297,14 @@ int file_cmd(ClientData clientData, Tcl_
+       else if (strcmp(argv[1], "tell") == 0)
+ 	{
+ 	  long offset;
++	  char buf[CHARLEN(unsigned long) + 1];
+ 
+ 	  offset = hfs_seek(file, 0, HFS_SEEK_CUR);
+ 	  if (offset == -1)
+ 	    return error(interp, 0);
+ 
+-	  sprintf(interp->result, "%lu", offset);
++	  sprintf(buf, "%lu", offset);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	}
+       else if (strcmp(argv[1], "stat") == 0)
+ 	{
+@@ -315,7 +317,7 @@ int file_cmd(ClientData clientData, Tcl_
+ 	  str = direntstr(&ent);
+ 	  if (str == 0)
+ 	    {
+-	      interp->result = "out of memory";
++	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -323,7 +325,7 @@ int file_cmd(ClientData clientData, Tcl_
+ 	}
+       else if (strcmp(argv[1], "getfork") == 0)
+ 	{
+-	  interp->result = (hfs_getfork(file) == 0) ? "data" : "rsrc";
++	  Tcl_SetResult(interp, (hfs_getfork(file) == 0) ? "data" : "rsrc", TCL_STATIC);
+ 	}
+       else
+ 	{
+@@ -346,7 +348,7 @@ int file_cmd(ClientData clientData, Tcl_
+ 	    fork = 1;
+ 	  else
+ 	    {
+-	      interp->result = "bad arg to setfork: must be data or rsrc";
++	      Tcl_SetResult(interp, "bad arg to setfork: must be data or rsrc", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -355,6 +357,7 @@ int file_cmd(ClientData clientData, Tcl_
+       else if (strcmp(argv[1], "seek") == 0)
+ 	{
+ 	  long offset;
++	  char buf[CHARLEN(unsigned long) + 1];
+ 
+ 	  if (Tcl_ExprLong(interp, argv[2], &offset) != TCL_OK)
+ 	    return TCL_ERROR;
+@@ -363,7 +366,8 @@ int file_cmd(ClientData clientData, Tcl_
+ 	  if (offset == -1)
+ 	    return error(interp, 0);
+ 
+-	  sprintf(interp->result, "%lu", offset);
++	  sprintf(buf, "%lu", offset);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	}
+       else if (strcmp(argv[1], "read") == 0)
+ 	{
+@@ -375,14 +379,14 @@ int file_cmd(ClientData clientData, Tcl_
+ 
+ 	  if (bytes < 0)
+ 	    {
+-	      interp->result = "size must be >= 0";
++	      Tcl_SetResult(interp, "size must be >= 0", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+ 	  mem = ALLOC(char, bytes + 1);
+ 	  if (mem == 0)
+ 	    {
+-	      interp->result = "out of memory";
++	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -400,12 +404,14 @@ int file_cmd(ClientData clientData, Tcl_
+       else if (strcmp(argv[1], "write") == 0)
+ 	{
+ 	  long bytes;
++	  char buf[CHARLEN(unsigned long) + 1];
+ 
+ 	  bytes = hfs_write(file, argv[2], strlen(argv[2]));
+ 	  if (bytes == -1)
+ 	    return error(interp, 0);
+ 
+-	  sprintf(interp->result, "%lu", bytes);
++	  sprintf(buf, "%lu", bytes);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	}
+       else
+ 	{
+@@ -420,6 +426,7 @@ int file_cmd(ClientData clientData, Tcl_
+ 	{
+ 	  long offset;
+ 	  int whence;
++	  char buf[CHARLEN(unsigned long) + 1];
+ 
+ 	  if (Tcl_ExprLong(interp, argv[2], &offset) != TCL_OK)
+ 	    return TCL_ERROR;
+@@ -434,7 +441,7 @@ int file_cmd(ClientData clientData, Tcl_
+ 	    whence = HFS_SEEK_END;
+ 	  else
+ 	    {
+-	      interp->result = "bad arg 3: must be start, current, or end";
++	      Tcl_SetResult(interp, "bad arg 3: must be start, current, or end", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -442,7 +449,8 @@ int file_cmd(ClientData clientData, Tcl_
+ 	  if (offset == -1)
+ 	    return error(interp, 0);
+ 
+-	  sprintf(interp->result, "%lu", offset);
++	  sprintf(buf, "%lu", offset);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	}
+       else
+ 	{
+@@ -500,18 +508,21 @@ void file_ref(Tcl_Interp *interp, volref
+   Tcl_CmdInfo info;
+   Tcl_HashEntry *entry;
+   int new;
++  char name[CHARLEN(int) + 8];
+ 
+   do
+-    sprintf(interp->result, "hfsfile%d", id++);
+-  while (Tcl_GetCommandInfo(interp, interp->result, &info));
++    sprintf(name, "hfsfile%d", id++);
++  while (Tcl_GetCommandInfo(interp, name, &info));
+ 
+   fref->file   = file;
+   fref->interp = interp;
+-  fref->cmd    = Tcl_CreateCommand(interp, interp->result,
++  fref->cmd    = Tcl_CreateCommand(interp, name,
+ 				   file_cmd, fref, file_del);
+ 
+   entry = Tcl_CreateHashEntry(&files, (char *) fref, &new);
+   Tcl_SetHashValue(entry, vref);
++
++  Tcl_SetResult(interp, name, TCL_VOLATILE);
+ }
+ 
+ /*
+@@ -618,7 +629,7 @@ int copynative(Tcl_Interp *interp, volre
+   if (srcvref->vol == dstvref->vol &&
+       ent.cnid == cnid)
+     {
+-      interp->result = "source and destination files are the same";
++      Tcl_SetResult(interp, "source and destination files are the same", TCL_STATIC);
+       hfs_close(ifile);
+       return TCL_ERROR;
+     }
+@@ -672,7 +683,7 @@ int copyin(Tcl_Interp *interp, hfsvol *v
+     copyfile = cpi_raw;
+   else
+     {
+-      interp->result = "bad mode: must be macb, binh, text, or raw";
++      Tcl_SetResult(interp, "bad mode: must be macb, binh, text, or raw", TCL_STATIC);
+       return TCL_ERROR;
+     }
+ 
+@@ -707,7 +718,7 @@ int copyout(Tcl_Interp *interp, hfsvol *
+     copyfile = cpo_raw;
+   else
+     {
+-      interp->result = "bad mode: must be macb, binh, text, or raw";
++      Tcl_SetResult(interp, "bad mode: must be macb, binh, text, or raw", TCL_STATIC);
+       return TCL_ERROR;
+     }
+ 
+@@ -821,7 +832,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+   switch (argc)
+     {
+     case 1:
+-      interp->result = "missing command";
++      Tcl_SetResult(interp, "missing command", TCL_STATIC);
+       return TCL_ERROR;
+ 
+     case 2:
+@@ -835,23 +846,29 @@ int vol_cmd(ClientData clientData, Tcl_I
+       else if (strcmp(argv[1], "size") == 0)
+ 	{
+ 	  hfsvolent ent;
++	  char buf[2 * CHARLEN(unsigned long) + 2];
+ 
+ 	  hfs_vstat(vol, &ent);
+-	  sprintf(interp->result, "%lu %lu", ent.totbytes, ent.freebytes);
++	  sprintf(buf, "%lu %lu", ent.totbytes, ent.freebytes);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	}
+       else if (strcmp(argv[1], "crdate") == 0)
+ 	{
+ 	  hfsvolent ent;
++	  char buf[CHARLEN(long) + 1];
+ 
+ 	  hfs_vstat(vol, &ent);
+-	  sprintf(interp->result, "%ld", (long) ent.crdate);
++	  sprintf(buf, "%ld", (long) ent.crdate);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	}
+       else if (strcmp(argv[1], "mddate") == 0)
+ 	{
+ 	  hfsvolent ent;
++	  char buf[CHARLEN(long) + 1];
+ 
+ 	  hfs_vstat(vol, &ent);
+-	  sprintf(interp->result, "%ld", (long) ent.mddate);
++	  sprintf(buf, "%ld", (long) ent.mddate);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	}
+       else if (strcmp(argv[1], "islocked") == 0)
+ 	{
+@@ -859,9 +876,9 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 
+ 	  hfs_vstat(vol, &ent);
+ 	  if (ent.flags & HFS_ISLOCKED)
+-	    interp->result = "1";
++	    Tcl_SetResult(interp, "1", TCL_STATIC);
+ 	  else
+-	    interp->result = "0";
++	    Tcl_SetResult(interp, "0", TCL_STATIC);
+ 	}
+       else if (strcmp(argv[1], "umount") == 0)
+ 	{
+@@ -870,7 +887,12 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	    return error(interp, 0);
+ 	}
+       else if (strcmp(argv[1], "cwd") == 0)
+-	sprintf(interp->result, "%lu", vref->cwd);
++	{
++	  char buf[CHARLEN(unsigned long) + 1];
++
++	  sprintf(buf, "%lu", vref->cwd);
++	  Tcl_SetResult(interp, buf, TCL_VOLATILE);
++	}
+       else if (strcmp(argv[1], "path") == 0)
+ 	{
+ 	  char name[HFS_MAX_FLEN + 1];
+@@ -890,7 +912,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 
+ 	  /* reverse the resulting list */
+ 
+-	  if (Tcl_SplitList(interp, interp->result, &listc, &listv) != TCL_OK)
++	  if (Tcl_SplitList(interp, Tcl_GetStringResult(interp), &listc, &listv) != TCL_OK)
+ 	    return TCL_ERROR;
+ 
+ 	  for (i = 0; i < listc / 2; ++i)
+@@ -918,7 +940,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	    return error(interp, 0);
+ 	}
+       else if (strcmp(argv[1], "sepchar") == 0)
+-	interp->result = ":";
++	Tcl_SetResult(interp, ":", TCL_STATIC);
+       else
+ 	{
+ 	  Tcl_AppendResult(interp, "bad command \"", argv[1],
+@@ -965,7 +987,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	  fref = ALLOC(fileref, 1);
+ 	  if (fref == 0)
+ 	    {
+-	      interp->result = "out of memory";
++	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -990,7 +1012,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	  str = direntstr(&ent);
+ 	  if (str == 0)
+ 	    {
+-	      interp->result = "out of memory";
++	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -1043,7 +1065,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 
+ 	  if (fargv == 0)
+ 	    {
+-	      interp->result = "globbing error";
++	      Tcl_SetResult(interp, "globbing error", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -1099,14 +1121,14 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	  if (strlen(argv[3]) != 4 ||
+ 	      strlen(argv[4]) != 4)
+ 	    {
+-	      interp->result = "type and creator must be 4 character strings";
++	      Tcl_SetResult(interp, "type and creator must be 4 character strings", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+ 	  fref = ALLOC(fileref, 1);
+ 	  if (fref == 0)
+ 	    {
+-	      interp->result = "out of memory";
++	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -1164,7 +1186,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 
+   if (argc < 2)
+     {
+-      interp->result = "wrong # args";
++      Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+       return TCL_ERROR;
+     }
+ 
+@@ -1176,10 +1198,11 @@ int cmd_hfs(ClientData clientData, Tcl_I
+       Tcl_CmdInfo info;
+       Tcl_HashEntry *entry;
+       int new;
++      char name[CHARLEN(int) + 8];
+ 
+       if (argc < 3 || argc > 4)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1191,6 +1214,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+       else
+ 	{
+ 	  int nparts;
++	  char buf[64];
+ 
+ 	  suid_enable();
+ 	  nparts = hfs_nparts(argv[2]);
+@@ -1198,8 +1222,9 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 
+ 	  if (nparts > 1)
+ 	    {
+-	      sprintf(interp->result, "must specify partition number "
++	      sprintf(buf, "must specify partition number "
+ 		      "(%d available)", nparts);
++	      Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 	      return TCL_ERROR;
+ 	    }
+ 	  else if (nparts == -1)
+@@ -1211,7 +1236,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+       vref = ALLOC(volref, 1);
+       if (vref == 0)
+ 	{
+-	  interp->result = "out of memory";
++	  Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1232,20 +1257,23 @@ int cmd_hfs(ClientData clientData, Tcl_I
+       entry = Tcl_CreateHashEntry(&volumes, (char *) vref, &new);
+ 
+       do
+-	sprintf(interp->result, "hfsvol%d", id++);
+-      while (Tcl_GetCommandInfo(interp, interp->result, &info));
++	sprintf(name, "hfsvol%d", id++);
++      while (Tcl_GetCommandInfo(interp, name, &info));
+ 
+-      Tcl_CreateCommand(interp, interp->result,
++      Tcl_CreateCommand(interp, name,
+ 			vol_cmd, vref, vol_del);
++
++      Tcl_SetResult(interp, name, TCL_VOLATILE);
+     }
+   else if (strcmp(argv[1], "zero") == 0)
+     {
+       int nparts;
+       unsigned long len;
++      char buf[CHARLEN(unsigned long) + 1];
+ 
+       if (argc != 4)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1255,7 +1283,8 @@ int cmd_hfs(ClientData clientData, Tcl_I
+       if (do_zero(argv[2], nparts, &len) == -1)
+ 	return error(interp, 0);
+ 
+-      sprintf(interp->result, "%lu", len);
++      sprintf(buf, "%lu", len);
++      Tcl_SetResult(interp, buf, TCL_VOLATILE);
+     }
+   else if (strcmp(argv[1], "mkpart") == 0)
+     {
+@@ -1263,7 +1292,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 
+       if (argc != 4)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1276,10 +1305,11 @@ int cmd_hfs(ClientData clientData, Tcl_I
+   else if (strcmp(argv[1], "nparts") == 0)
+     {
+       int nparts;
++      char buf[CHARLEN(int) + 1];
+ 
+       if (argc != 3)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1287,7 +1317,8 @@ int cmd_hfs(ClientData clientData, Tcl_I
+       nparts = hfs_nparts(argv[2]);
+       suid_disable();
+ 
+-      sprintf(interp->result, "%d", nparts);
++      sprintf(buf, "%d", nparts);
++      Tcl_SetResult(interp, buf, TCL_VOLATILE);
+     }
+   else if (strcmp(argv[1], "format") == 0)
+     {
+@@ -1295,7 +1326,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 
+       if (argc < 5 || argc > 6)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1316,7 +1347,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 	    {
+ 	      free(listv);
+ 
+-	      interp->result = "out of memory";
++	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	      return TCL_ERROR;
+ 	    }
+ 
+@@ -1356,7 +1387,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 
+       if (argc != 5)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1365,8 +1396,8 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 	  (strcmp(argv[3], "latin1") != 0 &&
+ 	   strcmp(argv[3], "macroman") != 0))
+ 	{
+-	  interp->result = "bad arg to chartrans: "
+-	    "charsets must be one of latin1, macroman";
++	  Tcl_SetResult(interp, "bad arg to chartrans: "
++	    "charsets must be one of latin1, macroman", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1384,7 +1415,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 
+       if (result == 0)
+ 	{
+-	  interp->result = "out of memory";
++	  Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+@@ -1394,41 +1425,41 @@ int cmd_hfs(ClientData clientData, Tcl_I
+     {
+       if (argc != 2)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+-      interp->result = (char *) hfsutils_version;
++      Tcl_SetResult(interp, (char *) hfsutils_version, TCL_STATIC);
+     }
+   else if (strcmp(argv[1], "copyright") == 0)
+     {
+       if (argc != 2)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+-      interp->result = (char *) hfsutils_copyright;
++      Tcl_SetResult(interp, (char *) hfsutils_copyright, TCL_STATIC);
+     }
+   else if (strcmp(argv[1], "author") == 0)
+     {
+       if (argc != 2)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+-      interp->result = (char *) hfsutils_author;
++      Tcl_SetResult(interp, (char *) hfsutils_author, TCL_STATIC);
+     }
+   else if (strcmp(argv[1], "license") == 0)
+     {
+       if (argc != 2)
+ 	{
+-	  interp->result = "wrong # args";
++	  Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
+ 	  return TCL_ERROR;
+ 	}
+ 
+-      interp->result = (char *) hfsutils_license;
++      Tcl_SetResult(interp, (char *) hfsutils_license, TCL_STATIC);
+     }
+   else
+     {
+@@ -1455,7 +1486,7 @@ int cmd_exit(ClientData clientData, Tcl_
+ 
+   if (argc > 2)
+     {
+-      interp->result = "wrong # args: should be \"exit ?returnCode?\"";
++      Tcl_SetResult(interp, "wrong # args: should be \"exit ?returnCode?\"", TCL_STATIC);
+       return TCL_ERROR;
+     }
+ 
+--- hfsutils-3.2.6/hfswish.c	1998-04-11 09:26:57.000000000 +0100
++++ hfsutils-3.2.6/hfswish.c	2026-07-20 15:44:40.281374410 +0100
+@@ -94,7 +94,7 @@ int Tcl_AppInit(Tcl_Interp *interp)
+ 
+   if (Tcl_Eval(interp, xhfs) == TCL_ERROR)
+     {
+-      fprintf(stderr, "Error: %s\n", interp->result);
++      fprintf(stderr, "Error: %s\n", Tcl_GetStringResult(interp));
+       exit(1);
+     }
+ 

diff --git a/hfsutils-3.2.6-tcl9-pointer-types.patch b/hfsutils-3.2.6-tcl9-pointer-types.patch
new file mode 100644
index 0000000..5f3c150
--- /dev/null
+++ b/hfsutils-3.2.6-tcl9-pointer-types.patch
@@ -0,0 +1,280 @@
+Fix pointer-type mismatches with the Tcl 9 API and allocator pairing
+
+This completes the Tcl 9 port so the package no longer needs
+-Wno-incompatible-pointer-types:
+
+- Tcl 9's Tcl_CmdProc takes (int argc, const char *argv[]); adjust the
+  command procedures and the helpers they hand argv to.  cs_latin1()/
+  cs_macroman() only read their input, so their argument is constified
+  rather than casting away const at the call sites.
+- Tcl_SplitList() now fills in a Tcl_Size (64-bit) element count and a
+  const char ** vector.  Passing the old int * misreads/clobbers stack
+  memory on 64-bit architectures, so this was a latent runtime bug, not
+  just a warning.
+- Tcl_Merge() takes const char *const *; constify direntstr()'s argv
+  and cast hfs_glob()'s result vector.
+- Pair allocators correctly for Tcl 9, where Tcl_Free() is no longer
+  interchangeable with free(): memory obtained from Tcl (Tcl_SplitList
+  vectors, Tcl_Merge strings) is released with Tcl_Free(); the "read"
+  command result is allocated with Tcl_AttemptAlloc() to match its
+  TCL_DYNAMIC free; the malloc()ed chartrans result is copied with
+  TCL_VOLATILE and freed with free().
+- Tcl_GetInt() in "hfs mkpart" needs an int, not an unsigned int.
+
+--- hfsutils-3.2.6/tclhfs.c	2026-07-20 15:51:51.339443468 +0100
++++ hfsutils-3.2.6/tclhfs.c	2026-07-20 15:58:13.697974421 +0100
+@@ -120,7 +120,7 @@ char *direntstr(hfsdirent *ent)
+     mddate[CHARLEN(long) + 1],
+     bkdate[CHARLEN(long) + 1];
+   register int argc;
+-  char *argv[24];
++  const char *argv[24];
+   int locked, invis;
+ 
+   argc = 0;
+@@ -228,7 +228,7 @@ int getdir(Tcl_Interp *interp, volref *v
+ 
+ 	  Tcl_AppendElement(interp, str);
+ 
+-	  free(str);
++	  Tcl_Free(str);
+ 	}
+ 
+       if (hfs_closedir(dir) == -1)
+@@ -245,7 +245,7 @@ int getdir(Tcl_Interp *interp, volref *v
+ 
+       Tcl_AppendElement(interp, str);
+ 
+-      free(str);
++      Tcl_Free(str);
+     }
+ 
+   return TCL_OK;
+@@ -276,7 +276,7 @@ void file_del(ClientData clientData)
+  */
+ static
+ int file_cmd(ClientData clientData, Tcl_Interp *interp,
+-	     int argc, char *argv[])
++	     int argc, const char *argv[])
+ {
+   fileref *fref = clientData;
+   hfsfile *file = fref->file;
+@@ -383,7 +383,7 @@ int file_cmd(ClientData clientData, Tcl_
+ 	      return TCL_ERROR;
+ 	    }
+ 
+-	  mem = ALLOC(char, bytes + 1);
++	  mem = Tcl_AttemptAlloc(bytes + 1);
+ 	  if (mem == 0)
+ 	    {
+ 	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+@@ -393,7 +393,7 @@ int file_cmd(ClientData clientData, Tcl_
+ 	  bytes = hfs_read(file, mem, bytes);
+ 	  if (bytes == -1)
+ 	    {
+-	      free(mem);
++	      Tcl_Free(mem);
+ 	      return error(interp, 0);
+ 	    }
+ 
+@@ -558,7 +558,7 @@ int do_copynative(Tcl_Interp *interp, hf
+  * DESCRIPTION:	copy an HFS file to another HFS volume
+  */
+ static
+-int copynative(Tcl_Interp *interp, volref *srcvref, char *argv[])
++int copynative(Tcl_Interp *interp, volref *srcvref, const char *argv[])
+ {
+   volref *dstvref;
+   Tcl_CmdInfo info;
+@@ -666,7 +666,7 @@ int copynative(Tcl_Interp *interp, volre
+  * DESCRIPTION:	copy a UNIX file into an HFS volume
+  */
+ static
+-int copyin(Tcl_Interp *interp, hfsvol *vol, char *argv[])
++int copyin(Tcl_Interp *interp, hfsvol *vol, const char *argv[])
+ {
+   cpifunc copyfile;
+ 
+@@ -701,7 +701,7 @@ int copyin(Tcl_Interp *interp, hfsvol *v
+  * DESCRIPTION:	copy an HFS file out to a UNIX file
+  */
+ static
+-int copyout(Tcl_Interp *interp, hfsvol *vol, char *argv[])
++int copyout(Tcl_Interp *interp, hfsvol *vol, const char *argv[])
+ {
+   cpofunc copyfile;
+ 
+@@ -824,7 +824,7 @@ void vol_del(ClientData clientData)
+  */
+ static
+ int vol_cmd(ClientData clientData, Tcl_Interp *interp,
+-	    int argc, char *argv[])
++	    int argc, const char *argv[])
+ {
+   volref *vref = clientData;
+   hfsvol *vol  = vref->vol;
+@@ -897,8 +897,8 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	{
+ 	  char name[HFS_MAX_FLEN + 1];
+ 	  long id;
+-	  int listc, i;
+-	  char **listv;
++	  Tcl_Size listc, i;
++	  const char **listv;
+ 	  char *result;
+ 
+ 	  id = vref->cwd;
+@@ -917,7 +917,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 
+ 	  for (i = 0; i < listc / 2; ++i)
+ 	    {
+-	      char *tmp;
++	      const char *tmp;
+ 
+ 	      tmp = listv[i];
+ 	      listv[i] = listv[listc - 1 - i];
+@@ -925,7 +925,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	    }
+ 
+ 	  result = Tcl_Merge(listc, listv);
+-	  free(listv);
++	  Tcl_Free((void *) listv);
+ 
+ 	  Tcl_SetResult(interp, result, TCL_DYNAMIC);
+ 	}
+@@ -1051,8 +1051,10 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	}
+       else if (strcmp(argv[1], "glob") == 0)
+ 	{
+-	  int listc, fargc;
+-	  char **listv, **fargv, *result;
++	  Tcl_Size listc;
++	  int fargc;
++	  const char **listv;
++	  char **fargv, *result;
+ 
+ 	  if (hfs_setcwd(vol, vref->cwd) == -1)
+ 	    return error(interp, 0);
+@@ -1060,8 +1062,8 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	  if (Tcl_SplitList(interp, argv[2], &listc, &listv) != TCL_OK)
+ 	    return TCL_ERROR;
+ 
+-	  fargv = hfs_glob(vol, listc, listv, &fargc);
+-	  free(listv);
++	  fargv = hfs_glob(vol, listc, (char **) listv, &fargc);
++	  Tcl_Free((void *) listv);
+ 
+ 	  if (fargv == 0)
+ 	    {
+@@ -1069,7 +1071,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+ 	      return TCL_ERROR;
+ 	    }
+ 
+-	  result = Tcl_Merge(fargc, fargv);
++	  result = Tcl_Merge(fargc, (const char **) fargv);
+ 	  free(fargv);
+ 
+ 	  Tcl_SetResult(interp, result, TCL_DYNAMIC);
+@@ -1180,7 +1182,7 @@ int vol_cmd(ClientData clientData, Tcl_I
+  */
+ static
+ int cmd_hfs(ClientData clientData, Tcl_Interp *interp,
+-	    int argc, char *argv[])
++	    int argc, const char *argv[])
+ {
+   static int id = 0;
+ 
+@@ -1288,7 +1290,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+     }
+   else if (strcmp(argv[1], "mkpart") == 0)
+     {
+-      unsigned int len;
++      int len;
+ 
+       if (argc != 4)
+ 	{
+@@ -1335,8 +1337,8 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 
+       if (argc == 6)
+ 	{
+-	  int listc, i;
+-	  char **listv;
++	  Tcl_Size listc, i;
++	  const char **listv;
+ 	  unsigned long *badblocks;
+ 
+ 	  if (Tcl_SplitList(interp, argv[5], &listc, &listv) != TCL_OK)
+@@ -1345,7 +1347,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 	  badblocks = ALLOCX(unsigned long, listc);
+ 	  if (listc && badblocks == 0)
+ 	    {
+-	      free(listv);
++	      Tcl_Free((void *) listv);
+ 
+ 	      Tcl_SetResult(interp, "out of memory", TCL_STATIC);
+ 	      return TCL_ERROR;
+@@ -1356,13 +1358,13 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 	      if (Tcl_ExprLong(interp, listv[i],
+ 			       (long *) &badblocks[i]) != TCL_OK)
+ 		{
+-		  free(listv);
++		  Tcl_Free((void *) listv);
+ 		  FREE(badblocks);
+ 		  return TCL_ERROR;
+ 		}
+ 	    }
+ 
+-	  free(listv);
++	  Tcl_Free((void *) listv);
+ 
+ 	  if (do_format(argv[2], partno, 0, argv[4], listc, badblocks) == -1)
+ 	    {
+@@ -1419,7 +1421,8 @@ int cmd_hfs(ClientData clientData, Tcl_I
+ 	  return TCL_ERROR;
+ 	}
+ 
+-      Tcl_SetResult(interp, result, TCL_DYNAMIC);
++      Tcl_SetResult(interp, result, TCL_VOLATILE);
++      free(result);
+     }
+   else if (strcmp(argv[1], "version") == 0)
+     {
+@@ -1480,7 +1483,7 @@ int cmd_hfs(ClientData clientData, Tcl_I
+  */
+ static
+ int cmd_exit(ClientData clientData, Tcl_Interp *interp,
+-	     int argc, char *argv[])
++	     int argc, const char *argv[])
+ {
+   int status = 0;
+ 
+--- hfsutils-3.2.6/charset.h	1998-04-11 09:26:53.000000000 +0100
++++ hfsutils-3.2.6/charset.h	2026-07-20 15:58:13.697974421 +0100
+@@ -23,5 +23,5 @@ typedef unsigned short UCS2;
+ 
+ UCS2 *cs_unicode(char *, int *);
+ 
+-char *cs_latin1(char *, int *);
+-char *cs_macroman(char *, int *);
++char *cs_latin1(const char *, int *);
++char *cs_macroman(const char *, int *);
+--- hfsutils-3.2.6/charset.c	1998-11-02 22:08:23.000000000 +0000
++++ hfsutils-3.2.6/charset.c	2026-07-20 15:58:13.697974421 +0100
+@@ -151,7 +151,7 @@ UCS2 *cs_unicode(char *mstr, int *lenptr
+  * NAME:	charset->latin1()
+  * DESCRIPTION:	return a Latin-1 (ISO 8859-1) string for MacOS Standard Roman
+  */
+-char *cs_latin1(char *mstr, int *lenptr)
++char *cs_latin1(const char *mstr, int *lenptr)
+ {
+   int ilen, olen, i;
+   char *latin1, *ptr;
+@@ -229,7 +229,7 @@ void mktable(void)
+  * NAME:	charset->macroman()
+  * DESCRIPTION:	return a MacOS Standard Roman string for Latin-1 (ISO 8859-1)
+  */
+-char *cs_macroman(char *lstr, int *lenptr)
++char *cs_macroman(const char *lstr, int *lenptr)
+ {
+   int ilen, olen, i;
+   char *macroman, *ptr;

diff --git a/hfsutils.spec b/hfsutils.spec
index d842303..4f7cbbe 100644
--- a/hfsutils.spec
+++ b/hfsutils.spec
@@ -1,7 +1,7 @@
 Summary: Tools for reading and writing Macintosh HFS volumes
 Name: hfsutils
 Version: 3.2.6
-Release: 56%{?dist}
+Release: 57%{?dist}
 # Automatically converted from old format: GPLv2+ - review is highly recommended.
 License: GPL-2.0-or-later
 Source: ftp://ftp.mars.org/pub/hfs/%{name}-%{version}.tar.gz
@@ -9,6 +9,12 @@ Patch0: hfsutils-3.2.6-errno.patch
 Patch1: hfsutils-3.2.6-largefile.patch
 Patch2: hfsutils-3.2.6-configure-c99.patch
 Patch3: hfsutils-3.2.6-include-c99.patch
+# Tcl 9 made Tcl_Interp opaque; use Tcl_SetResult()/Tcl_GetStringResult()
+# instead of poking interp->result directly
+Patch4: hfsutils-3.2.6-tcl9-interp-result.patch
+# Tcl 9 type fixes (Tcl_Size, const argv) and Tcl_Free/free pairing, so we
+# can drop -Wno-incompatible-pointer-types
+Patch5: hfsutils-3.2.6-tcl9-pointer-types.patch
 URL: http://www.mars.org/home/rob/proj/hfs/
 BuildRequires: libXft-devel tcl-devel tk-devel gcc
 BuildRequires: make
@@ -44,7 +50,7 @@ hfsutils-devel package.
 %autosetup -p1
 
 %build
-CFLAGS="%{optflags} -D_FILE_OFFSET_BITS=64 -DUSE_INTERP_RESULT -Wno-incompatible-pointer-types -Wno-deprecated-declarations -Wno-deprecated-declarations -Wno-pointer-sign -Wno-unused-but-set-variable -Wno-int-to-pointer-cast"
+CFLAGS="%{optflags} -D_FILE_OFFSET_BITS=64 -Wno-deprecated-declarations -Wno-pointer-sign -Wno-unused-but-set-variable -Wno-int-to-pointer-cast"
 %{configure} --with-tcl=%{_libdir}  --with-tk=%{_libdir}
 make
 make hfsck/hfsck
@@ -111,6 +117,10 @@ install -p -m 0755 hfsck/hfsck $RPM_BUILD_ROOT/%{_bindir}
 %{_includedir}/rsrc.h
 
 %changelog
+* Mon Jul 20 2026 Michel Lind <salimma@fedoraproject.org> - 3.2.6-57
+- Port tclhfs.c and hfswish.c to the Tcl 9 result API
+- Fix pointer-type mismatches with the Tcl 9 API and allocator pairing
+
 * Thu Jul 16 2026 Fedora Release Engineering <releng@fedoraproject.org> - 3.2.6-56
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
 

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-07-31 13:59 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-31 13:59 [rpms/hfsutils] rawhide: Port tclhfs.c and hfswish.c to the Tcl 9 result API Michel Lind

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox