sit - Create StuffIt archives on Unix systems

thecloud

New Tinkerer
Oct 2, 2025
24
19
3
Starting a new thread for the modernization of the `sit` command-line tool, which creates StuffIt 1.5.1-compatible archives on Unix systems (including macOS!)

sit-usage.jpg


You can find the project at https://github.com/thecloudexpanse/sit.

Initially, I removed the ability to do compression of files as it was causing headaches while getting directory entries to work properly. (Also, links can't be created to a named fork as it's not a real path.) The roadmap ahead includes looking at how to restore compression, and whether to use the old method (piping the file stream through the `compress` command), or just include compression code directly in `sit`. I also want to look at incorporating the functionality of `unsit`, a companion program from the same era. It doesn't need to be a separate tool since `sit` could just take a `-x` option to extract archives.

Modern compilers have a lot of complaints about code that was originally written in 1988, when there was only K&R 'C' syntax. The code has now been updated to the C89 (ANSI C) standard. Eric has sent a PR for AppleDouble support, which will be merged soon.
 

JDW

Administrator
Staff member
Founder
Sep 2, 2021
2,403
1,916
113
54
Japan
youtube.com
Very interesting.

What would be really nice is if Smith Micro would release modern Stuffit Deluxe source code, especially since they no longer sell the product. Makes zero sense to just keep the stuffit site up without offering the source code too.

I purchased the very last version of Stuffit Deluxe (16.0.5) many years ago, which works on modern Macs. Since it's abandonware, I placed it on Macintosh Garden here:


What really impresses me about it though is that it still works on even Apple Silicon Macs, and I'm currently using it in my menubar right now on my 16" M1 Max MacBook Pro running macOS Sequoia.

Years ago, I grew sick of the low-res C-clamp menubar icon, so I created a Retina display version. I added info about that on the Macintosh Garden page so anyone can use it.

What I love about using Stuffit Deluxe 16 is the convenience. I can just click any file in the Finder on my modern Mac, then access legacy SIT compression via the "Magic Menu" as shown below...

1763425771461.png


The only downside I dislike is the SIT files are version 5.x, not the older version 1.5.1 that some very old Macs require. Not every 68K Mac can run Stuffit Expander 5.x. So your Github solution that creates v1.5.1 archives is a very nice touch.
 

thecloud

New Tinkerer
Oct 2, 2025
24
19
3
I'll get around to adding full native macOS FinderInfo metadata support.
Can you explain what that would mean? The contents of the com.apple.FinderInfo extended attribute seem to be the same 32 bytes found in com.apple.ResourceFork at offset $52, and are already being read from the resource fork data.

The StuffIt 1.5.1 archive format, as documented by Raymond Lau, only stores the following metadata about each file:
- filename (63 chars max)
- file type (4 chars)
- file creator (4 chars)
- Finder flags (16 bits)
- creation date
- modification date

Anything else isn't saved in the archive, and wouldn't be understood by StuffIt 1.5.1 or StuffIt Expander.
 

joevt

Tinkerer
Mar 5, 2023
202
76
28
Can you explain what that would mean? The contents of the com.apple.FinderInfo extended attribute seem to be the same 32 bytes found in com.apple.ResourceFork at offset $52, and are already being read from the resource fork data.

FinderInfo and ResourceFork are two separate file system objects so they can have different data.
Code:
xattr -lpx com.apple.FinderInfo "/Volumes/Classic/System Folder/Mac OS ROM" | sed -ne '1,/^0*10 /p'
com.apple.FinderInfo:
00000000  74 62 78 69 63 68 72 70 31 00 00 C8 01 73 00 00  |tbxichrp1.......|
00000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|

xattr -lpx com.apple.ResourceFork "/Volumes/Classic/System Folder/Mac OS ROM" | sed -ne '1,/^0*F0 /p'
com.apple.ResourceFork:
00000000  00 00 01 00 00 09 57 12 00 09 56 12 00 00 11 5A  |................|
00000010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000070  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000080  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
00000090  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000000A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000000B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000000C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000000D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000000E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000000F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
 

