1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /******************************************************************************
4 * Copyright (C) 2000-2016, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *******************************************************************************
7 * file name: pkgdata.cpp
8 * encoding: ANSI X3.4 (1968)
9 * tab size: 8 (not used)
10 * indentation:4
11 *
12 * created on: 2000may15
13 * created by: Steven \u24C7 Loomis
14 *
15 * This program packages the ICU data into different forms
16 * (DLL, common data, etc.)
17 */
18
19 // Defines _XOPEN_SOURCE for access to POSIX functions.
20 // Must be before any other #includes.
21 #include "uposixdefs.h"
22
23 #include "unicode/utypes.h"
24
25 #include "unicode/putil.h"
26 #include "putilimp.h"
27
28 #if U_HAVE_POPEN
29 #if (U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(__STRICT_ANSI__)
30 /* popen/pclose aren't defined in strict ANSI on Cygwin and MinGW */
31 #undef __STRICT_ANSI__
32 #endif
33 #endif
34
35 #include "cmemory.h"
36 #include "cstring.h"
37 #include "filestrm.h"
38 #include "toolutil.h"
39 #include "unicode/uclean.h"
40 #include "unewdata.h"
41 #include "uoptions.h"
42 #include "package.h"
43 #include "pkg_icu.h"
44 #include "pkg_genc.h"
45 #include "pkg_gencmn.h"
46 #include "flagparser.h"
47 #include "filetools.h"
48 #include "charstr.h"
49 #include "uassert.h"
50
51 #if U_HAVE_POPEN
52 # include <unistd.h>
53 #endif
54
55 #include <stdio.h>
56 #include <stdlib.h>
57
58 U_CDECL_BEGIN
59 #include "pkgtypes.h"
60 U_CDECL_END
61
62 #if U_HAVE_POPEN
63
64 using icu::LocalPointerBase;
65
66 U_DEFINE_LOCAL_OPEN_POINTER(LocalPipeFilePointer, FILE, pclose);
67
68 #endif
69
70 using icu::LocalMemory;
71
72 static void loadLists(UPKGOptions *o, UErrorCode *status);
73
74 static int32_t pkg_executeOptions(UPKGOptions *o);
75
76 #ifdef WINDOWS_WITH_MSVC
77 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
78 #endif
79 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling=false);
80 static int32_t pkg_installLibrary(const char *installDir, const char *dir, UBool noVersion);
81 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
82 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName);
83
84 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
85 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
86 #endif
87
88 #ifdef CAN_WRITE_OBJ_CODE
89 static void pkg_createOptMatchArch(char *optMatchArch);
90 static void pkg_destroyOptMatchArch(char *optMatchArch);
91 #endif
92
93 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
94 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = nullptr, UBool specialHandling=false);
95 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
96 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, const UBool reverseExt, UBool noVersion);
97 static int32_t initializePkgDataFlags(UPKGOptions *o);
98
99 static int32_t pkg_getPkgDataPath(UBool verbose, UOption *option);
100 static int runCommand(const char* command, UBool specialHandling=false);
101
102 #define IN_COMMON_MODE(mode) (mode == 'a' || mode == 'c')
103 #define IN_DLL_MODE(mode) (mode == 'd' || mode == 'l')
104 #define IN_STATIC_MODE(mode) (mode == 's')
105 #define IN_FILES_MODE(mode) (mode == 'f')
106
107 enum {
108 NAME,
109 BLDOPT,
110 MODE,
111 HELP,
112 HELP_QUESTION_MARK,
113 VERBOSE,
114 COPYRIGHT,
115 COMMENT,
116 DESTDIR,
117 REBUILD,
118 TEMPDIR,
119 INSTALL,
120 SOURCEDIR,
121 ENTRYPOINT,
122 REVISION,
123 FORCE_PREFIX,
124 LIBNAME,
125 QUIET,
126 WITHOUT_ASSEMBLY,
127 PDS_BUILD,
128 WIN_UWP_BUILD,
129 WIN_DLL_ARCH,
130 WIN_DYNAMICBASE
131 };
132
133 /* This sets the modes that are available */
134 static struct {
135 const char *name, *alt_name;
136 const char *desc;
137 } modes[] = {
138 { "files", 0, "Uses raw data files (no effect). Installation copies all files to the target location." },
139 #if U_PLATFORM_HAS_WIN32_API
140 { "dll", "library", "Generates one common data file and one shared library, <package>.dll"},
141 { "common", "archive", "Generates just the common file, <package>.dat"},
142 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
143 #else
144 #ifdef UDATA_SO_SUFFIX
145 { "dll", "library", "Generates one shared library, <package>" UDATA_SO_SUFFIX },
146 #endif
147 { "common", "archive", "Generates one common data file, <package>.dat" },
148 { "static", "static", "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
149 #endif
150 };
151
152 static UOption options[]={
153 /*00*/ UOPTION_DEF( "name", 'p', UOPT_REQUIRES_ARG),
154 /*01*/ UOPTION_DEF( "bldopt", 'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
155 /*02*/ UOPTION_DEF( "mode", 'm', UOPT_REQUIRES_ARG),
156 /*03*/ UOPTION_HELP_H, /* -h */
157 /*04*/ UOPTION_HELP_QUESTION_MARK, /* -? */
158 /*05*/ UOPTION_VERBOSE, /* -v */
159 /*06*/ UOPTION_COPYRIGHT, /* -c */
160 /*07*/ UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
161 /*08*/ UOPTION_DESTDIR, /* -d */
162 /*11*/ UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
163 /*12*/ UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
164 /*13*/ UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
165 /*14*/ UOPTION_SOURCEDIR ,
166 /*15*/ UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
167 /*16*/ UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
168 /*17*/ UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
169 /*18*/ UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
170 /*19*/ UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG),
171 /*20*/ UOPTION_DEF( "without-assembly", 'w', UOPT_NO_ARG),
172 /*21*/ UOPTION_DEF("zos-pds-build", 'z', UOPT_NO_ARG),
173 /*22*/ UOPTION_DEF("windows-uwp-build", 'u', UOPT_NO_ARG),
174 /*23*/ UOPTION_DEF("windows-DLL-arch", 'a', UOPT_REQUIRES_ARG),
175 /*24*/ UOPTION_DEF("windows-dynamicbase", 'b', UOPT_NO_ARG),
176 };
177
178 /* This enum and the following char array should be kept in sync. */
179 enum {
180 GENCCODE_ASSEMBLY_TYPE,
181 SO_EXT,
182 SOBJ_EXT,
183 A_EXT,
184 LIBPREFIX,
185 LIB_EXT_ORDER,
186 COMPILER,
187 LIBFLAGS,
188 GENLIB,
189 LDICUDTFLAGS,
190 LD_SONAME,
191 RPATH_FLAGS,
192 BIR_FLAGS,
193 AR,
194 ARFLAGS,
195 RANLIB,
196 INSTALL_CMD,
197 PKGDATA_FLAGS_SIZE
198 };
199 static const char* FLAG_NAMES[PKGDATA_FLAGS_SIZE] = {
200 "GENCCODE_ASSEMBLY_TYPE",
201 "SO",
202 "SOBJ",
203 "A",
204 "LIBPREFIX",
205 "LIB_EXT_ORDER",
206 "COMPILE",
207 "LIBFLAGS",
208 "GENLIB",
209 "LDICUDTFLAGS",
210 "LD_SONAME",
211 "RPATH_FLAGS",
212 "BIR_LDFLAGS",
213 "AR",
214 "ARFLAGS",
215 "RANLIB",
216 "INSTALL_CMD"
217 };
218 static char **pkgDataFlags = nullptr;
219
220 enum {
221 LIB_FILE,
222 LIB_FILE_VERSION_MAJOR,
223 LIB_FILE_VERSION,
224 LIB_FILE_VERSION_TMP,
225 #if U_PLATFORM == U_PF_CYGWIN
226 LIB_FILE_CYGWIN,
227 LIB_FILE_CYGWIN_VERSION,
228 #elif U_PLATFORM == U_PF_MINGW
229 LIB_FILE_MINGW,
230 #elif U_PLATFORM == U_PF_OS390
231 LIB_FILE_OS390BATCH_MAJOR,
232 LIB_FILE_OS390BATCH_VERSION,
233 #endif
234 LIB_FILENAMES_SIZE
235 };
236 static char libFileNames[LIB_FILENAMES_SIZE][256];
237
238 static UPKGOptions *pkg_checkFlag(UPKGOptions *o);
239
240 const char options_help[][320]={
241 "Set the data name",
242 #ifdef U_MAKE_IS_NMAKE
243 "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
244 #else
245 "Specify options for the builder.",
246 #endif
247 "Specify the mode of building (see below; default: common)",
248 "This usage text",
249 "This usage text",
250 "Make the output verbose",
251 "Use the standard ICU copyright",
252 "Use a custom comment (instead of the copyright)",
253 "Specify the destination directory for files",
254 "Force rebuilding of all data",
255 "Specify temporary dir (default: output dir)",
256 "Install the data (specify target)",
257 "Specify a custom source directory",
258 "Specify a custom entrypoint name (default: short name)",
259 "Specify a version when packaging in dll or static mode",
260 "Add package to all file names if not present",
261 "Library name to build (if different than package name)",
262 "Quiet mode. (e.g. Do not output a readme file for static libraries)",
263 "Build the data without assembly code",
264 "Build PDS dataset (zOS build only)",
265 "Build for Universal Windows Platform (Windows build only)",
266 "Specify the DLL machine architecture for LINK.exe (Windows build only)",
267 "Ignored. Enable DYNAMICBASE on the DLL. This is now the default. (Windows build only)",
268 };
269
270 const char *progname = "PKGDATA";
271
272 int
main(int argc,char * argv[])273 main(int argc, char* argv[]) {
274 int result = 0;
275 /* FileStream *out; */
276 UPKGOptions o;
277 CharList *tail;
278 UBool needsHelp = false;
279 UErrorCode status = U_ZERO_ERROR;
280 /* char tmp[1024]; */
281 uint32_t i;
282 int32_t n;
283
284 U_MAIN_INIT_ARGS(argc, argv);
285
286 progname = argv[0];
287
288 options[MODE].value = "common";
289
290 /* read command line options */
291 argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options);
292
293 /* error handling, printing usage message */
294 /* I've decided to simply print an error and quit. This tool has too
295 many options to just display them all of the time. */
296
297 if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
298 needsHelp = true;
299 }
300 else {
301 if(!needsHelp && argc<0) {
302 fprintf(stderr,
303 "%s: error in command line argument \"%s\"\n",
304 progname,
305 argv[-argc]);
306 fprintf(stderr, "Run '%s --help' for help.\n", progname);
307 return 1;
308 }
309
310
311 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
312 if(!options[BLDOPT].doesOccur && uprv_strcmp(options[MODE].value, "common") != 0) {
313 if (pkg_getPkgDataPath(options[VERBOSE].doesOccur, &options[BLDOPT]) != 0) {
314 fprintf(stderr, " required parameter is missing: -O is required for static and shared builds.\n");
315 fprintf(stderr, "Run '%s --help' for help.\n", progname);
316 return 1;
317 }
318 }
319 #else
320 if(options[BLDOPT].doesOccur) {
321 fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
322 }
323 #endif
324
325 if(!options[NAME].doesOccur) /* -O we already have - don't report it. */
326 {
327 fprintf(stderr, " required parameter -p is missing \n");
328 fprintf(stderr, "Run '%s --help' for help.\n", progname);
329 return 1;
330 }
331
332 if(argc == 1) {
333 fprintf(stderr,
334 "No input files specified.\n"
335 "Run '%s --help' for help.\n", progname);
336 return 1;
337 }
338 } /* end !needsHelp */
339
340 if(argc<0 || needsHelp ) {
341 fprintf(stderr,
342 "usage: %s [-options] [-] [packageFile] \n"
343 "\tProduce packaged ICU data from the given list(s) of files.\n"
344 "\t'-' by itself means to read from stdin.\n"
345 "\tpackageFile is a text file containing the list of files to package.\n",
346 progname);
347
348 fprintf(stderr, "\n options:\n");
349 for(i=0;i<UPRV_LENGTHOF(options);i++) {
350 fprintf(stderr, "%-5s -%c %s%-10s %s\n",
351 (i<1?"[REQ]":""),
352 options[i].shortName,
353 options[i].longName ? "or --" : " ",
354 options[i].longName ? options[i].longName : "",
355 options_help[i]);
356 }
357
358 fprintf(stderr, "modes: (-m option)\n");
359 for(i=0;i<UPRV_LENGTHOF(modes);i++) {
360 fprintf(stderr, " %-9s ", modes[i].name);
361 if (modes[i].alt_name) {
362 fprintf(stderr, "/ %-9s", modes[i].alt_name);
363 } else {
364 fprintf(stderr, " ");
365 }
366 fprintf(stderr, " %s\n", modes[i].desc);
367 }
368 return 1;
369 }
370
371 /* OK, fill in the options struct */
372 uprv_memset(&o, 0, sizeof(o));
373
374 o.mode = options[MODE].value;
375 o.version = options[REVISION].doesOccur ? options[REVISION].value : 0;
376
377 o.shortName = options[NAME].value;
378 {
379 int32_t len = (int32_t)uprv_strlen(o.shortName);
380 char *csname, *cp;
381 const char *sp;
382
383 cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
384 if (*(sp = o.shortName)) {
385 *cp++ = isalpha(*sp) ? * sp : '_';
386 for (++sp; *sp; ++sp) {
387 *cp++ = isalnum(*sp) ? *sp : '_';
388 }
389 }
390 *cp = 0;
391
392 o.cShortName = csname;
393 }
394
395 if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */
396 o.libName = options[LIBNAME].value;
397 } else {
398 o.libName = o.shortName;
399 }
400
401 if(options[QUIET].doesOccur) {
402 o.quiet = true;
403 } else {
404 o.quiet = false;
405 }
406
407 if(options[PDS_BUILD].doesOccur) {
408 #if U_PLATFORM == U_PF_OS390
409 o.pdsbuild = true;
410 #else
411 o.pdsbuild = false;
412 fprintf(stdout, "Warning: You are using the -z option which only works on z/OS.\n");
413
414 #endif
415 } else {
416 o.pdsbuild = false;
417 }
418
419 o.verbose = options[VERBOSE].doesOccur;
420
421
422 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) /* on UNIX, we'll just include the file... */
423 if (options[BLDOPT].doesOccur) {
424 o.options = options[BLDOPT].value;
425 } else {
426 o.options = nullptr;
427 }
428 #endif
429 if(options[COPYRIGHT].doesOccur) {
430 o.comment = U_COPYRIGHT_STRING;
431 } else if (options[COMMENT].doesOccur) {
432 o.comment = options[COMMENT].value;
433 }
434
435 if( options[DESTDIR].doesOccur ) {
436 o.targetDir = options[DESTDIR].value;
437 } else {
438 o.targetDir = "."; /* cwd */
439 }
440
441 o.rebuild = options[REBUILD].doesOccur;
442
443 if( options[TEMPDIR].doesOccur ) {
444 o.tmpDir = options[TEMPDIR].value;
445 } else {
446 o.tmpDir = o.targetDir;
447 }
448
449 if( options[INSTALL].doesOccur ) {
450 o.install = options[INSTALL].value;
451 } else {
452 o.install = nullptr;
453 }
454
455 if( options[SOURCEDIR].doesOccur ) {
456 o.srcDir = options[SOURCEDIR].value;
457 } else {
458 o.srcDir = ".";
459 }
460
461 if( options[ENTRYPOINT].doesOccur ) {
462 o.entryName = options[ENTRYPOINT].value;
463 } else {
464 o.entryName = o.cShortName;
465 }
466
467 o.withoutAssembly = false;
468 if (options[WITHOUT_ASSEMBLY].doesOccur) {
469 #ifndef BUILD_DATA_WITHOUT_ASSEMBLY
470 fprintf(stdout, "Warning: You are using the option to build without assembly code which is not supported on this platform.\n");
471 fprintf(stdout, "Warning: This option will be ignored.\n");
472 #else
473 o.withoutAssembly = true;
474 #endif
475 }
476
477 if (options[WIN_DYNAMICBASE].doesOccur) {
478 fprintf(stdout, "Note: Ignoring option -b (windows-dynamicbase).\n");
479 }
480
481 /* OK options are set up. Now the file lists. */
482 tail = nullptr;
483 for( n=1; n<argc; n++) {
484 o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n]));
485 }
486
487 /* load the files */
488 loadLists(&o, &status);
489 if( U_FAILURE(status) ) {
490 fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
491 return 2;
492 }
493
494 result = pkg_executeOptions(&o);
495
496 if (pkgDataFlags != nullptr) {
497 for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) {
498 if (pkgDataFlags[n] != nullptr) {
499 uprv_free(pkgDataFlags[n]);
500 }
501 }
502 uprv_free(pkgDataFlags);
503 }
504
505 if (o.cShortName != nullptr) {
506 uprv_free((char *)o.cShortName);
507 }
508 if (o.fileListFiles != nullptr) {
509 pkg_deleteList(o.fileListFiles);
510 }
511 if (o.filePaths != nullptr) {
512 pkg_deleteList(o.filePaths);
513 }
514 if (o.files != nullptr) {
515 pkg_deleteList(o.files);
516 }
517 return result;
518 }
519
runCommand(const char * command,UBool specialHandling)520 static int runCommand(const char* command, UBool specialHandling) {
521 char *cmd = nullptr;
522 char cmdBuffer[SMALL_BUFFER_MAX_SIZE];
523 int32_t len = static_cast<int32_t>(strlen(command));
524
525 if (len == 0) {
526 return 0;
527 }
528
529 if (!specialHandling) {
530 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400
531 int32_t buff_len;
532 if ((len + BUFFER_PADDING_SIZE) >= SMALL_BUFFER_MAX_SIZE) {
533 cmd = (char *)uprv_malloc(len + BUFFER_PADDING_SIZE);
534 buff_len = len + BUFFER_PADDING_SIZE;
535 } else {
536 cmd = cmdBuffer;
537 buff_len = SMALL_BUFFER_MAX_SIZE;
538 }
539 #if defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW
540 snprintf(cmd, buff_len, "bash -c \"%s\"", command);
541
542 #elif U_PLATFORM == U_PF_OS400
543 snprintf(cmd, buff_len "QSH CMD('%s')", command);
544 #endif
545 #else
546 goto normal_command_mode;
547 #endif
548 } else {
549 #if !(defined(USING_CYGWIN) || U_PLATFORM == U_PF_MINGW || U_PLATFORM == U_PF_OS400)
550 normal_command_mode:
551 #endif
552 cmd = (char *)command;
553 }
554
555 printf("pkgdata: %s\n", cmd);
556 int result = system(cmd);
557 if (result != 0) {
558 fprintf(stderr, "-- return status = %d\n", result);
559 result = 1; // system() result code is platform specific.
560 }
561
562 if (cmd != cmdBuffer && cmd != command) {
563 uprv_free(cmd);
564 }
565
566 return result;
567 }
568
569 #define LN_CMD "ln -s"
570 #define RM_CMD "rm -f"
571
pkg_executeOptions(UPKGOptions * o)572 static int32_t pkg_executeOptions(UPKGOptions *o) {
573 int32_t result = 0;
574
575 const char mode = o->mode[0];
576 char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
577 char tmpDir[SMALL_BUFFER_MAX_SIZE] = "";
578 char datFileName[SMALL_BUFFER_MAX_SIZE] = "";
579 char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
580 char checkLibFile[LARGE_BUFFER_MAX_SIZE] = "";
581
582 initializePkgDataFlags(o);
583
584 if (IN_FILES_MODE(mode)) {
585 /* Copy the raw data to the installation directory. */
586 if (o->install != nullptr) {
587 uprv_strcpy(targetDir, o->install);
588 if (o->shortName != nullptr) {
589 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
590 uprv_strcat(targetDir, o->shortName);
591 }
592
593 if(o->verbose) {
594 fprintf(stdout, "# Install: Files mode, copying files to %s..\n", targetDir);
595 }
596 result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str);
597 }
598 return result;
599 } else /* if (IN_COMMON_MODE(mode) || IN_DLL_MODE(mode) || IN_STATIC_MODE(mode)) */ {
600 UBool noVersion = false;
601
602 uprv_strcpy(targetDir, o->targetDir);
603 uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
604
605 uprv_strcpy(tmpDir, o->tmpDir);
606 uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING);
607
608 uprv_strcpy(datFileNamePath, tmpDir);
609
610 uprv_strcpy(datFileName, o->shortName);
611 uprv_strcat(datFileName, UDATA_CMN_SUFFIX);
612
613 uprv_strcat(datFileNamePath, datFileName);
614
615 if(o->verbose) {
616 fprintf(stdout, "# Writing package file %s ..\n", datFileNamePath);
617 }
618 result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, nullptr, U_CHARSET_FAMILY ? 'e' : U_IS_BIG_ENDIAN ? 'b' : 'l');
619 if (result != 0) {
620 fprintf(stderr,"Error writing package dat file.\n");
621 return result;
622 }
623
624 if (IN_COMMON_MODE(mode)) {
625 char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
626
627 uprv_strcpy(targetFileNamePath, targetDir);
628 uprv_strcat(targetFileNamePath, datFileName);
629
630 /* Move the dat file created to the target directory. */
631 if (uprv_strcmp(datFileNamePath, targetFileNamePath) != 0) {
632 if (T_FileStream_file_exists(targetFileNamePath)) {
633 if ((result = remove(targetFileNamePath)) != 0) {
634 fprintf(stderr, "Unable to remove old dat file: %s\n",
635 targetFileNamePath);
636 return result;
637 }
638 }
639
640 result = rename(datFileNamePath, targetFileNamePath);
641
642 if (o->verbose) {
643 fprintf(stdout, "# Moving package file to %s ..\n",
644 targetFileNamePath);
645 }
646 if (result != 0) {
647 fprintf(
648 stderr,
649 "Unable to move dat file (%s) to target location (%s).\n",
650 datFileNamePath, targetFileNamePath);
651 return result;
652 }
653 }
654
655 if (o->install != nullptr) {
656 result = pkg_installCommonMode(o->install, targetFileNamePath);
657 }
658
659 return result;
660 } else /* if (IN_STATIC_MODE(mode) || IN_DLL_MODE(mode)) */ {
661 char gencFilePath[SMALL_BUFFER_MAX_SIZE] = "";
662 char version_major[10] = "";
663 UBool reverseExt = false;
664
665 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
666 /* Get the version major number. */
667 if (o->version != nullptr) {
668 for (uint32_t i = 0;i < sizeof(version_major);i++) {
669 if (o->version[i] == '.') {
670 version_major[i] = 0;
671 break;
672 }
673 version_major[i] = o->version[i];
674 }
675 } else {
676 noVersion = true;
677 if (IN_DLL_MODE(mode)) {
678 fprintf(stdout, "Warning: Providing a revision number with the -r option is recommended when packaging data in the current mode.\n");
679 }
680 }
681
682 #if U_PLATFORM != U_PF_OS400
683 /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
684 * reverseExt is false if the suffix should be the version number.
685 */
686 if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) {
687 reverseExt = true;
688 }
689 #endif
690 /* Using the base libName and version number, generate the library file names. */
691 createFileNames(o, mode, version_major, o->version == nullptr ? "" : o->version, o->libName, reverseExt, noVersion);
692
693 if ((o->version!=nullptr || IN_STATIC_MODE(mode)) && o->rebuild == false && o->pdsbuild == false) {
694 /* Check to see if a previous built data library file exists and check if it is the latest. */
695 snprintf(checkLibFile, sizeof(checkLibFile), "%s%s", targetDir, libFileNames[LIB_FILE_VERSION]);
696 if (T_FileStream_file_exists(checkLibFile)) {
697 if (isFileModTimeLater(checkLibFile, o->srcDir, true) && isFileModTimeLater(checkLibFile, o->options)) {
698 if (o->install != nullptr) {
699 if(o->verbose) {
700 fprintf(stdout, "# Installing already-built library into %s\n", o->install);
701 }
702 result = pkg_installLibrary(o->install, targetDir, noVersion);
703 } else {
704 if(o->verbose) {
705 printf("# Not rebuilding %s - up to date.\n", checkLibFile);
706 }
707 }
708 return result;
709 } else if (o->verbose && (o->install!=nullptr)) {
710 fprintf(stdout, "# Not installing up-to-date library %s into %s\n", checkLibFile, o->install);
711 }
712 } else if(o->verbose && (o->install!=nullptr)) {
713 fprintf(stdout, "# Not installing missing %s into %s\n", checkLibFile, o->install);
714 }
715 }
716
717 if (pkg_checkFlag(o) == nullptr) {
718 /* Error occurred. */
719 return result;
720 }
721 #endif
722
723 if (!o->withoutAssembly && pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) {
724 const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE];
725
726 if(o->verbose) {
727 fprintf(stdout, "# Generating assembly code %s of type %s ..\n", gencFilePath, genccodeAssembly);
728 }
729
730 /* Offset genccodeAssembly by 3 because "-a " */
731 if (genccodeAssembly &&
732 (uprv_strlen(genccodeAssembly)>3) &&
733 checkAssemblyHeaderName(genccodeAssembly+3)) {
734 writeAssemblyCode(
735 datFileNamePath,
736 o->tmpDir,
737 o->entryName,
738 nullptr,
739 gencFilePath,
740 sizeof(gencFilePath));
741
742 result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath);
743 if (result != 0) {
744 fprintf(stderr, "Error generating assembly code for data.\n");
745 return result;
746 } else if (IN_STATIC_MODE(mode)) {
747 if(o->install != nullptr) {
748 if(o->verbose) {
749 fprintf(stdout, "# Installing static library into %s\n", o->install);
750 }
751 result = pkg_installLibrary(o->install, targetDir, noVersion);
752 }
753 return result;
754 }
755 } else {
756 fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly);
757 return -1;
758 }
759 } else {
760 if(o->verbose) {
761 fprintf(stdout, "# Writing object code to %s ..\n", gencFilePath);
762 }
763 if (o->withoutAssembly) {
764 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
765 result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
766 #else
767 /* This error should not occur. */
768 fprintf(stderr, "Error- BUILD_DATA_WITHOUT_ASSEMBLY is not defined. Internal error.\n");
769 #endif
770 } else {
771 #ifdef CAN_WRITE_OBJ_CODE
772 /* Try to detect the arch type, use nullptr if unsuccessful */
773 char optMatchArch[10] = { 0 };
774 pkg_createOptMatchArch(optMatchArch);
775 writeObjectCode(
776 datFileNamePath,
777 o->tmpDir,
778 o->entryName,
779 (optMatchArch[0] == 0 ? nullptr : optMatchArch),
780 nullptr,
781 gencFilePath,
782 sizeof(gencFilePath),
783 true);
784 pkg_destroyOptMatchArch(optMatchArch);
785 #if U_PLATFORM_IS_LINUX_BASED
786 result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
787 #elif defined(WINDOWS_WITH_MSVC)
788 result = pkg_createWindowsDLL(mode, gencFilePath, o);
789 #endif
790 #elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
791 result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
792 #else
793 fprintf(stderr, "Error- neither CAN_WRITE_OBJ_CODE nor BUILD_DATA_WITHOUT_ASSEMBLY are defined. Internal error.\n");
794 return 1;
795 #endif
796 }
797
798 if (result != 0) {
799 fprintf(stderr, "Error generating package data.\n");
800 return result;
801 }
802 }
803 #if !U_PLATFORM_USES_ONLY_WIN32_API
804 if(!IN_STATIC_MODE(mode)) {
805 /* Certain platforms uses archive library. (e.g. AIX) */
806 if(o->verbose) {
807 fprintf(stdout, "# Creating data archive library file ..\n");
808 }
809 result = pkg_archiveLibrary(targetDir, o->version, reverseExt);
810 if (result != 0) {
811 fprintf(stderr, "Error creating data archive library file.\n");
812 return result;
813 }
814 #if U_PLATFORM != U_PF_OS400
815 if (!noVersion) {
816 /* Create symbolic links for the final library file. */
817 #if U_PLATFORM == U_PF_OS390
818 result = pkg_createSymLinks(targetDir, o->pdsbuild);
819 #else
820 result = pkg_createSymLinks(targetDir, noVersion);
821 #endif
822 if (result != 0) {
823 fprintf(stderr, "Error creating symbolic links of the data library file.\n");
824 return result;
825 }
826 }
827 #endif
828 } /* !IN_STATIC_MODE */
829 #endif
830
831 #if !U_PLATFORM_USES_ONLY_WIN32_API
832 /* Install the libraries if option was set. */
833 if (o->install != nullptr) {
834 if(o->verbose) {
835 fprintf(stdout, "# Installing library file to %s ..\n", o->install);
836 }
837 result = pkg_installLibrary(o->install, targetDir, noVersion);
838 if (result != 0) {
839 fprintf(stderr, "Error installing the data library.\n");
840 return result;
841 }
842 }
843 #endif
844 }
845 }
846 return result;
847 }
848
849 /* Initialize the pkgDataFlags with the option file given. */
initializePkgDataFlags(UPKGOptions * o)850 static int32_t initializePkgDataFlags(UPKGOptions *o) {
851 UErrorCode status = U_ZERO_ERROR;
852 int32_t result = 0;
853 int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE;
854 int32_t tmpResult = 0;
855
856 /* Initialize pkgdataFlags */
857 pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE);
858
859 /* If we run out of space, allocate more */
860 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
861 do {
862 #endif
863 if (pkgDataFlags != nullptr) {
864 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
865 pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize);
866 if (pkgDataFlags[i] != nullptr) {
867 pkgDataFlags[i][0] = 0;
868 } else {
869 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
870 /* If an error occurs, ensure that the rest of the array is nullptr */
871 for (int32_t n = i + 1; n < PKGDATA_FLAGS_SIZE; n++) {
872 pkgDataFlags[n] = nullptr;
873 }
874 return -1;
875 }
876 }
877 } else {
878 fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
879 return -1;
880 }
881
882 if (o->options == nullptr) {
883 return result;
884 }
885
886 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
887 /* Read in options file. */
888 if(o->verbose) {
889 fprintf(stdout, "# Reading options file %s\n", o->options);
890 }
891 status = U_ZERO_ERROR;
892 tmpResult = parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, FLAG_NAMES, (int32_t)PKGDATA_FLAGS_SIZE, &status);
893 if (status == U_BUFFER_OVERFLOW_ERROR) {
894 for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
895 if (pkgDataFlags[i]) {
896 uprv_free(pkgDataFlags[i]);
897 pkgDataFlags[i] = nullptr;
898 }
899 }
900 currentBufferSize = tmpResult;
901 } else if (U_FAILURE(status)) {
902 fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status));
903 return -1;
904 }
905 #endif
906 if(o->verbose) {
907 fprintf(stdout, "# pkgDataFlags=\n");
908 for(int32_t i=0;i<PKGDATA_FLAGS_SIZE;i++) {
909 fprintf(stdout, " [%d] %s: %s\n", i, FLAG_NAMES[i], pkgDataFlags[i]);
910 }
911 fprintf(stdout, "\n");
912 }
913 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
914 } while (status == U_BUFFER_OVERFLOW_ERROR);
915 #endif
916
917 return result;
918 }
919
920
921 /*
922 * Given the base libName and version numbers, generate the library file names and store it in libFileNames.
923 * Depending on the configuration, the library name may either end with version number or shared object suffix.
924 */
createFileNames(UPKGOptions * o,const char mode,const char * version_major,const char * version,const char * libName,UBool reverseExt,UBool noVersion)925 static void createFileNames(UPKGOptions *o, const char mode, const char *version_major, const char *version, const char *libName, UBool reverseExt, UBool noVersion) {
926 const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : ".";
927 const char* FILE_SUFFIX = pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "";
928
929 #if U_PLATFORM == U_PF_MINGW
930 /* MinGW does not need the library prefix when building in dll mode. */
931 if (IN_DLL_MODE(mode)) {
932 snprintf(libFileNames[LIB_FILE], sizeof(libFileNames[LIB_FILE]), "%s", libName);
933 } else {
934 snprintf(libFileNames[LIB_FILE], sizeof(libFileNames[LIB_FILE]), "%s%s%s",
935 (strstr(libName, "icudt") ? "lib" : ""),
936 pkgDataFlags[LIBPREFIX],
937 libName);
938 }
939 #else
940 snprintf(libFileNames[LIB_FILE], sizeof(libFileNames[LIB_FILE]), "%s%s",
941 pkgDataFlags[LIBPREFIX],
942 libName);
943 #endif
944
945 if(o->verbose) {
946 fprintf(stdout, "# libFileName[LIB_FILE] = %s\n", libFileNames[LIB_FILE]);
947 }
948
949 #if U_PLATFORM == U_PF_MINGW
950 // Name the import library lib*.dll.a
951 snprintf(libFileNames[LIB_FILE_MINGW], sizeof(libFileNames[LIB_FILE_MINGW]), "lib%s.dll.a", libName);
952 #elif U_PLATFORM == U_PF_CYGWIN
953 snprintf(libFileNames[LIB_FILE_CYGWIN], sizeof(libFileNames[LIB_FILE_CYGWIN]), "cyg%s%s%s",
954 libName,
955 FILE_EXTENSION_SEP,
956 pkgDataFlags[SO_EXT]);
957 snprintf(libFileNames[LIB_FILE_CYGWIN_VERSION], sizeof(libFileNames[LIB_FILE_CYGWIN_VERSION]), "cyg%s%s%s%s",
958 libName,
959 version_major,
960 FILE_EXTENSION_SEP,
961 pkgDataFlags[SO_EXT]);
962
963 uprv_strcat(pkgDataFlags[SO_EXT], ".");
964 uprv_strcat(pkgDataFlags[SO_EXT], pkgDataFlags[A_EXT]);
965 #elif U_PLATFORM == U_PF_OS400 || defined(_AIX)
966 snprintf(libFileNames[LIB_FILE_VERSION_TMP], sizeof(libFileNames[LIB_FILE_VERSION_TMP]), "%s%s%s",
967 libFileNames[LIB_FILE],
968 FILE_EXTENSION_SEP,
969 pkgDataFlags[SOBJ_EXT]);
970 #elif U_PLATFORM == U_PF_OS390
971 snprintf(libFileNames[LIB_FILE_VERSION_TMP], sizeof(libFileNames[LIB_FILE_VERSION_TMP]), "%s%s%s%s%s",
972 libFileNames[LIB_FILE],
973 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
974 reverseExt ? version : pkgDataFlags[SOBJ_EXT],
975 FILE_EXTENSION_SEP,
976 reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
977
978 snprintf(libFileNames[LIB_FILE_OS390BATCH_VERSION], sizeof(libFileNames[LIB_FILE_OS390BATCH_VERSION]), "%s%s.x",
979 libFileNames[LIB_FILE],
980 version);
981 snprintf(libFileNames[LIB_FILE_OS390BATCH_MAJOR], sizeof(libFileNames[LIB_FILE_OS390BATCH_MAJOR]), "%s%s.x",
982 libFileNames[LIB_FILE],
983 version_major);
984 #else
985 if (noVersion && !reverseExt) {
986 snprintf(libFileNames[LIB_FILE_VERSION_TMP], sizeof(libFileNames[LIB_FILE_VERSION_TMP]), "%s%s%s",
987 libFileNames[LIB_FILE],
988 FILE_SUFFIX,
989 pkgDataFlags[SOBJ_EXT]);
990 } else {
991 snprintf(libFileNames[LIB_FILE_VERSION_TMP], sizeof(libFileNames[LIB_FILE_VERSION_TMP]), "%s%s%s%s%s",
992 libFileNames[LIB_FILE],
993 FILE_SUFFIX,
994 reverseExt ? version : pkgDataFlags[SOBJ_EXT],
995 FILE_EXTENSION_SEP,
996 reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
997 }
998 #endif
999 if (noVersion && !reverseExt) {
1000 snprintf(libFileNames[LIB_FILE_VERSION_MAJOR], sizeof(libFileNames[LIB_FILE_VERSION_TMP]), "%s%s%s",
1001 libFileNames[LIB_FILE],
1002 FILE_SUFFIX,
1003 pkgDataFlags[SO_EXT]);
1004
1005 snprintf(libFileNames[LIB_FILE_VERSION], sizeof(libFileNames[LIB_FILE_VERSION]), "%s%s%s",
1006 libFileNames[LIB_FILE],
1007 FILE_SUFFIX,
1008 pkgDataFlags[SO_EXT]);
1009 } else {
1010 snprintf(libFileNames[LIB_FILE_VERSION_MAJOR], sizeof(libFileNames[LIB_FILE_VERSION_MAJOR]), "%s%s%s%s%s",
1011 libFileNames[LIB_FILE],
1012 FILE_SUFFIX,
1013 reverseExt ? version_major : pkgDataFlags[SO_EXT],
1014 FILE_EXTENSION_SEP,
1015 reverseExt ? pkgDataFlags[SO_EXT] : version_major);
1016
1017 snprintf(libFileNames[LIB_FILE_VERSION], sizeof(libFileNames[LIB_FILE_VERSION]), "%s%s%s%s%s",
1018 libFileNames[LIB_FILE],
1019 FILE_SUFFIX,
1020 reverseExt ? version : pkgDataFlags[SO_EXT],
1021 FILE_EXTENSION_SEP,
1022 reverseExt ? pkgDataFlags[SO_EXT] : version);
1023 }
1024
1025 if(o->verbose) {
1026 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s\n", libFileNames[LIB_FILE_VERSION]);
1027 }
1028
1029 #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
1030 /* Cygwin and MinGW only deals with the version major number. */
1031 uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
1032 #endif
1033
1034 if(IN_STATIC_MODE(mode)) {
1035 snprintf(libFileNames[LIB_FILE_VERSION], sizeof(libFileNames[LIB_FILE_VERSION]), "%s.%s", libFileNames[LIB_FILE], pkgDataFlags[A_EXT]);
1036 libFileNames[LIB_FILE_VERSION_MAJOR][0]=0;
1037 if(o->verbose) {
1038 fprintf(stdout, "# libFileName[LIB_FILE_VERSION] = %s (static)\n", libFileNames[LIB_FILE_VERSION]);
1039 }
1040 }
1041 }
1042
1043 /* Create the symbolic links for the final library file. */
pkg_createSymLinks(const char * targetDir,UBool specialHandling)1044 static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) {
1045 int32_t result = 0;
1046 char cmd[LARGE_BUFFER_MAX_SIZE];
1047 char name1[SMALL_BUFFER_MAX_SIZE]; /* symlink file name */
1048 char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */
1049 const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : ".";
1050
1051 #if U_PLATFORM != U_PF_CYGWIN
1052 /* No symbolic link to make. */
1053 if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 ||
1054 uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
1055 return result;
1056 }
1057
1058 snprintf(cmd, sizeof(cmd), "cd %s && %s %s && %s %s %s",
1059 targetDir,
1060 RM_CMD,
1061 libFileNames[LIB_FILE_VERSION_MAJOR],
1062 LN_CMD,
1063 libFileNames[LIB_FILE_VERSION],
1064 libFileNames[LIB_FILE_VERSION_MAJOR]);
1065 result = runCommand(cmd);
1066 if (result != 0) {
1067 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
1068 return result;
1069 }
1070 #endif
1071
1072 if (specialHandling) {
1073 #if U_PLATFORM == U_PF_CYGWIN
1074 snprintf(name1, sizeof(name1), "%s", libFileNames[LIB_FILE_CYGWIN]);
1075 snprintf(name2, sizeof(name2), "%s", libFileNames[LIB_FILE_CYGWIN_VERSION]);
1076 #elif U_PLATFORM == U_PF_OS390
1077 /* Create the symbolic links for the import data */
1078 /* Use the cmd buffer to store path to import data file to check its existence */
1079 snprintf(cmd, sizeof(cmd), "%s/%s", targetDir, libFileNames[LIB_FILE_OS390BATCH_VERSION]);
1080 if (T_FileStream_file_exists(cmd)) {
1081 snprintf(cmd, sizeof(cmd), "cd %s && %s %s && %s %s %s",
1082 targetDir,
1083 RM_CMD,
1084 libFileNames[LIB_FILE_OS390BATCH_MAJOR],
1085 LN_CMD,
1086 libFileNames[LIB_FILE_OS390BATCH_VERSION],
1087 libFileNames[LIB_FILE_OS390BATCH_MAJOR]);
1088 result = runCommand(cmd);
1089 if (result != 0) {
1090 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
1091 return result;
1092 }
1093
1094 snprintf(cmd, sizeof(cmd), "cd %s && %s %s.x && %s %s %s.x",
1095 targetDir,
1096 RM_CMD,
1097 libFileNames[LIB_FILE],
1098 LN_CMD,
1099 libFileNames[LIB_FILE_OS390BATCH_VERSION],
1100 libFileNames[LIB_FILE]);
1101 result = runCommand(cmd);
1102 if (result != 0) {
1103 fprintf(stderr, "Error creating symbolic links. Failed command: %s\n", cmd);
1104 return result;
1105 }
1106 }
1107
1108 /* Needs to be set here because special handling skips it */
1109 snprintf(name1, sizeof(name1), "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
1110 snprintf(name2, sizeof(name2), "%s", libFileNames[LIB_FILE_VERSION]);
1111 #else
1112 goto normal_symlink_mode;
1113 #endif
1114 } else {
1115 #if U_PLATFORM != U_PF_CYGWIN
1116 normal_symlink_mode:
1117 #endif
1118 snprintf(name1, sizeof(name1), "%s%s%s", libFileNames[LIB_FILE], FILE_EXTENSION_SEP, pkgDataFlags[SO_EXT]);
1119 snprintf(name2, sizeof(name2), "%s", libFileNames[LIB_FILE_VERSION]);
1120 }
1121
1122 snprintf(cmd, sizeof(cmd), "cd %s && %s %s && %s %s %s",
1123 targetDir,
1124 RM_CMD,
1125 name1,
1126 LN_CMD,
1127 name2,
1128 name1);
1129
1130 result = runCommand(cmd);
1131
1132 return result;
1133 }
1134
pkg_installLibrary(const char * installDir,const char * targetDir,UBool noVersion)1135 static int32_t pkg_installLibrary(const char *installDir, const char *targetDir, UBool noVersion) {
1136 int32_t result = 0;
1137 char cmd[SMALL_BUFFER_MAX_SIZE];
1138
1139 auto ret = snprintf(cmd,
1140 sizeof(cmd),
1141 "cd %s && %s %s %s%s%s",
1142 targetDir,
1143 pkgDataFlags[INSTALL_CMD],
1144 libFileNames[LIB_FILE_VERSION],
1145 installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]);
1146 (void)ret;
1147 U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE);
1148
1149 result = runCommand(cmd);
1150
1151 if (result != 0) {
1152 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1153 return result;
1154 }
1155
1156 #ifdef CYGWINMSVC
1157 snprintf(cmd, sizeof(cmd), "cd %s && %s %s.lib %s",
1158 targetDir,
1159 pkgDataFlags[INSTALL_CMD],
1160 libFileNames[LIB_FILE],
1161 installDir
1162 );
1163 result = runCommand(cmd);
1164
1165 if (result != 0) {
1166 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1167 return result;
1168 }
1169 #elif U_PLATFORM == U_PF_CYGWIN
1170 snprintf(cmd, sizeof(cmd), "cd %s && %s %s %s",
1171 targetDir,
1172 pkgDataFlags[INSTALL_CMD],
1173 libFileNames[LIB_FILE_CYGWIN_VERSION],
1174 installDir
1175 );
1176 result = runCommand(cmd);
1177
1178 if (result != 0) {
1179 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1180 return result;
1181 }
1182
1183 #elif U_PLATFORM == U_PF_OS390
1184 if (T_FileStream_file_exists(libFileNames[LIB_FILE_OS390BATCH_VERSION])) {
1185 snprintf(cmd, sizeof(cmd), "%s %s %s",
1186 pkgDataFlags[INSTALL_CMD],
1187 libFileNames[LIB_FILE_OS390BATCH_VERSION],
1188 installDir
1189 );
1190 result = runCommand(cmd);
1191
1192 if (result != 0) {
1193 fprintf(stderr, "Error installing library. Failed command: %s\n", cmd);
1194 return result;
1195 }
1196 }
1197 #endif
1198
1199 if (noVersion) {
1200 return result;
1201 } else {
1202 return pkg_createSymLinks(installDir, true);
1203 }
1204 }
1205
pkg_installCommonMode(const char * installDir,const char * fileName)1206 static int32_t pkg_installCommonMode(const char *installDir, const char *fileName) {
1207 int32_t result = 0;
1208 char cmd[SMALL_BUFFER_MAX_SIZE] = "";
1209
1210 if (!T_FileStream_file_exists(installDir)) {
1211 UErrorCode status = U_ZERO_ERROR;
1212
1213 uprv_mkdir(installDir, &status);
1214 if (U_FAILURE(status)) {
1215 fprintf(stderr, "Error creating installation directory: %s\n", installDir);
1216 return -1;
1217 }
1218 }
1219 #ifndef U_WINDOWS_WITH_MSVC
1220 snprintf(cmd, sizeof(cmd), "%s %s %s", pkgDataFlags[INSTALL_CMD], fileName, installDir);
1221 #else
1222 snprintf(cmd, sizeof(cmd), "%s %s %s %s", WIN_INSTALL_CMD, fileName, installDir, WIN_INSTALL_CMD_FLAGS);
1223 #endif
1224
1225 result = runCommand(cmd);
1226 if (result != 0) {
1227 fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
1228 }
1229
1230 return result;
1231 }
1232
1233 #ifdef U_WINDOWS_MSVC
1234 /* Copy commands for installing the raw data files on Windows. */
1235 #define WIN_INSTALL_CMD "xcopy"
1236 #define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
1237 #endif
pkg_installFileMode(const char * installDir,const char * srcDir,const char * fileListName)1238 static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
1239 int32_t result = 0;
1240 char cmd[SMALL_BUFFER_MAX_SIZE] = "";
1241
1242 if (!T_FileStream_file_exists(installDir)) {
1243 UErrorCode status = U_ZERO_ERROR;
1244
1245 uprv_mkdir(installDir, &status);
1246 if (U_FAILURE(status)) {
1247 fprintf(stderr, "Error creating installation directory: %s\n", installDir);
1248 return -1;
1249 }
1250 }
1251 #ifndef U_WINDOWS_WITH_MSVC
1252 char buffer[SMALL_BUFFER_MAX_SIZE] = "";
1253 int32_t bufferLength = 0;
1254
1255 FileStream *f = T_FileStream_open(fileListName, "r");
1256 if (f != nullptr) {
1257 for(;;) {
1258 if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != nullptr) {
1259 bufferLength = static_cast<int32_t>(uprv_strlen(buffer));
1260 /* Remove new line character. */
1261 if (bufferLength > 0) {
1262 buffer[bufferLength-1] = 0;
1263 }
1264
1265 auto ret = snprintf(cmd,
1266 sizeof(cmd),
1267 "%s %s%s%s %s%s%s",
1268 pkgDataFlags[INSTALL_CMD],
1269 srcDir, PKGDATA_FILE_SEP_STRING, buffer,
1270 installDir, PKGDATA_FILE_SEP_STRING, buffer);
1271 (void)ret;
1272 U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE);
1273
1274 result = runCommand(cmd);
1275 if (result != 0) {
1276 fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
1277 break;
1278 }
1279 } else {
1280 if (!T_FileStream_eof(f)) {
1281 fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
1282 result = -1;
1283 }
1284 break;
1285 }
1286 }
1287 T_FileStream_close(f);
1288 } else {
1289 result = -1;
1290 fprintf(stderr, "Unable to open list file: %s\n", fileListName);
1291 }
1292 #else
1293 snprintf(cmd, sizeof(cmd), "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
1294 result = runCommand(cmd);
1295 if (result != 0) {
1296 fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
1297 }
1298 #endif
1299
1300 return result;
1301 }
1302
1303 /* Archiving of the library file may be needed depending on the platform and options given.
1304 * If archiving is not needed, copy over the library file name.
1305 */
pkg_archiveLibrary(const char * targetDir,const char * version,UBool reverseExt)1306 static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
1307 int32_t result = 0;
1308 char cmd[LARGE_BUFFER_MAX_SIZE];
1309
1310 /* If the shared object suffix and the final object suffix is different and the final object suffix and the
1311 * archive file suffix is the same, then the final library needs to be archived.
1312 */
1313 if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
1314 snprintf(libFileNames[LIB_FILE_VERSION], sizeof(libFileNames[LIB_FILE_VERSION]), "%s%s%s.%s",
1315 libFileNames[LIB_FILE],
1316 pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
1317 reverseExt ? version : pkgDataFlags[SO_EXT],
1318 reverseExt ? pkgDataFlags[SO_EXT] : version);
1319
1320 snprintf(cmd, sizeof(cmd), "%s %s %s%s %s%s",
1321 pkgDataFlags[AR],
1322 pkgDataFlags[ARFLAGS],
1323 targetDir,
1324 libFileNames[LIB_FILE_VERSION],
1325 targetDir,
1326 libFileNames[LIB_FILE_VERSION_TMP]);
1327
1328 result = runCommand(cmd);
1329 if (result != 0) {
1330 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
1331 return result;
1332 }
1333
1334 snprintf(cmd, sizeof(cmd), "%s %s%s",
1335 pkgDataFlags[RANLIB],
1336 targetDir,
1337 libFileNames[LIB_FILE_VERSION]);
1338
1339 result = runCommand(cmd);
1340 if (result != 0) {
1341 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
1342 return result;
1343 }
1344
1345 /* Remove unneeded library file. */
1346 snprintf(cmd, sizeof(cmd), "%s %s%s",
1347 RM_CMD,
1348 targetDir,
1349 libFileNames[LIB_FILE_VERSION_TMP]);
1350
1351 result = runCommand(cmd);
1352 if (result != 0) {
1353 fprintf(stderr, "Error creating archive library. Failed command: %s\n", cmd);
1354 return result;
1355 }
1356
1357 } else {
1358 uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
1359 }
1360
1361 return result;
1362 }
1363
1364 /*
1365 * Using the compiler information from the configuration file set by -O option, generate the library file.
1366 * command may be given to allow for a larger buffer for cmd.
1367 */
pkg_generateLibraryFile(const char * targetDir,const char mode,const char * objectFile,char * command,UBool specialHandling)1368 static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command, UBool specialHandling) {
1369 int32_t result = 0;
1370 char *cmd = nullptr;
1371 UBool freeCmd = false;
1372 int32_t length = 0;
1373
1374 (void)specialHandling; // Suppress unused variable compiler warnings on platforms where all usage
1375 // of this parameter is #ifdefed out.
1376
1377 /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
1378 * containing many object files and so the calling function should supply a command buffer that is large
1379 * enough to handle this. Otherwise, use the default size.
1380 */
1381 if (command != nullptr) {
1382 cmd = command;
1383 }
1384
1385 if (IN_STATIC_MODE(mode)) {
1386 if (cmd == nullptr) {
1387 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[AR]) + uprv_strlen(pkgDataFlags[ARFLAGS]) + uprv_strlen(targetDir) +
1388 uprv_strlen(libFileNames[LIB_FILE_VERSION]) + uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[RANLIB]) + BUFFER_PADDING_SIZE);
1389 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == nullptr) {
1390 fprintf(stderr, "Unable to allocate memory for command.\n");
1391 return -1;
1392 }
1393 freeCmd = true;
1394 }
1395 sprintf(cmd, "%s %s %s%s %s",
1396 pkgDataFlags[AR],
1397 pkgDataFlags[ARFLAGS],
1398 targetDir,
1399 libFileNames[LIB_FILE_VERSION],
1400 objectFile);
1401
1402 result = runCommand(cmd);
1403 if (result == 0) {
1404 sprintf(cmd, "%s %s%s",
1405 pkgDataFlags[RANLIB],
1406 targetDir,
1407 libFileNames[LIB_FILE_VERSION]);
1408
1409 result = runCommand(cmd);
1410 }
1411 } else /* if (IN_DLL_MODE(mode)) */ {
1412 if (cmd == nullptr) {
1413 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[GENLIB]) + uprv_strlen(pkgDataFlags[LDICUDTFLAGS]) +
1414 ((uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_VERSION_TMP])) * 2) +
1415 uprv_strlen(objectFile) + uprv_strlen(pkgDataFlags[LD_SONAME]) +
1416 uprv_strlen(pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR]) +
1417 uprv_strlen(pkgDataFlags[RPATH_FLAGS]) + uprv_strlen(pkgDataFlags[BIR_FLAGS]) + BUFFER_PADDING_SIZE);
1418 #if U_PLATFORM == U_PF_CYGWIN
1419 length += static_cast<int32_t>(uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_CYGWIN_VERSION]));
1420 #elif U_PLATFORM == U_PF_MINGW
1421 length += static_cast<int32_t>(uprv_strlen(targetDir) + uprv_strlen(libFileNames[LIB_FILE_MINGW]));
1422 #endif
1423 if ((cmd = (char *)uprv_malloc(sizeof(char) * length)) == nullptr) {
1424 fprintf(stderr, "Unable to allocate memory for command.\n");
1425 return -1;
1426 }
1427 freeCmd = true;
1428 }
1429 #if U_PLATFORM == U_PF_MINGW
1430 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
1431 pkgDataFlags[GENLIB],
1432 targetDir,
1433 libFileNames[LIB_FILE_MINGW],
1434 pkgDataFlags[LDICUDTFLAGS],
1435 targetDir,
1436 libFileNames[LIB_FILE_VERSION_TMP],
1437 #elif U_PLATFORM == U_PF_CYGWIN
1438 sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
1439 pkgDataFlags[GENLIB],
1440 targetDir,
1441 libFileNames[LIB_FILE_VERSION_TMP],
1442 pkgDataFlags[LDICUDTFLAGS],
1443 targetDir,
1444 libFileNames[LIB_FILE_CYGWIN_VERSION],
1445 #elif U_PLATFORM == U_PF_AIX
1446 sprintf(cmd, "%s %s%s;%s %s -o %s%s %s %s%s %s %s",
1447 RM_CMD,
1448 targetDir,
1449 libFileNames[LIB_FILE_VERSION_TMP],
1450 pkgDataFlags[GENLIB],
1451 pkgDataFlags[LDICUDTFLAGS],
1452 targetDir,
1453 libFileNames[LIB_FILE_VERSION_TMP],
1454 #else
1455 sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
1456 pkgDataFlags[GENLIB],
1457 pkgDataFlags[LDICUDTFLAGS],
1458 targetDir,
1459 libFileNames[LIB_FILE_VERSION_TMP],
1460 #endif
1461 objectFile,
1462 pkgDataFlags[LD_SONAME],
1463 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
1464 pkgDataFlags[RPATH_FLAGS],
1465 pkgDataFlags[BIR_FLAGS]);
1466
1467 /* Generate the library file. */
1468 result = runCommand(cmd);
1469
1470 #if U_PLATFORM == U_PF_OS390
1471 char *env_tmp;
1472 char PDS_LibName[512];
1473 char PDS_Name[512];
1474
1475 PDS_Name[0] = 0;
1476 PDS_LibName[0] = 0;
1477 if (specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata") == 0) {
1478 if (env_tmp = getenv("ICU_PDS_NAME")) {
1479 sprintf(PDS_Name, "%s%s",
1480 env_tmp,
1481 "DA");
1482 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
1483 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
1484 sprintf(PDS_Name, "%s%s",
1485 env_tmp,
1486 U_ICU_VERSION_SHORT "DA");
1487 } else {
1488 sprintf(PDS_Name, "%s%s",
1489 "IXMI",
1490 U_ICU_VERSION_SHORT "DA");
1491 }
1492 } else if (!specialHandling && uprv_strcmp(libFileNames[LIB_FILE],"libicudata_stub") == 0) {
1493 if (env_tmp = getenv("ICU_PDS_NAME")) {
1494 sprintf(PDS_Name, "%s%s",
1495 env_tmp,
1496 "D1");
1497 strcat(PDS_Name, getenv("ICU_PDS_NAME_SUFFIX"));
1498 } else if (env_tmp = getenv("PDS_NAME_PREFIX")) {
1499 sprintf(PDS_Name, "%s%s",
1500 env_tmp,
1501 U_ICU_VERSION_SHORT "D1");
1502 } else {
1503 sprintf(PDS_Name, "%s%s",
1504 "IXMI",
1505 U_ICU_VERSION_SHORT "D1");
1506 }
1507 }
1508
1509 if (PDS_Name[0]) {
1510 sprintf(PDS_LibName,"%s%s%s%s%s",
1511 "\"//'",
1512 getenv("LOADMOD"),
1513 "(",
1514 PDS_Name,
1515 ")'\"");
1516 sprintf(cmd, "%s %s -o %s %s %s%s %s %s",
1517 pkgDataFlags[GENLIB],
1518 pkgDataFlags[LDICUDTFLAGS],
1519 PDS_LibName,
1520 objectFile,
1521 pkgDataFlags[LD_SONAME],
1522 pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
1523 pkgDataFlags[RPATH_FLAGS],
1524 pkgDataFlags[BIR_FLAGS]);
1525
1526 result = runCommand(cmd);
1527 }
1528 #endif
1529 }
1530
1531 if (result != 0) {
1532 fprintf(stderr, "Error generating library file. Failed command: %s\n", cmd);
1533 }
1534
1535 if (freeCmd) {
1536 uprv_free(cmd);
1537 }
1538
1539 return result;
1540 }
1541
pkg_createWithAssemblyCode(const char * targetDir,const char mode,const char * gencFilePath)1542 static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
1543 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
1544 int32_t result = 0;
1545 int32_t length = 0;
1546
1547 /* Remove the ending .s and replace it with .o for the new object file. */
1548 uprv_strcpy(tempObjectFile, gencFilePath);
1549 tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
1550
1551 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS])
1552 + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + BUFFER_PADDING_SIZE);
1553
1554 LocalMemory<char> cmd((char *)uprv_malloc(sizeof(char) * length));
1555 if (cmd.isNull()) {
1556 return -1;
1557 }
1558
1559 /* Generate the object file. */
1560 snprintf(cmd.getAlias(), length, "%s %s -o %s %s",
1561 pkgDataFlags[COMPILER],
1562 pkgDataFlags[LIBFLAGS],
1563 tempObjectFile,
1564 gencFilePath);
1565
1566 result = runCommand(cmd.getAlias());
1567
1568 if (result != 0) {
1569 fprintf(stderr, "Error creating with assembly code. Failed command: %s\n", cmd.getAlias());
1570 return result;
1571 }
1572
1573 return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
1574 }
1575
1576 #ifdef BUILD_DATA_WITHOUT_ASSEMBLY
1577 /*
1578 * Generation of the data library without assembly code needs to compile each data file
1579 * individually and then link it all together.
1580 * Note: Any update to the directory structure of the data needs to be reflected here.
1581 */
1582 enum {
1583 DATA_PREFIX_BRKITR,
1584 DATA_PREFIX_COLL,
1585 DATA_PREFIX_CURR,
1586 DATA_PREFIX_LANG,
1587 DATA_PREFIX_RBNF,
1588 DATA_PREFIX_REGION,
1589 DATA_PREFIX_TRANSLIT,
1590 DATA_PREFIX_ZONE,
1591 DATA_PREFIX_UNIT,
1592 DATA_PREFIX_LENGTH
1593 };
1594
1595 const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
1596 "brkitr",
1597 "coll",
1598 "curr",
1599 "lang",
1600 "rbnf",
1601 "region",
1602 "translit",
1603 "zone",
1604 "unit"
1605 };
1606
pkg_createWithoutAssemblyCode(UPKGOptions * o,const char * targetDir,const char mode)1607 static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
1608 int32_t result = 0;
1609 CharList *list = o->filePaths;
1610 CharList *listNames = o->files;
1611 int32_t listSize = pkg_countCharList(list);
1612 char *buffer;
1613 char *cmd;
1614 char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
1615 char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
1616 #ifdef USE_SINGLE_CCODE_FILE
1617 char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
1618 FileStream *icudtAllFile = nullptr;
1619
1620 snprintf(icudtAll, sizeof(icudtAll), "%s%s%sall.c",
1621 o->tmpDir,
1622 PKGDATA_FILE_SEP_STRING,
1623 libFileNames[LIB_FILE]);
1624 /* Remove previous icudtall.c file. */
1625 if (T_FileStream_file_exists(icudtAll) && (result = remove(icudtAll)) != 0) {
1626 fprintf(stderr, "Unable to remove old icudtall file: %s\n", icudtAll);
1627 return result;
1628 }
1629
1630 if((icudtAllFile = T_FileStream_open(icudtAll, "w"))==nullptr) {
1631 fprintf(stderr, "Unable to write to icudtall file: %s\n", icudtAll);
1632 return result;
1633 }
1634 #endif
1635
1636 if (list == nullptr || listNames == nullptr) {
1637 /* list and listNames should never be nullptr since we are looping through the CharList with
1638 * the given size.
1639 */
1640 return -1;
1641 }
1642
1643 if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == nullptr) {
1644 fprintf(stderr, "Unable to allocate memory for cmd.\n");
1645 return -1;
1646 } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == nullptr) {
1647 fprintf(stderr, "Unable to allocate memory for buffer.\n");
1648 uprv_free(cmd);
1649 return -1;
1650 }
1651
1652 for (int32_t i = 0; i < (listSize + 1); i++) {
1653 const char *file ;
1654 const char *name;
1655
1656 if (i == 0) {
1657 /* The first iteration calls the gencmn function and initializes the buffer. */
1658 createCommonDataFile(o->tmpDir, o->shortName, o->entryName, nullptr, o->srcDir, o->comment, o->fileListFiles->str, 0, true, o->verbose, gencmnFile);
1659 buffer[0] = 0;
1660 #ifdef USE_SINGLE_CCODE_FILE
1661 uprv_strcpy(tempObjectFile, gencmnFile);
1662 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
1663
1664 sprintf(cmd, "%s %s -o %s %s",
1665 pkgDataFlags[COMPILER],
1666 pkgDataFlags[LIBFLAGS],
1667 tempObjectFile,
1668 gencmnFile);
1669
1670 result = runCommand(cmd);
1671 if (result != 0) {
1672 break;
1673 }
1674
1675 sprintf(buffer, "%s",tempObjectFile);
1676 #endif
1677 } else {
1678 char newName[SMALL_BUFFER_MAX_SIZE];
1679 char dataName[SMALL_BUFFER_MAX_SIZE];
1680 char dataDirName[SMALL_BUFFER_MAX_SIZE];
1681 const char *pSubstring;
1682 file = list->str;
1683 name = listNames->str;
1684
1685 newName[0] = dataName[0] = 0;
1686 for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
1687 dataDirName[0] = 0;
1688 sprintf(dataDirName, "%s%s", DATA_PREFIX[n], PKGDATA_FILE_SEP_STRING);
1689 /* If the name contains a prefix (indicating directory), alter the new name accordingly. */
1690 pSubstring = uprv_strstr(name, dataDirName);
1691 if (pSubstring != nullptr) {
1692 char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
1693 const char *p = name + uprv_strlen(dataDirName);
1694 for (int32_t i = 0;;i++) {
1695 if (p[i] == '.') {
1696 newNameTmp[i] = '_';
1697 continue;
1698 }
1699 newNameTmp[i] = p[i];
1700 if (p[i] == 0) {
1701 break;
1702 }
1703 }
1704 auto ret = snprintf(newName,
1705 sizeof(newName),
1706 "%s_%s",
1707 DATA_PREFIX[n],
1708 newNameTmp);
1709 (void)ret;
1710 U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE);
1711 ret = snprintf(dataName,
1712 sizeof(dataName),
1713 "%s_%s",
1714 o->shortName,
1715 DATA_PREFIX[n]);
1716 (void)ret;
1717 U_ASSERT(0 <= ret && ret < SMALL_BUFFER_MAX_SIZE);
1718 }
1719 if (newName[0] != 0) {
1720 break;
1721 }
1722 }
1723
1724 if(o->verbose) {
1725 printf("# Generating %s \n", gencmnFile);
1726 }
1727
1728 writeCCode(
1729 file,
1730 o->tmpDir,
1731 nullptr,
1732 dataName[0] != 0 ? dataName : o->shortName,
1733 newName[0] != 0 ? newName : nullptr,
1734 gencmnFile,
1735 sizeof(gencmnFile));
1736
1737 #ifdef USE_SINGLE_CCODE_FILE
1738 sprintf(cmd, "#include \"%s\"\n", gencmnFile);
1739 T_FileStream_writeLine(icudtAllFile, cmd);
1740 /* don't delete the file */
1741 #endif
1742 }
1743
1744 #ifndef USE_SINGLE_CCODE_FILE
1745 uprv_strcpy(tempObjectFile, gencmnFile);
1746 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
1747
1748 sprintf(cmd, "%s %s -o %s %s",
1749 pkgDataFlags[COMPILER],
1750 pkgDataFlags[LIBFLAGS],
1751 tempObjectFile,
1752 gencmnFile);
1753 result = runCommand(cmd);
1754 if (result != 0) {
1755 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
1756 break;
1757 }
1758
1759 uprv_strcat(buffer, " ");
1760 uprv_strcat(buffer, tempObjectFile);
1761
1762 #endif
1763
1764 if (i > 0) {
1765 list = list->next;
1766 listNames = listNames->next;
1767 }
1768 }
1769
1770 #ifdef USE_SINGLE_CCODE_FILE
1771 T_FileStream_close(icudtAllFile);
1772 uprv_strcpy(tempObjectFile, icudtAll);
1773 tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
1774
1775 sprintf(cmd, "%s %s -I. -o %s %s",
1776 pkgDataFlags[COMPILER],
1777 pkgDataFlags[LIBFLAGS],
1778 tempObjectFile,
1779 icudtAll);
1780
1781 result = runCommand(cmd);
1782 if (result == 0) {
1783 uprv_strcat(buffer, " ");
1784 uprv_strcat(buffer, tempObjectFile);
1785 } else {
1786 fprintf(stderr, "Error creating library without assembly code. Failed command: %s\n", cmd);
1787 }
1788 #endif
1789
1790 if (result == 0) {
1791 /* Generate the library file. */
1792 #if U_PLATFORM == U_PF_OS390
1793 result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd, (o->pdsbuild && IN_DLL_MODE(mode)));
1794 #else
1795 result = pkg_generateLibraryFile(targetDir,mode, buffer, cmd);
1796 #endif
1797 }
1798
1799 uprv_free(buffer);
1800 uprv_free(cmd);
1801
1802 return result;
1803 }
1804 #endif
1805
1806 #ifdef WINDOWS_WITH_MSVC
1807 #define LINK_CMD "link.exe /nologo /release /out:"
1808 #define LINK_FLAGS "/NXCOMPAT /DYNAMICBASE /DLL /NOENTRY /MANIFEST:NO /implib:"
1809
1810 #define LINK_EXTRA_UWP_FLAGS "/APPCONTAINER "
1811 #define LINK_EXTRA_UWP_FLAGS_X86_ONLY "/SAFESEH "
1812
1813 #define LINK_EXTRA_FLAGS_MACHINE "/MACHINE:"
1814 #define LIB_CMD "LIB.exe /nologo /out:"
1815 #define LIB_FILE "icudt.lib"
1816 #define LIB_EXT UDATA_LIB_SUFFIX
1817 #define DLL_EXT UDATA_SO_SUFFIX
1818
pkg_createWindowsDLL(const char mode,const char * gencFilePath,UPKGOptions * o)1819 static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
1820 int32_t result = 0;
1821 char cmd[LARGE_BUFFER_MAX_SIZE];
1822 if (IN_STATIC_MODE(mode)) {
1823 char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1824
1825 #ifdef CYGWINMSVC
1826 snprintf(staticLibFilePath, sizeof(staticLibFilePath), "%s%s%s%s%s",
1827 o->targetDir,
1828 PKGDATA_FILE_SEP_STRING,
1829 pkgDataFlags[LIBPREFIX],
1830 o->libName,
1831 LIB_EXT);
1832 #else
1833 snprintf(staticLibFilePath, sizeof(staticLibFilePath), "%s%s%s%s%s",
1834 o->targetDir,
1835 PKGDATA_FILE_SEP_STRING,
1836 (strstr(o->libName, "icudt") ? "s" : ""),
1837 o->libName,
1838 LIB_EXT);
1839 #endif
1840
1841 snprintf(cmd, sizeof(cmd), "%s\"%s\" \"%s\"",
1842 LIB_CMD,
1843 staticLibFilePath,
1844 gencFilePath);
1845 } else if (IN_DLL_MODE(mode)) {
1846 char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1847 char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1848 char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1849 char tmpResFilePath[SMALL_BUFFER_MAX_SIZE] = "";
1850
1851 #ifdef CYGWINMSVC
1852 uprv_strcpy(dllFilePath, o->targetDir);
1853 #else
1854 uprv_strcpy(dllFilePath, o->srcDir);
1855 #endif
1856 uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
1857 uprv_strcpy(libFilePath, dllFilePath);
1858
1859 #ifdef CYGWINMSVC
1860 uprv_strcat(libFilePath, o->libName);
1861 uprv_strcat(libFilePath, ".lib");
1862
1863 uprv_strcat(dllFilePath, o->libName);
1864 uprv_strcat(dllFilePath, o->version);
1865 #else
1866 if (strstr(o->libName, "icudt")) {
1867 uprv_strcat(libFilePath, LIB_FILE);
1868 } else {
1869 uprv_strcat(libFilePath, o->libName);
1870 uprv_strcat(libFilePath, ".lib");
1871 }
1872 uprv_strcat(dllFilePath, o->entryName);
1873 #endif
1874 uprv_strcat(dllFilePath, DLL_EXT);
1875
1876 uprv_strcpy(tmpResFilePath, o->tmpDir);
1877 uprv_strcat(tmpResFilePath, PKGDATA_FILE_SEP_STRING);
1878 uprv_strcat(tmpResFilePath, ICUDATA_RES_FILE);
1879
1880 if (T_FileStream_file_exists(tmpResFilePath)) {
1881 snprintf(resFilePath, sizeof(resFilePath), "\"%s\"", tmpResFilePath);
1882 }
1883
1884 /* Check if dll file and lib file exists and that it is not newer than genc file. */
1885 if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
1886 (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
1887 if(o->verbose) {
1888 printf("# Not rebuilding %s - up to date.\n", gencFilePath);
1889 }
1890 return 0;
1891 }
1892
1893 char extraFlags[SMALL_BUFFER_MAX_SIZE] = "";
1894 #ifdef WINDOWS_WITH_MSVC
1895 if (options[WIN_UWP_BUILD].doesOccur) {
1896 uprv_strcat(extraFlags, LINK_EXTRA_UWP_FLAGS);
1897
1898 if (options[WIN_DLL_ARCH].doesOccur) {
1899 if (uprv_strcmp(options[WIN_DLL_ARCH].value, "X86") == 0) {
1900 uprv_strcat(extraFlags, LINK_EXTRA_UWP_FLAGS_X86_ONLY);
1901 }
1902 }
1903 }
1904
1905 if (options[WIN_DLL_ARCH].doesOccur) {
1906 uprv_strcat(extraFlags, LINK_EXTRA_FLAGS_MACHINE);
1907 uprv_strcat(extraFlags, options[WIN_DLL_ARCH].value);
1908 }
1909
1910 #endif
1911 snprintf(cmd, sizeof(cmd), "%s\"%s\" %s %s\"%s\" \"%s\" %s",
1912 LINK_CMD,
1913 dllFilePath,
1914 extraFlags,
1915 LINK_FLAGS,
1916 libFilePath,
1917 gencFilePath,
1918 resFilePath
1919 );
1920 }
1921
1922 result = runCommand(cmd, true);
1923 if (result != 0) {
1924 fprintf(stderr, "Error creating Windows DLL library. Failed command: %s\n", cmd);
1925 }
1926
1927 return result;
1928 }
1929 #endif
1930
pkg_checkFlag(UPKGOptions * o)1931 static UPKGOptions *pkg_checkFlag(UPKGOptions *o) {
1932 #if U_PLATFORM == U_PF_AIX
1933 /* AIX needs a map file. */
1934 char *flag = nullptr;
1935 int32_t length = 0;
1936 char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
1937 const char MAP_FILE_EXT[] = ".map";
1938 FileStream *f = nullptr;
1939 char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
1940 int32_t start = -1;
1941 uint32_t count = 0;
1942 const char rm_cmd[] = "rm -f all ;";
1943
1944 flag = pkgDataFlags[GENLIB];
1945
1946 /* This portion of the code removes 'rm -f all' in the GENLIB.
1947 * Only occurs in AIX.
1948 */
1949 if (uprv_strstr(flag, rm_cmd) != nullptr) {
1950 char *tmpGenlibFlagBuffer = nullptr;
1951 int32_t i, offset;
1952
1953 length = static_cast<int32_t>(uprv_strlen(flag) + 1);
1954 tmpGenlibFlagBuffer = (char *)uprv_malloc(length);
1955 if (tmpGenlibFlagBuffer == nullptr) {
1956 /* Memory allocation error */
1957 fprintf(stderr,"Unable to allocate buffer of size: %d.\n", length);
1958 return nullptr;
1959 }
1960
1961 uprv_strcpy(tmpGenlibFlagBuffer, flag);
1962
1963 offset = static_cast<int32_t>(uprv_strlen(rm_cmd));
1964
1965 for (i = 0; i < (length - offset); i++) {
1966 flag[i] = tmpGenlibFlagBuffer[offset + i];
1967 }
1968
1969 /* Zero terminate the string */
1970 flag[i] = 0;
1971
1972 uprv_free(tmpGenlibFlagBuffer);
1973 }
1974
1975 flag = pkgDataFlags[BIR_FLAGS];
1976 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[BIR_FLAGS]));
1977
1978 for (int32_t i = 0; i < length; i++) {
1979 if (flag[i] == MAP_FILE_EXT[count]) {
1980 if (count == 0) {
1981 start = i;
1982 }
1983 count++;
1984 } else {
1985 count = 0;
1986 }
1987
1988 if (count == uprv_strlen(MAP_FILE_EXT)) {
1989 break;
1990 }
1991 }
1992
1993 if (start >= 0) {
1994 int32_t index = 0;
1995 for (int32_t i = 0;;i++) {
1996 if (i == start) {
1997 for (int32_t n = 0;;n++) {
1998 if (o->shortName[n] == 0) {
1999 break;
2000 }
2001 tmpbuffer[index++] = o->shortName[n];
2002 }
2003 }
2004
2005 tmpbuffer[index++] = flag[i];
2006
2007 if (flag[i] == 0) {
2008 break;
2009 }
2010 }
2011
2012 uprv_memset(flag, 0, length);
2013 uprv_strcpy(flag, tmpbuffer);
2014
2015 uprv_strcpy(mapFile, o->shortName);
2016 uprv_strcat(mapFile, MAP_FILE_EXT);
2017
2018 f = T_FileStream_open(mapFile, "w");
2019 if (f == nullptr) {
2020 fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
2021 return nullptr;
2022 } else {
2023 snprintf(tmpbuffer, sizeof(tmpbuffer), "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
2024
2025 T_FileStream_writeLine(f, tmpbuffer);
2026
2027 T_FileStream_close(f);
2028 }
2029 }
2030 #elif U_PLATFORM == U_PF_CYGWIN || U_PLATFORM == U_PF_MINGW
2031 /* Cygwin needs to change flag options. */
2032 char *flag = nullptr;
2033 int32_t length = 0;
2034
2035 flag = pkgDataFlags[GENLIB];
2036 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[GENLIB]));
2037
2038 int32_t position = length - 1;
2039
2040 for(;position >= 0;position--) {
2041 if (flag[position] == '=') {
2042 position++;
2043 break;
2044 }
2045 }
2046
2047 uprv_memset(flag + position, 0, length - position);
2048 #elif U_PLATFORM == U_PF_OS400
2049 /* OS/400 needs to fix the ld options (swap single quote with double quote) */
2050 char *flag = nullptr;
2051 int32_t length = 0;
2052
2053 flag = pkgDataFlags[GENLIB];
2054 length = static_cast<int32_t>(uprv_strlen(pkgDataFlags[GENLIB]));
2055
2056 int32_t position = length - 1;
2057
2058 for(int32_t i = 0; i < length; i++) {
2059 if (flag[i] == '\'') {
2060 flag[i] = '\"';
2061 }
2062 }
2063 #endif
2064 // Don't really need a return value, just need to stop compiler warnings about
2065 // the unused parameter 'o' on platforms where it is not otherwise used.
2066 return o;
2067 }
2068
loadLists(UPKGOptions * o,UErrorCode * status)2069 static void loadLists(UPKGOptions *o, UErrorCode *status)
2070 {
2071 CharList *l, *tail = nullptr, *tail2 = nullptr;
2072 FileStream *in;
2073 char line[16384];
2074 char *linePtr, *lineNext;
2075 const uint32_t lineMax = 16300;
2076 char *tmp;
2077 int32_t tmpLength = 0;
2078 char *s;
2079 int32_t ln=0; /* line number */
2080
2081 for(l = o->fileListFiles; l; l = l->next) {
2082 if(o->verbose) {
2083 fprintf(stdout, "# pkgdata: Reading %s..\n", l->str);
2084 }
2085 /* TODO: stdin */
2086 in = T_FileStream_open(l->str, "r"); /* open files list */
2087
2088 if(!in) {
2089 fprintf(stderr, "Error opening <%s>.\n", l->str);
2090 *status = U_FILE_ACCESS_ERROR;
2091 return;
2092 }
2093
2094 while(T_FileStream_readLine(in, line, sizeof(line))!=nullptr) { /* for each line */
2095 ln++;
2096 if(uprv_strlen(line)>lineMax) {
2097 fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
2098 exit(1);
2099 }
2100 /* remove spaces at the beginning */
2101 linePtr = line;
2102 /* On z/OS, disable call to isspace (#9996). Investigate using uprv_isspace instead (#9999) */
2103 #if U_PLATFORM != U_PF_OS390
2104 while(isspace(*linePtr)) {
2105 linePtr++;
2106 }
2107 #endif
2108 s=linePtr;
2109 /* remove trailing newline characters */
2110 while(*s!=0) {
2111 if(*s=='\r' || *s=='\n') {
2112 *s=0;
2113 break;
2114 }
2115 ++s;
2116 }
2117 if((*linePtr == 0) || (*linePtr == '#')) {
2118 continue; /* comment or empty line */
2119 }
2120
2121 /* Now, process the line */
2122 lineNext = nullptr;
2123
2124 while(linePtr && *linePtr) { /* process space-separated items */
2125 while(*linePtr == ' ') {
2126 linePtr++;
2127 }
2128 /* Find the next quote */
2129 if(linePtr[0] == '"')
2130 {
2131 lineNext = uprv_strchr(linePtr+1, '"');
2132 if(lineNext == nullptr) {
2133 fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
2134 l->str, (int)ln);
2135 exit(1);
2136 } else {
2137 lineNext++;
2138 if(*lineNext) {
2139 if(*lineNext != ' ') {
2140 fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
2141 l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
2142 exit(1);
2143 }
2144 *lineNext = 0;
2145 lineNext++;
2146 }
2147 }
2148 } else {
2149 lineNext = uprv_strchr(linePtr, ' ');
2150 if(lineNext) {
2151 *lineNext = 0; /* terminate at space */
2152 lineNext++;
2153 }
2154 }
2155
2156 /* add the file */
2157 s = (char*)getLongPathname(linePtr);
2158
2159 /* normal mode.. o->files is just the bare list without package names */
2160 o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
2161 if(uprv_pathIsAbsolute(s) || s[0] == '.') {
2162 fprintf(stderr, "pkgdata: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, s);
2163 exit(U_ILLEGAL_ARGUMENT_ERROR);
2164 }
2165 /* The +5 is to add a little extra space for, among other things, PKGDATA_FILE_SEP_STRING */
2166 tmpLength = static_cast<int32_t>(uprv_strlen(o->srcDir) + uprv_strlen(s) + 5);
2167 if((tmp = (char *)uprv_malloc(tmpLength)) == nullptr) {
2168 fprintf(stderr, "pkgdata: Error: Unable to allocate tmp buffer size: %d\n", tmpLength);
2169 exit(U_MEMORY_ALLOCATION_ERROR);
2170 }
2171 uprv_strcpy(tmp, o->srcDir);
2172 uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" : PKGDATA_FILE_SEP_STRING);
2173 uprv_strcat(tmp, s);
2174 o->filePaths = pkg_appendToList(o->filePaths, &tail2, tmp);
2175 linePtr = lineNext;
2176 } /* for each entry on line */
2177 } /* for each line */
2178 T_FileStream_close(in);
2179 } /* for each file list file */
2180 }
2181
2182 /* Helper for pkg_getPkgDataPath() */
2183 #if U_HAVE_POPEN
getPkgDataPath(const char * cmd,UBool verbose,char * buf,size_t items)2184 static UBool getPkgDataPath(const char *cmd, UBool verbose, char *buf, size_t items) {
2185 icu::CharString cmdBuf;
2186 UErrorCode status = U_ZERO_ERROR;
2187 LocalPipeFilePointer p;
2188 size_t n;
2189
2190 cmdBuf.append(cmd, status);
2191 if (verbose) {
2192 fprintf(stdout, "# Calling: %s\n", cmdBuf.data());
2193 }
2194 p.adoptInstead( popen(cmdBuf.data(), "r") );
2195
2196 if (p.isNull() || (n = fread(buf, 1, items-1, p.getAlias())) <= 0) {
2197 fprintf(stderr, "%s: Error calling '%s'\n", progname, cmd);
2198 *buf = 0;
2199 return false;
2200 }
2201
2202 return true;
2203 }
2204 #endif
2205
2206 /* Get path to pkgdata.inc. Try pkg-config first, falling back to icu-config. */
pkg_getPkgDataPath(UBool verbose,UOption * option)2207 static int32_t pkg_getPkgDataPath(UBool verbose, UOption *option) {
2208 #if U_HAVE_POPEN
2209 static char buf[512] = "";
2210 UBool pkgconfigIsValid = true;
2211 const char *pkgconfigCmd = "pkg-config --variable=pkglibdir icu-uc";
2212 const char *icuconfigCmd = "icu-config --incpkgdatafile";
2213 const char *pkgdata = "pkgdata.inc";
2214
2215 if (!getPkgDataPath(pkgconfigCmd, verbose, buf, UPRV_LENGTHOF(buf))) {
2216 if (!getPkgDataPath(icuconfigCmd, verbose, buf, UPRV_LENGTHOF(buf))) {
2217 fprintf(stderr, "%s: icu-config not found. Fix PATH or specify -O option\n", progname);
2218 return -1;
2219 }
2220
2221 pkgconfigIsValid = false;
2222 }
2223
2224 for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
2225 if (buf[length] == '\n' || buf[length] == ' ') {
2226 buf[length] = 0;
2227 } else {
2228 break;
2229 }
2230 }
2231
2232 if (!*buf) {
2233 fprintf(stderr, "%s: Unable to locate pkgdata.inc. Unable to parse the results of '%s'. Check paths or use the -O option to specify the path to pkgdata.inc.\n", progname, pkgconfigIsValid ? pkgconfigCmd : icuconfigCmd);
2234 return -1;
2235 }
2236
2237 if (pkgconfigIsValid) {
2238 uprv_strcat(buf, U_FILE_SEP_STRING);
2239 uprv_strcat(buf, pkgdata);
2240 }
2241
2242 buf[strlen(buf)] = 0;
2243
2244 option->value = buf;
2245 option->doesOccur = true;
2246
2247 return 0;
2248 #else
2249 return -1;
2250 #endif
2251 }
2252
2253 #ifdef CAN_WRITE_OBJ_CODE
2254 /* Create optMatchArch for genccode architecture detection */
pkg_createOptMatchArch(char * optMatchArch)2255 static void pkg_createOptMatchArch(char *optMatchArch) {
2256 #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN)
2257 const char* code = "void oma(){}";
2258 const char* source = "oma.c";
2259 const char* obj = "oma.obj";
2260 FileStream* stream = nullptr;
2261
2262 stream = T_FileStream_open(source,"w");
2263 if (stream != nullptr) {
2264 T_FileStream_writeLine(stream, code);
2265 T_FileStream_close(stream);
2266
2267 char cmd[LARGE_BUFFER_MAX_SIZE];
2268 snprintf(cmd, sizeof(cmd), "%s %s -o %s",
2269 pkgDataFlags[COMPILER],
2270 source,
2271 obj);
2272
2273 if (runCommand(cmd) == 0){
2274 sprintf(optMatchArch, "%s", obj);
2275 }
2276 else {
2277 fprintf(stderr, "Failed to compile %s\n", source);
2278 }
2279 if(!T_FileStream_remove(source)){
2280 fprintf(stderr, "T_FileStream_remove failed to delete %s\n", source);
2281 }
2282 }
2283 else {
2284 fprintf(stderr, "T_FileStream_open failed to open %s for writing\n", source);
2285 }
2286 #endif
2287 }
pkg_destroyOptMatchArch(char * optMatchArch)2288 static void pkg_destroyOptMatchArch(char *optMatchArch) {
2289 if(T_FileStream_file_exists(optMatchArch) && !T_FileStream_remove(optMatchArch)){
2290 fprintf(stderr, "T_FileStream_remove failed to delete %s\n", optMatchArch);
2291 }
2292 }
2293 #endif
2294