10 #include <Resources.h>
13 static const char *kUsage
=
14 "Usage: %s [ <options> ] -o <outFile> [ <inFile> ... ]\n"
16 "Reads resources from zero or more input files and adds them as attributes\n"
17 "to the specified output file, or (in reverse mode) reads attributes from\n"
18 "zero or more input files and adds them as resources to the specified output\n"
19 "file. If not existent the output file is created as an empty file.\n"
22 " -h, --help - Print this text.\n"
23 " -o <outfile> - Specifies the output file.\n"
24 " -O, --overwrite - Overwrite existing attributes. regardless of whether\n"
25 " an attribute does already exist, it is always written\n"
26 " when a respective resource is encountered in an input\n"
27 " file. The last input file specifying the attribute\n"
28 " wins. If the options is not given, already existing\n"
29 " attributes remain untouched. Otherwise the first input\n"
30 " file specifying an attribute wins.\n"
31 " -r, --reverse - Reverse mode: Reads attributes from input files and\n"
32 " writes resources. A unique resource ID is assigned to\n"
33 " each attribute, so there will be no conflicts if two\n"
34 " input files feature the same attribute.\n"
39 static const char *const *sArgv
;
43 print_usage(bool error
)
45 // get nice program name
46 const char *programName
= (sArgc
> 0 ? sArgv
[0] : "resattr");
47 if (const char *lastSlash
= strrchr(programName
, '/'))
48 programName
= lastSlash
+ 1;
51 fprintf((error
? stderr
: stdout
), kUsage
, programName
);
54 // print_usage_and_exit
57 print_usage_and_exit(bool error
)
66 next_arg(int argc
, const char* const* argv
, int& argi
, bool dontFail
= false)
68 if (argi
+ 1 >= argc
) {
71 print_usage_and_exit(true);
80 write_attributes(BNode
&out
, const char *inFileName
, BResources
&resources
,
83 // iterate through the resources
88 for (int resIndex
= 0;
89 resources
.GetResourceInfo(resIndex
, &type
, &id
, &name
, &size
);
91 // if we shall not overwrite attributes, we skip the attribute, if it
94 if (!overwrite
&& out
.GetAttrInfo(name
, &attrInfo
) == B_OK
)
98 const void *data
= resources
.LoadResource(type
, id
, &size
);
99 if (!data
&& size
> 0) {
101 fprintf(stderr
, "Failed to get resource `%s', type: %" B_PRIx32
102 ", id: %" B_PRId32
" from input file `%s'\n", name
, type
, id
,
107 // construct a name, if the resource doesn't have one
110 sprintf(nameBuffer
, "unnamed_%d\n", resIndex
);
114 // write the attribute
115 ssize_t bytesWritten
= out
.WriteAttr(name
, type
, 0LL, data
, size
);
116 if (bytesWritten
< 0) {
117 fprintf(stderr
, "Failed to write attribute `%s' to output file: "
118 "%s\n", name
, strerror(bytesWritten
));
126 write_resources(BResources
&resources
, const char *inFileName
, BNode
&in
,
129 // iterate through the attributes
130 char name
[B_ATTR_NAME_LENGTH
];
131 while (in
.GetNextAttrName(name
) == B_OK
) {
132 // get attribute info
134 status_t error
= in
.GetAttrInfo(name
, &attrInfo
);
136 fprintf(stderr
, "Failed to get info for attribute `%s' of input "
137 "file `%s': %s\n", name
, inFileName
, strerror(error
));
142 char *data
= new char[attrInfo
.size
];
143 ssize_t bytesRead
= in
.ReadAttr(name
, attrInfo
.type
, 0LL, data
,
146 fprintf(stderr
, "Failed to read attribute `%s' of input "
147 "file `%s': %s\n", name
, inFileName
, strerror(bytesRead
));
153 const char *existingName
;
155 while (resources
.GetResourceInfo(attrInfo
.type
, resID
, &existingName
,
161 error
= resources
.AddResource(attrInfo
.type
, resID
++, data
,
162 attrInfo
.size
, name
);
164 fprintf(stderr
, "Failed to write resource `%s' to output "
165 "file: %s\n", name
, strerror(error
));
171 // resources_to_attributes
174 resources_to_attributes(const char *outputFile
, const char **inputFiles
,
175 int inputFileCount
, bool overwrite
)
177 // create output file, if it doesn't exist
178 if (!BEntry(outputFile
).Exists()) {
180 status_t error
= createdOut
.SetTo(outputFile
,
181 B_READ_WRITE
| B_CREATE_FILE
);
183 fprintf(stderr
, "Failed to create output file `%s': %s\n",
184 outputFile
, strerror(error
));
191 status_t error
= out
.SetTo(outputFile
);
193 fprintf(stderr
, "Failed to open output file `%s': %s\n", outputFile
,
198 // iterate through the input files
199 for (int i
= 0; i
< inputFileCount
; i
++) {
202 error
= in
.SetTo(inputFiles
[i
], B_READ_ONLY
);
204 fprintf(stderr
, "Failed to open input file `%s': %s\n",
205 inputFiles
[i
], strerror(error
));
210 BResources resources
;
211 error
= resources
.SetTo(&in
, false);
213 fprintf(stderr
, "Failed to read resources of input file `%s': %s\n",
214 inputFiles
[i
], strerror(error
));
218 // add the attributes
219 write_attributes(out
, inputFiles
[i
], resources
, overwrite
);
223 // resources_to_attributes
226 attributes_to_resources(const char *outputFile
, const char **inputFiles
,
231 status_t error
= out
.SetTo(outputFile
, B_READ_WRITE
| B_CREATE_FILE
);
233 fprintf(stderr
, "Failed to open output file `%s': %s\n", outputFile
,
238 // init output resources
239 BResources resources
;
240 error
= resources
.SetTo(&out
, false);
242 fprintf(stderr
, "Failed to init resources of output file `%s': %s\n",
243 outputFile
, strerror(error
));
249 // iterate through the input files
250 for (int i
= 0; i
< inputFileCount
; i
++) {
253 error
= in
.SetTo(inputFiles
[i
]);
255 fprintf(stderr
, "Failed to open input file `%s': %s\n",
256 inputFiles
[i
], strerror(error
));
262 write_resources(resources
, inputFiles
[i
], in
, resID
);
268 main(int argc
, const char *const *argv
)
274 const char *outputFile
= NULL
;
275 bool overwrite
= false;
276 bool reverse
= false;
277 const char **inputFiles
= new const char*[argc
];
278 int inputFileCount
= 0;
281 for (int argi
= 1; argi
< argc
; argi
++) {
282 const char *arg
= argv
[argi
];
284 if (strcmp(arg
, "-h") == 0 || strcmp(arg
, "--help") == 0) {
285 print_usage_and_exit(false);
286 } else if (strcmp(arg
, "-o") == 0) {
287 outputFile
= next_arg(argc
, argv
, argi
);
288 } else if (strcmp(arg
, "-O") == 0) {
290 } else if (strcmp(arg
, "-r") == 0
291 || strcmp(arg
, "--reverse") == 0) {
294 print_usage_and_exit(true);
297 inputFiles
[inputFileCount
++] = arg
;
303 print_usage_and_exit(true);
306 attributes_to_resources(outputFile
, inputFiles
, inputFileCount
);
308 resources_to_attributes(outputFile
, inputFiles
, inputFileCount
,