NJRoadfan

New Tinkerer
Feb 6, 2022
68
20
8
Not every file has a resource fork (this is certainly the case for Apple II files stored on Macintosh volumes) and the resource fork doesn't store the Finder Flags (labels, etc.).
 

thecloud

New Tinkerer
Oct 2, 2025
24
19
3
Thanks, hopefully I get it now. You're saying that some of the basic metadata (like tbxi/chrp type and creator in your example) is externally stored if the file doesn't have a resource fork. I thought you were talking about other extended metadata (like label names and window location) which would not be useful to read because there is nowhere in the file's archive format to store it.
 
Last edited:

thecloud

New Tinkerer
Oct 2, 2025
24
19
3
Just finished reimplementing compression. Since it's not guaranteed that a system will have the compress command available (and StuffIt uses modified parameters that make it incompatible anyway), I ended up pulling the zopen.c file from FreeBSD into the project. (Back in the day, the patent on LZW compression hadn't yet expired and so it made sense to ask an external command to accomplish this.) The new code has been pushed to the compression branch.
 
Last edited:

joevt

Tinkerer
Mar 5, 2023
202
76
28
Thanks, hopefully I get it now. You're saying that some of the basic metadata (like tbxi/chrp type and creator in your example) is externally stored if the file doesn't have a resource fork. I thought you were talking about other extended metadata (like label names and window location) which would not be useful to read because there is nowhere in the file's archive format to store it.
The file in my example has a resource fork without the type/creator that is in the FinderInfo.

I think a correct implementation would not attempt to do any parsing of the resource fork.

Metadata is ALWAYS externally stored regardless of whether a resource fork exists or not.

It appears that xattr -lx (in Monterey at least) has a bug with showing text of lines after a non-printable ASCII character. This is an improvement:
Code:
xattr -px com.apple.FinderInfo "/Volumes/Classic/System Folder/Mac OS ROM" | xxd -p -r | xxd | sed -ne '1,/^0*f0:/p'
00000000: 7462 7869 6368 7270 3100 00c8 0173 0000  tbxichrp1....s..
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................

xattr -px com.apple.ResourceFork "/Volumes/Classic/System Folder/Mac OS ROM" | xxd -p -r | xxd | sed -ne '1,/^0*f0:/p'
00000000: 0000 0100 0009 5712 0009 5612 0000 115a  ......W...V....Z
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000b0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................


This is an example of a file that has type/creator in the resource fork:
Code:
xattr -px com.apple.FinderInfo "/Volumes/Apps/Communication/ZTerm/ZTerm 0.9" | xxd -p -r | xxd
00000000: 4150 504c 7a54 524d 2106 ffff ffff 0000  APPLzTRM!.......
00000010: 0000 0000 0000 0000 0070 0000 0000 0000  .........p......

xattr -px com.apple.ResourceFork "/Volumes/Apps/Communication/ZTerm/ZTerm 0.9" | xxd -p -r | xxd | sed -ne '1,/^0*f0:/p'
00000000: 0000 0100 0003 045e 0003 035e 0000 0f2e  .......^...^....
00000010: 0000 0f25 0756 5431 3030 2e63 0200 0000  ...%.VT100.c....
00000020: 5445 5854 4b41 484c 0100 0000 0140 0000  TEXTKAHL.....@..
00000030: 095a 5465 726d 2030 2e39 0200 0000 4150  .ZTerm 0.9....AP
00000040: 504c 7a54 524d 2106 ffff ffff 0000 0000  PLzTRM!.........
00000050: 0000 4150 504c 7a54 524d 2106 ffff ffff  ..APPLzTRM!.....
00000060: 0000 0000 0000 0000 0000 0070 0000 0000  ...........p....
00000070: 0000 a5b9 ed3d 0000 0000 0003 138c 0000  .....=..........
00000080: 0000 1600 0000 0f25 1076 7431 3030 2e6f  .......%.vt100.o
00000090: 6c64 2e70 726f 746f 7331 0200 0000 5445  ld.protos1....TE
000000a0: 5854 4b41 484c 0100 ffcc 0000 0000 0000  XTKAHL..........
000000b0: 0f47 0000 0000 0c6b 0000 1200 0000 0000  .G.....k........
000000c0: 0000 0000 0000 a465 83b7 a465 8aae 0000  .......e...e....
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000e0: 0000 0000 119f 0003 0000 0000 0000 0000  ................
000000f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
 

