1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 * gcc -framework ApplicationServices -l stdc++ -o asencode asencode.cpp
16 #include <sys/types.h>
19 #include <Carbon/Carbon.h>
21 typedef struct ASFinderInfo
23 FInfo ioFlFndrInfo
; /* PBGetFileInfo() or PBGetCatInfo() */
24 FXInfo ioFlXFndrInfo
; /* PBGetCatInfo() (HFS only) */
25 } ASFinderInfo
; /* ASFinderInfo */
27 #define EXIT_IF_FALSE(x) \
30 printf("Assertion failure: %s\n" \
32 #x, __FILE__, __LINE__); \
37 // encodes a file with data and resource forks into a single
38 // AppleSingle encoded file..
40 static void append_file(FILE* output
, const char* input_name
)
42 FILE* input
= fopen(input_name
, "rb");
43 EXIT_IF_FALSE(input
!= NULL
);
47 size_t amount
= fread(buffer
, 1, sizeof(buffer
), input
);
49 EXIT_IF_FALSE(feof(input
) != 0);
52 fwrite(buffer
, 1, amount
, output
);
57 int main(int argc
, char** argv
)
60 printf("usage: %s input output\n", argv
[0]);
64 const char *input_name
= argv
[1];
67 if (stat(input_name
, &input_st
) != 0) {
68 printf("%s: can't open file `%s'\n", argv
[0], input_name
);
72 if ((input_st
.st_mode
& S_IFMT
) != S_IFREG
) {
73 printf("%s: file `%s' not a regular file\n", argv
[0], input_name
);
78 strcpy(rez_name
, input_name
);
79 strcat(rez_name
, "/rsrc");
82 EXIT_IF_FALSE(stat(rez_name
, &rez_st
) == 0);
84 if (rez_st
.st_size
== 0) {
85 printf("%s: no resource fork found on file `%s'\n", argv
[0], argv
[1]);
89 FILE* output
= fopen(argv
[2], "wb");
91 printf("%s: can't open file `%s'\n", argv
[0], argv
[2]);
101 header
.magic_number
= 0x00051600;
102 header
.version_number
= 0x00020000;
104 EXIT_IF_FALSE(fwrite(&header
, sizeof(header
), 1, output
) == 1);
106 short entry_count
= 5;
107 EXIT_IF_FALSE(fwrite(&entry_count
, sizeof(entry_count
), 1, output
) == 1);
117 int create
; /* file creation date/time */
118 int modify
; /* last modification date/time */
119 int backup
; /* last backup date/time */
120 int access
; /* last access date/time */
123 char *name_buf
= strdup(input_name
);
124 char *orig_name
= basename(name_buf
);
125 int orig_name_len
= strlen(orig_name
);
127 entry entries
[entry_count
];
129 int header_end
= sizeof(header
) + sizeof(entry_count
) + sizeof(entries
);
131 entries
[0].id
= 1; // data fork
132 entries
[0].offset
= header_end
;
133 entries
[0].length
= input_st
.st_size
;
135 entries
[1].id
= 2; // data fork
136 entries
[1].offset
= entries
[0].offset
+ entries
[0].length
;
137 entries
[1].length
= rez_st
.st_size
;
139 entries
[2].id
= 3; // file name
140 entries
[2].offset
= entries
[1].offset
+ entries
[1].length
;
141 entries
[2].length
= orig_name_len
;
143 entries
[3].id
= 8; // file dates
144 entries
[3].offset
= entries
[2].offset
+ entries
[2].length
;
145 entries
[3].length
= sizeof(dates
);
147 entries
[4].id
= 9; // finder info
148 entries
[4].offset
= entries
[3].offset
+ entries
[3].length
;
149 entries
[4].length
= sizeof(ASFinderInfo
);
151 EXIT_IF_FALSE(fwrite(entries
, sizeof(entry
), entry_count
, output
) ==
154 append_file(output
, input_name
);
155 append_file(output
, rez_name
);
157 EXIT_IF_FALSE(fwrite(orig_name
, 1, orig_name_len
, output
) == orig_name_len
);
159 // Dates in an AppleSingle encoded file should be the number of
160 // seconds since (or to) 00:00:00, January 1, 2000 UTC
161 #define Y2K_SECONDS (946710000U)
163 dates
.create
= input_st
.st_ctime
- Y2K_SECONDS
;
164 dates
.modify
= input_st
.st_mtime
- Y2K_SECONDS
;
165 dates
.backup
= 0x80000000; // earliest possible time
166 dates
.access
= input_st
.st_atime
- Y2K_SECONDS
;
168 EXIT_IF_FALSE(fwrite(&dates
, 1, sizeof(dates
), output
) == sizeof(dates
));
170 char abs_input_name
[PATH_MAX
];
171 EXIT_IF_FALSE(realpath(input_name
, abs_input_name
) == abs_input_name
);
174 EXIT_IF_FALSE(FSPathMakeRef((unsigned char *)abs_input_name
, &fsref
, 0) == 0);
176 FSCatalogInfo cat_info
;
177 memset(&cat_info
, 0, sizeof(cat_info
));
178 EXIT_IF_FALSE(FSGetCatalogInfo(&fsref
,
179 kFSCatInfoGettableInfo
,
180 &cat_info
, NULL
, NULL
, NULL
) == 0);
182 ASFinderInfo finder_info
;
183 memcpy(&finder_info
.ioFlFndrInfo
, &cat_info
.finderInfo
,
184 sizeof(finder_info
.ioFlFndrInfo
));
185 memcpy(&finder_info
.ioFlXFndrInfo
, &cat_info
.extFinderInfo
,
186 sizeof(finder_info
.ioFlXFndrInfo
));
188 EXIT_IF_FALSE(fwrite(&finder_info
, 1, sizeof(finder_info
), output
) ==
189 sizeof(finder_info
));