123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065 |
- /****************************************************************************
- * tools/zds/zdsar.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <sys/stat.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <limits.h>
- #include <ctype.h>
- #include <libgen.h>
- #include <errno.h>
- #ifdef HOST_CYGWIN
- # include <sys/cygwin.h>
- #endif
- /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
- #define MAX_BUFFER (4096)
- #define MAX_EXPAND (2048)
- /* MAX_PATH might be defined in stdlib.h */
- #if !defined(MAX_PATH)
- # define MAX_PATH (512)
- #endif
- /* NAME_MAX is typically defined in limits.h */
- #if !defined(NAME_MAX)
- /* FILENAME_MAX might be defined in stdio.h */
- # if defined(FILENAME_MAX)
- # define NAME_MAX FILENAME_MAX
- # else
- /* MAXNAMELEN might be defined in dirent.h */
- # include <dirent.h>
- # if defined(MAXNAMLEN)
- # define NAME_MAX MAXNAMLEN
- # else
- /* Lets not let a silly think like this stop us... just make something up */
- # define NAME_MAX 256
- # endif
- # endif
- #endif
- /* Maximum objects per librarian call.
- *
- * REVISIT: The librarian is supposed to handle multiple object insertions
- * per call, but my experience was that it was unreliable in that case. That
- * may have improved, however, and perhaps we can increase MAX_OPBJEXT.. TRY
- * IT!
- */
- #define MAX_OBJECTS 1 /* 64 */
- /* Name of the host. The ZDS-II toolchain runs only on Windows. Therefore,
- * the only options are (1) Windows native, or (2) Cygwin or environments
- * that derive for Cygwin (like MSYS2).
- */
- #define WINSEPARATOR '\\'
- #if defined(HOST_NATIVE)
- # define SEPARATOR '\\'
- # define HOSTNAME "Native" /* Windows native */
- #elif defined(HOST_CYGWIN)
- # define SEPARATOR '/'
- # define HOSTNAME "Cygwin" /* Cygwin or MSYS under Windows */
- #endif
- /****************************************************************************
- * Private Data
- ****************************************************************************/
- static char *g_current_wd = NULL; /* Current working directory */
- static char *g_ar = NULL; /* Full path to the librarian program */
- static char *g_arflags = NULL; /* Flags to use with the librarian program */
- static char *g_libpath = NULL; /* Path to the library */
- static char *g_libname = NULL; /* Library file name*/
- static char *g_objects = NULL; /* List of object files */
- static int g_debug = 0; /* Debug output enabled if >0 */
- static char g_command[MAX_BUFFER]; /* Full librarian command */
- static char g_initial_wd[MAX_PATH]; /* Initial working directory */
- static char g_path[MAX_PATH]; /* Temporary for path generation */
- static char g_objpath[MAX_PATH]; /* Holds the relative path to the objects */
- #ifdef HOST_CYGWIN
- static char g_expand[MAX_EXPAND]; /* Temporary for quoted path */
- static char g_dequoted[MAX_PATH]; /* Temporary for de-quoted path */
- static char g_hostpath[MAX_PATH]; /* Temporary for host path conversions */
- #endif
- /****************************************************************************
- * Private Functions
- ****************************************************************************/
- /* MinGW does not seem to provide strtok_r */
- #ifndef HAVE_STRTOK_R
- static char *my_strtok_r(char *str, const char *delim, char **saveptr)
- {
- char *pbegin;
- char *pend = NULL;
- /* Decide if we are starting a new string or continuing from
- * the point we left off.
- */
- if (str)
- {
- pbegin = str;
- }
- else if (saveptr && *saveptr)
- {
- pbegin = *saveptr;
- }
- else
- {
- return NULL;
- }
- /* Find the beginning of the next token */
- for (;
- *pbegin && strchr(delim, *pbegin) != NULL;
- pbegin++);
- /* If we are at the end of the string with nothing
- * but delimiters found, then return NULL.
- */
- if (!*pbegin)
- {
- return NULL;
- }
- /* Find the end of the token */
- for (pend = pbegin + 1;
- *pend && strchr(delim, *pend) == NULL;
- pend++);
- /* pend either points to the end of the string or to
- * the first delimiter after the string.
- */
- if (*pend)
- {
- /* Turn the delimiter into a null terminator */
- *pend++ = '\0';
- }
- /* Save the pointer where we left off and return the
- * beginning of the token.
- */
- if (saveptr)
- {
- *saveptr = pend;
- }
- return pbegin;
- }
- #undef strtok_r
- # define strtok_r my_strtok_r
- #endif
- static void append(char **base, char *str)
- {
- char *oldbase;
- char *newbase;
- int alloclen;
- oldbase = *base;
- if (oldbase == NULL)
- {
- newbase = strdup(str);
- if (!newbase)
- {
- fprintf(stderr, "ERROR: Failed to strdup %s\n", str);
- exit(EXIT_FAILURE);
- }
- }
- else
- {
- alloclen = strlen(oldbase) + strlen(str) + sizeof((char) ' ') +
- sizeof((char) '\0');
- newbase = (char *)malloc(alloclen);
- if (!newbase)
- {
- fprintf(stderr, "ERROR: Failed to allocate %d bytes\n", alloclen);
- exit(EXIT_FAILURE);
- }
- snprintf(newbase, alloclen, "%s %s", oldbase, str);
- free(oldbase);
- }
- *base = newbase;
- }
- static const char *quote_backslash(const char *argument)
- {
- #ifdef HOST_CYGWIN
- const char *src;
- char *dest;
- int len;
- src = argument;
- dest = g_expand;
- len = 0;
- while (*src && len < MAX_EXPAND)
- {
- if (*src == '\\')
- {
- /* Copy backslash */
- *dest++ = *src++;
- if (++len >= MAX_EXPAND)
- {
- break;
- }
- /* Already quoted? */
- if (*src == '\\')
- {
- /* Yes... just copy all consecutive backslashes */
- do
- {
- *dest++ = *src++;
- if (++len >= MAX_EXPAND)
- {
- break;
- }
- }
- while (*src == '\\');
- }
- else
- {
- /* No.. expend */
- *dest++ = '\\';
- if (++len >= MAX_EXPAND)
- {
- break;
- }
- }
- }
- else
- {
- *dest++ = *src++;
- len++;
- }
- }
- if (*src)
- {
- fprintf(stderr, "ERROR: Truncated during expansion string "
- "is too long [%lu/%u]\n",
- (unsigned long)strlen(argument), MAX_EXPAND);
- exit(EXIT_FAILURE);
- }
- *dest = '\0';
- return g_expand;
- #else
- return argument;
- #endif
- }
- /* Remove backslash quoting from a path */
- #ifdef HOST_CYGWIN
- static bool dequote_path(const char *winpath)
- {
- char *dest = g_dequoted;
- const char *src = winpath;
- int len = 0;
- bool quoted = false;
- while (*src && len < MAX_PATH)
- {
- if (src[0] != '\\' ||
- (src[1] != ' ' && src[1] != '(' && src[1] != ')'))
- {
- *dest++ = *src;
- len++;
- }
- else
- {
- quoted = true;
- }
- src++;
- }
- if (*src || len >= MAX_PATH)
- {
- fprintf(stderr, "# ERROR: Path truncated\n");
- exit(EXIT_FAILURE);
- }
- *dest = '\0';
- return quoted;
- }
- #endif
- /* If using Cygwin with a Window's Toolchain, then we have to convert the
- * POSIX path to a Windows or POSIX path.
- */
- #ifdef HOST_CYGWIN
- static const char *convert_path(const char *path, cygwin_conv_path_t what)
- {
- const char *retptr;
- ssize_t size;
- ssize_t ret;
- bool quoted;
- quoted = dequote_path(path);
- if (quoted)
- {
- retptr = g_hostpath;
- }
- else
- {
- retptr = &g_hostpath[1];
- }
- size = cygwin_conv_path(what | CCP_RELATIVE, g_dequoted, NULL, 0);
- if (size > (MAX_PATH - 3))
- {
- fprintf(stderr, "# ERROR: POSIX path too long: %lu\n",
- (unsigned long)size);
- exit(EXIT_FAILURE);
- }
- ret = cygwin_conv_path(what | CCP_RELATIVE, g_dequoted,
- &g_hostpath[1], MAX_PATH - 3);
- if (ret < 0)
- {
- fprintf(stderr, "# ERROR: cygwin_conv_path '%s' failed: %s\n",
- g_dequoted, strerror(errno));
- exit(EXIT_FAILURE);
- }
- if (quoted)
- {
- size++;
- g_hostpath[0] = '"';
- g_hostpath[size] = '"';
- }
- g_hostpath[size + 1] = '\0';
- return retptr;
- }
- #endif
- static const char *convert_path_windows(const char *path)
- {
- #ifdef HOST_CYGWIN
- return convert_path(path, CCP_POSIX_TO_WIN_A);
- #else
- strcpy(g_path, path);
- return g_path;
- #endif
- }
- static const char *convert_path_posix(const char *path)
- {
- #ifdef HOST_CYGWIN
- return convert_path(path, CCP_WIN_A_TO_POSIX);
- #else
- strcpy(g_path, path);
- return g_path;
- #endif
- }
- static void show_usage(const char *progname, const char *msg, int exitcode)
- {
- if (msg)
- {
- fprintf(stderr, "\n");
- fprintf(stderr, "%s:\n", msg);
- }
- fprintf(stderr, "\n");
- fprintf(stderr, "%s [OPTIONS] --ar \"<AR>\" --library \"<LIBRARY>\" "
- "obj [obj [obj...]]\n",
- progname);
- fprintf(stderr, "\n");
- fprintf(stderr, "Where:\n");
- fprintf(stderr, " --ar <AR>\n");
- fprintf(stderr, " A command line string that defines how to execute the "
- "ZDS-II librarian\n");
- fprintf(stderr, " --library \"<LIBRARY>\"\n");
- fprintf(stderr, " The library into which the object files will be "
- "inserted\n");
- fprintf(stderr, " obj\n");
- fprintf(stderr, " One or more object files that will be inserted into "
- "the archive. Each expected\n");
- fprintf(stderr, " to reside in the current directory unless --obj-path "
- "is provided on the command line\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "And [OPTIONS] include:\n");
- fprintf(stderr, " --ar_flags \"<ARFLAGS>\"\n");
- fprintf(stderr, " Optional librarian flags\n");
- fprintf(stderr, " --obj-path <path>\n");
- fprintf(stderr, " Do not look in the current directory for the object "
- "files. Instead, look in <path> for\n");
- fprintf(stderr, " the object files. --obj-path may be used only once "
- "on the command line\n");
- fprintf(stderr, " --debug\n");
- fprintf(stderr, " Enable %s debug output\n", progname);
- fprintf(stderr, " --help\n");
- fprintf(stderr, " Shows this message and exits\n");
- exit(exitcode);
- }
- static void parse_args(int argc, char **argv)
- {
- const char *tmp = NULL;
- char *library = NULL;
- char *objpath = NULL;
- int pathlen;
- int argidx;
- /* Parse arguments */
- for (argidx = 1; argidx < argc; argidx++)
- {
- if (strcmp(argv[argidx], "--ar") == 0)
- {
- argidx++;
- if (argidx >= argc)
- {
- show_usage(argv[0], "ERROR: Missing argument to --ar",
- EXIT_FAILURE);
- }
- else if (g_ar != NULL)
- {
- show_usage(argv[0], "ERROR: Multiple --ar arguments",
- EXIT_FAILURE);
- }
- g_ar = argv[argidx];
- }
- else if (strcmp(argv[argidx], "--ar_flags") == 0)
- {
- argidx++;
- if (argidx >= argc)
- {
- show_usage(argv[0], "ERROR: Missing argument to --ar_flags",
- EXIT_FAILURE);
- }
- else if (g_arflags != NULL)
- {
- show_usage(argv[0], "ERROR: Multiple --ar_flags arguments",
- EXIT_FAILURE);
- }
- g_arflags = argv[argidx];
- }
- else if (strcmp(argv[argidx], "--library") == 0)
- {
- const char *tmp_path;
- argidx++;
- if (argidx >= argc)
- {
- show_usage(argv[0], "ERROR: Missing argument to --library",
- EXIT_FAILURE);
- }
- else if (library != NULL)
- {
- show_usage(argv[0], "ERROR: Multiple --library arguments",
- EXIT_FAILURE);
- }
- /* Convert the library path a POSIX. NOTE this is a no-op in Windows
- * native mode.
- */
- tmp_path = convert_path_posix(argv[argidx]);
- library = strdup(tmp_path);
- if (library == NULL)
- {
- fprintf(stderr, "ERROR: strdup() failed\n");
- exit(EXIT_FAILURE);
- }
- }
- else if (strcmp(argv[argidx], "--obj-path") == 0)
- {
- argidx++;
- if (argidx >= argc)
- {
- show_usage(argv[0], "ERROR: Missing argument to --obj-path",
- EXIT_FAILURE);
- }
- else if (objpath != NULL)
- {
- show_usage(argv[0], "ERROR: Multiple --obj-path arguments",
- EXIT_FAILURE);
- }
- objpath = argv[argidx];
- }
- else if (strcmp(argv[argidx], "--debug") == 0)
- {
- g_debug++;
- }
- else if (strcmp(argv[argidx], "--help") == 0)
- {
- show_usage(argv[0], NULL, EXIT_SUCCESS);
- }
- else if (strncmp(argv[argidx], "--", 2) == 0)
- {
- show_usage(argv[0], "ERROR: Unrecognized option", EXIT_FAILURE);
- }
- else
- {
- break;
- }
- }
- /* Accumulate object files */
- for (; argidx < argc; argidx++)
- {
- append(&g_objects, argv[argidx]);
- }
- if (g_debug)
- {
- fprintf(stderr, "Selections:\n");
- fprintf(stderr, " CWD : [%s]\n",
- g_initial_wd);
- fprintf(stderr, " Host Environ : [%s]\n",
- HOSTNAME);
- fprintf(stderr, " AR : [%s]\n",
- g_ar ? g_ar : "(None)");
- fprintf(stderr, " AR Flags : [%s]\n",
- g_arflags ? g_arflags : "(None)");
- fprintf(stderr, " Library : [%s]\n",
- library ? library : "(None)");
- fprintf(stderr, " Object Path : [%s]\n",
- objpath ? objpath : "(None");
- fprintf(stderr, " Object Files : [%s]\n\n",
- g_objects ? g_objects : "(None)");
- }
- /* Check for required parameters */
- if (g_ar == NULL)
- {
- show_usage(argv[0], "ERROR: No librarian specified",
- EXIT_FAILURE);
- }
- if (library == NULL)
- {
- show_usage(argv[0], "ERROR: No library specified",
- EXIT_FAILURE);
- }
- else
- {
- /* Separate the library file name from the path. The ZDS-II librarian
- * expects the library to be in the current working directory.
- */
- g_libname = basename(library); /* Must come first */
- g_libpath = dirname(library);
- }
- if (g_objects == NULL)
- {
- /* Don't report an error -- this happens normally in some configurations */
- printf("No object files specified\n");
- exit(EXIT_SUCCESS);
- }
- g_objpath[0] = '\0';
- if (objpath != NULL)
- {
- /* If the object path relative to the current working directory? */
- /* It is a relative path if the path does not begin with the path
- * segment separator or if in the Windows native case, it begins
- * with a volume specified like C:.
- */
- pathlen = 0;
- #ifdef HOST_NATIVE
- if (objpath[0] != SEPARATOR ||
- (isalpha(objpath[0]) && objpath[1] != ':'))
- #else
- if (objpath[0] != SEPARATOR)
- #endif
- {
- /* Add the default working directory to the path */
- /* Copy the initial working directory */
- pathlen = strlen(g_initial_wd);
- if (pathlen >= MAX_PATH)
- {
- fprintf(stderr, "ERROR: Working directory path is "
- "too long [%d/%d]: %s\n",
- pathlen, MAX_PATH, g_initial_wd);
- exit(EXIT_FAILURE);
- }
- strcpy(g_path, g_initial_wd);
- /* Append a separator is one is not already present */
- if (g_path[pathlen - 1] != SEPARATOR)
- {
- int newlen = pathlen + 1;
- if (newlen >= MAX_PATH)
- {
- fprintf(stderr, "ERROR: Object path is too long "
- "with separator[%d/%d]: %s\n",
- newlen, MAX_PATH, g_initial_wd);
- exit(EXIT_FAILURE);
- }
- g_path[pathlen] = SEPARATOR;
- g_path[pathlen + 1] = '\0';
- pathlen = newlen;
- }
- }
- /* Add the object file path after the current working directory */
- pathlen += strlen(objpath);
- if (pathlen >= MAX_PATH)
- {
- fprintf(stderr, "ERROR: Path+objpath is too long [%d/%d]\n",
- pathlen, MAX_PATH);
- exit(EXIT_FAILURE);
- }
- strcat(g_path, objpath);
- }
- /* The object was in the current working directory. If a library path
- * is NOT the current working directory, then the library path will now
- * be the current working directory and the path to the objects will be
- * the working directory when the program was started.
- */
- else if (g_libpath != NULL && strcmp(g_libpath, ".") != 0)
- {
- strcpy(g_path, g_initial_wd);
- }
- /* Convert the absolute objection file path to the native host path form
- * NOTE that convert_path_posix() is a no-op in Windows native mode.
- */
- tmp = convert_path_posix(g_path);
- strcpy(g_path, tmp);
- /* Check for a relative path. We will CD to g_libpath because the
- * library must be in the current working directory.
- */
- pathlen = strlen(g_libpath);
- if (strncmp(g_path, g_libpath, pathlen) == 0)
- {
- const char *relpath = &g_path[pathlen];
- /* Skip over leading path segment delimiters.. that should be as
- * least one.
- */
- while (*relpath == SEPARATOR)
- {
- relpath++;
- }
- /* Convert the relative object file path to the Windows path form
- * for the ZDS-II tool tool. NOTE that convert_path_windows() is
- * a no-op in Windows native mode.
- */
- tmp = convert_path_windows(relpath);
- }
- else
- {
- /* Convert the absolute object file path to the Windows path form
- * for the ZDS-II tool tool. NOTE that convert_path_windows() is
- * a no-op in Windows native mode.
- */
- tmp = convert_path_windows(g_path);
- }
- /* And save the path in as a native Windows path */
- strcpy(g_objpath, tmp);
- /* Dump some intermediate results */
- if (g_debug)
- {
- fprintf(stderr, "Derived:\n");
- fprintf(stderr, " Object Path : [%s]\n",
- g_objpath[0] != '\0' ? g_objpath : "(None");
- fprintf(stderr, " Library Path : [%s]\n",
- g_libpath ? g_libpath : "(None)");
- fprintf(stderr, " Library Name : [%s]\n\n",
- g_libname ? g_libname : "(None)");
- }
- }
- static void do_archive(void)
- {
- struct stat buf;
- char *alloc;
- char *objects;
- char *object;
- char *lasts;
- int cmdlen;
- int pathlen;
- int objlen;
- int totallen;
- int nobjects;
- int ret;
- /* Make a copy of g_objects. We need to do this because at least the version
- * of strtok_r above does modify it.
- */
- alloc = strdup(g_objects);
- if (alloc == NULL)
- {
- fprintf(stderr, "ERROR: Failed to strdup object list\n");
- exit(EXIT_FAILURE);
- }
- objects = alloc;
- /* We may have to loop since we limit the number of objects in each call
- * to the librarian.
- */
- lasts = NULL;
- for (; ; )
- {
- /* Copy the librarian into the command buffer */
- cmdlen = strlen(g_ar);
- if (cmdlen >= MAX_BUFFER)
- {
- fprintf(stderr, "ERROR: Librarian string is too long [%d/%d]: %s\n",
- cmdlen, MAX_BUFFER, g_ar);
- exit(EXIT_FAILURE);
- }
- strcpy(g_command, g_ar);
- /* Add a space */
- g_command[cmdlen] = ' ';
- cmdlen++;
- g_command[cmdlen] = '\0';
- /* Copy the librarian flags into the command buffer */
- if (g_arflags != NULL)
- {
- const char *quoted;
- quoted = quote_backslash(g_arflags);
- cmdlen += strlen(quoted);
- if (cmdlen >= MAX_BUFFER)
- {
- fprintf(stderr, "ERROR: CFLAG string is too long [%d/%d]: %s\n",
- cmdlen, MAX_BUFFER, g_arflags);
- exit(EXIT_FAILURE);
- }
- strcat(g_command, quoted);
- }
- /* Add each object file. This loop will continue until each path has been
- * tried (failure) or until stat() finds the object file
- */
- nobjects = 0;
- while ((object = strtok_r(objects, " ", &lasts)) != NULL)
- {
- const char *quoted;
- const char *converted;
- /* Set objects to NULL. This will force strtok_r to move from the
- * the first object in the list.
- */
- objects = NULL;
- /* Add a space */
- g_command[cmdlen] = ' ';
- cmdlen++;
- g_command[cmdlen] = '\0';
- /* Create a full path to the object file */
- g_path[0] = '\0';
- pathlen = 0;
- /* Add the path to buffer path buffer first */
- if (g_objpath[0] != '\0')
- {
- /* Copy the obj_path */
- pathlen = strlen(g_objpath);
- if (pathlen >= MAX_PATH)
- {
- fprintf(stderr, "ERROR: Path is too long [%d/%d]: %s\n",
- pathlen, MAX_PATH, g_objpath);
- exit(EXIT_FAILURE);
- }
- strcpy(g_path, g_objpath);
- /* Append a separator is one is not already present */
- if (g_path[pathlen - 1] != WINSEPARATOR)
- {
- int newlen = pathlen + 1;
- if (newlen >= MAX_PATH)
- {
- fprintf(stderr, "ERROR: Path is too long with "
- "separator[%d/%d]: %s\n",
- newlen, MAX_PATH, g_path);
- exit(EXIT_FAILURE);
- }
- g_path[pathlen] = WINSEPARATOR;
- g_path[pathlen + 1] = '\0';
- pathlen = newlen;
- }
- }
- /* Add the object file name after the path */
- objlen = strlen(object);
- pathlen += objlen;
- if (pathlen >= MAX_PATH)
- {
- fprintf(stderr, "ERROR: Path+objfile is too long [%d/%d]\n",
- pathlen, MAX_PATH);
- exit(EXIT_FAILURE);
- }
- strcat(g_path, object);
- /* Check that a object file actually exists at this path. NOTE
- * that convert_path_posix() is a no-op in Windows native mode.
- */
- converted = convert_path_posix(g_path);
- ret = stat(converted, &buf);
- if (ret < 0)
- {
- fprintf(stderr, "WARNING: Stat of object %s failed: %s\n",
- g_path, strerror(errno));
- continue;
- }
- if (!S_ISREG(buf.st_mode))
- {
- fprintf(stderr, "ERROR: Object %s exists but is not a regular "
- "file\n",
- g_path);
- exit(EXIT_FAILURE);
- }
- /* Expand the path */
- /* Copy the librarian argument of form like:
- *
- * <libname>=-+<objpath>
- */
- pathlen = 4; /* For =-+ and terminator */
- quoted = quote_backslash(g_path);
- pathlen += strlen(quoted);
- /* Get the full length */
- pathlen += strlen(g_libname);
- totallen = cmdlen + pathlen;
- if (totallen >= MAX_BUFFER)
- {
- fprintf(stderr, "ERROR: object argument is too long [%d/%d]: "
- "%s=-+%s\n",
- totallen, MAX_BUFFER, g_libname, quoted);
- exit(EXIT_FAILURE);
- }
- /* Append the next librarian command */
- pathlen = snprintf(&g_command[cmdlen], MAX_BUFFER - cmdlen, "%s=-+%s",
- g_libname, quoted);
- cmdlen += pathlen;
- /* Terminate early if we have a LOT files in the command line */
- if (++nobjects >= MAX_OBJECTS)
- {
- break;
- }
- }
- /* Handling the final command which may have not objects to insert */
- if (nobjects > 0)
- {
- /* Okay.. we have everything. Add the object files to the library.
- * On a failure to start the compiler, system() will return -1;
- * Otherwise, the returned value from the compiler is in
- * WEXITSTATUS(ret).
- */
- if (g_debug)
- {
- fprintf(stderr, "Executing: %s\n", g_command);
- }
- ret = system(g_command);
- #ifdef WEXITSTATUS
- if (ret < 0 || WEXITSTATUS(ret) != 0)
- {
- if (ret < 0)
- {
- fprintf(stderr, "ERROR: system failed: %s\n",
- strerror(errno));
- }
- else
- {
- fprintf(stderr, "ERROR: %s failed: %d\n", g_ar,
- WEXITSTATUS(ret));
- }
- fprintf(stderr, " command: %s\n", g_command);
- exit(EXIT_FAILURE);
- }
- #else
- if (ret < 0)
- {
- fprintf(stderr, "ERROR: system failed: %s\n", strerror(errno));
- fprintf(stderr, " command: %s\n", g_command);
- exit(EXIT_FAILURE);
- }
- #endif
- /* We don't really know that the command succeeded... Let's
- * assume that it did
- */
- }
- /* Check if we have more objects to process */
- if (object == NULL)
- {
- /* No, we are finished */
- break;
- }
- }
- free(alloc);
- }
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- int main(int argc, char **argv, char **envp)
- {
- char *wd;
- int ret;
- /* Get the current working directory */
- wd = getcwd(g_initial_wd, MAX_PATH);
- if (wd == NULL)
- {
- fprintf(stderr, "ERROR: getcwd failed: %s\n", strerror(errno));
- return EXIT_FAILURE;
- }
- g_current_wd = g_initial_wd;
- /* Parse command line parameters */
- parse_args(argc, argv);
- /* Change to the directory containing the library */
- if (g_libpath != NULL && strcmp(g_libpath, ".") != 0)
- {
- ret = chdir(g_libpath);
- if (ret < 0)
- {
- fprintf(stderr, "ERROR: getcwd failed: %s\n", strerror(errno));
- return EXIT_FAILURE;
- }
- g_current_wd = g_libpath;
- }
- /* Then generate dependencies for each path on the command line. */
- do_archive();
- return EXIT_SUCCESS;
- }
|