NJRoadfan

New Tinkerer
Feb 6, 2022
68
20
8
The "Finder Flags" are the 4 bytes after the 8 bytes of File Type/Creator. Its stores things like the color/label, "has custom icon", "is on desktop", "is alias", "invisible", etc.
 

thecloud

New Tinkerer
Oct 2, 2025
24
19
3
The "Finder Flags" are the 4 bytes after the 8 bytes of File Type/Creator. Its stores things like the color/label, "has custom icon", "is on desktop", "is alias", "invisible", etc.
And as I mentioned, only the first two bytes of those flags (the $2106 in the above example) can be stored in a StuffIt 1.5.1 archive. The rest aren't in the specification.
 

thecloud

New Tinkerer
Oct 2, 2025
24
19
3
I think a correct implementation would not attempt to do any parsing of the resource fork.

Metadata is ALWAYS externally stored regardless of whether a resource fork exists or not.
Ah. If a com.apple.ResourceFork can never exist without a corresponding com.apple.FinderInfo, then I agree the latter should be the preferred source.
 

NJRoadfan

New Tinkerer
Feb 6, 2022
68
20
8
As mentioned before, this is common with Apple II files stored on HFS volumes as they usually don't have resource forks (only GS/OS supported them), but still needed to store ProDOS filetype/auxtype information. Also many cross platform document formats are data fork only, so rely on FinderInfo to store filetype/creator. Its also possible to encounter AppleDouble ._ files with zero byte resource forks too.
 
  • Like
Reactions: thecloud

joevt

Tinkerer
Mar 5, 2023
202
76
28
Ah. If a com.apple.ResourceFork can never exist without a corresponding com.apple.FinderInfo, then I agree the latter should be the preferred source.
The xattr command can't delete FinderInfo because in Mac OS X, on an HFS or HFS+ or APFS partition, FinderInfo is not an extended attribute or it contains info that cannot be removed - it can only be changed (using SetFile or xattr or other command).

Code:
dumpxattr () {
	local thefile="$1"
	printf "FinderInfo\n"
	xattr -px com.apple.FinderInfo "$thefile" | xxd -p -r | xxd
	printf "ResourceFork\n"
	xattr -px com.apple.ResourceFork "$thefile" | xxd -p -r | xxd | sed -ne '1,/^0*70:/p'
}


# Copy to APFS partition
cp -p "/Volumes/Apps/Communication/ZTerm/ZTerm 0.9" ~

dumpxattr ~"/ZTerm 0.9"
FinderInfo
00000000: 4150 504c 7a54 524d 2106 ffff ffff 0000  APPLzTRM!.......
00000010: 0000 0000 0000 0000 0070 0000 0000 0000  .........p......
ResourceFork
00000000: 0000 0100 0003 045e 0003 035e 0000 0f2e  .......^...^....
00000010: 0000 0f25 0756 5431 3030 2e63 0200 0000  ...%.VT100.c....
00000020: 5445 5854 4b41 484c 0100 0000 0140 0000  TEXTKAHL.....@..
00000030: 095a 5465 726d 2030 2e39 0200 0000 4150  .ZTerm 0.9....AP
00000040: 504c 7a54 524d 2106 ffff ffff 0000 0000  PLzTRM!.........
00000050: 0000 4150 504c 7a54 524d 2106 ffff ffff  ..APPLzTRM!.....
00000060: 0000 0000 0000 0000 0000 0070 0000 0000  ...........p....
00000070: 0000 a5b9 ed3d 0000 0000 0003 138c 0000  .....=..........

sudo xattr -d com.apple.FinderInfo ~"/ZTerm 0.9"
xattr: [Errno 1] Operation not permitted: '/Users/joevt/ZTerm 0.9'


# Copy to HFS+ partition
cp -p "/Volumes/Apps/Communication/ZTerm/ZTerm 0.9" "/Volumes/Apps/Communication/ZTerm/ZTerm 0.9 copy"
sudo xattr -d com.apple.FinderInfo "/Volumes/Apps/Communication/ZTerm/ZTerm 0.9 copy"
xattr: [Errno 1] Operation not permitted: '/Volumes/Apps/Communication/ZTerm/ZTerm 0.9 copy'

dumpxattr "/Volumes/Apps/Communication/ZTerm/ZTerm 0.9 copy"
FinderInfo
00000000: 4150 504c 7a54 524d 2106 ffff ffff 0000  APPLzTRM!.......
00000010: 0000 0000 0000 0000 0070 0000 0000 0000  .........p......
ResourceFork
00000000: 0000 0100 0003 045e 0003 035e 0000 0f2e  .......^...^....
00000010: 0000 0f25 0756 5431 3030 2e63 0200 0000  ...%.VT100.c....
00000020: 5445 5854 4b41 484c 0100 0000 0140 0000  TEXTKAHL.....@..
00000030: 095a 5465 726d 2030 2e39 0200 0000 4150  .ZTerm 0.9....AP
00000040: 504c 7a54 524d 2106 ffff ffff 0000 0000  PLzTRM!.........
00000050: 0000 4150 504c 7a54 524d 2106 ffff ffff  ..APPLzTRM!.....
00000060: 0000 0000 0000 0000 0000 0070 0000 0000  ...........p....
00000070: 0000 a5b9 ed3d 0000 0000 0003 138c 0000  .....=..........


SetFile -help
Usage: SetFile [option...] file...
    -a attributes     # attributes (lowercase = 0, uppercase = 1)*
    -c creator        # file creator
    -d date           # creation date (mm/dd/[yy]yy [hh:mm[:ss] [AM | PM]])*
    -m date           # modification date (mm/dd/[yy]yy [hh:mm[:ss] [AM | PM]])*
    -P                # perform action on symlink instead of following it
    -t type           # file type

    Note: The following attributes may be used with the -a option:
        A   Alias file
        B   Bundle
        C   Custom icon*
        D   Desktop*
        E   Hidden extension*
        I   Inited*
        M   Shared (can run multiple times)
        N   No INIT resources
        L   Locked
        S   System (name locked)
        T   Stationery
        V   Invisible*
        Z   Busy*

    Note: Items marked with an asterisk (*) are allowed with folders
    Note: Period (.) represents the current date and time.
    Note: [yy]yy < 100 assumes 21st century, e.g. 20yy
 

NJRoadfan

New Tinkerer
Feb 6, 2022
68
20
8
IIRC, if the FinderInfo is entirely null bytes (or set as such), the OS will hide the com.apple.FinderInfo extended attribute from xattr and the C functions. The extended attribute itself is a system abstraction as stated previously.
 

joevt

Tinkerer
Mar 5, 2023
202
76
28
IIRC, if the FinderInfo is entirely null bytes (or set as such), the OS will hide the com.apple.FinderInfo extended attribute from xattr and the C functions. The extended attribute itself is a system abstraction as stated previously.
The app in my example was locked! After unlocking it, -d does work to remove (or hide) the FinderInfo.
So both of these will remove the FinderInfo (or set it to zeros which hides it from the xattr -l command):
Code:
sudo xattr -d com.apple.FinderInfo "ZTerm 0.9"
sudo xattr -wx com.apple.FinderInfo '0000000000000000000000000000000000000000000000000000000000000000' "ZTerm 0.9"

You have to use -wx instead of -w if any bytes in the data is a null byte.