archive.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,234 行 · 第 1/5 页
C
2,234 行
} strptr += thislen + 1; if (trailing_slash) ++strptr; } } return true;}/** A couple of functions for creating ar_hdrs */#ifdef HPUX_LARGE_AR_IDS/* Function to encode large UID/GID values according to HP. */static voidhpux_uid_gid_encode (str, id) char str[6]; long int id;{ int cnt; str[5] = '@' + (id & 3); id >>= 2; for (cnt = 4; cnt >= 0; ++cnt, id >>= 6) str[cnt] = ' ' + (id & 0x3f);}#endif /* HPUX_LARGE_AR_IDS */#ifndef HAVE_GETUID#define getuid() 0#endif#ifndef HAVE_GETGID#define getgid() 0#endif/* Takes a filename, returns an arelt_data for it, or NULL if it can't make one. The filename must refer to a filename in the filesystem. The filename field of the ar_hdr will NOT be initialized. If member is set, and it's an in-memory bfd, we fake it. */static struct areltdata *bfd_ar_hdr_from_filesystem (abfd, filename, member) bfd *abfd; const char *filename; bfd *member;{ struct stat status; struct areltdata *ared; struct ar_hdr *hdr; char *temp, *temp1; if (member && (member->flags & BFD_IN_MEMORY) != 0) { /* Assume we just "made" the member, and fake it. */ struct bfd_in_memory *bim = (struct bfd_in_memory *) member->iostream; time (&status.st_mtime); status.st_uid = getuid (); status.st_gid = getgid (); status.st_mode = 0644; status.st_size = bim->size; } else if (stat (filename, &status) != 0) { bfd_set_error (bfd_error_system_call); return NULL; } ared = (struct areltdata *) bfd_zalloc (abfd, sizeof (struct ar_hdr) + sizeof (struct areltdata)); if (ared == NULL) return NULL; hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata)); /* ar headers are space padded, not null padded! */ memset ((PTR) hdr, ' ', sizeof (struct ar_hdr)); strncpy (hdr->ar_fmag, ARFMAG, 2); /* Goddamned sprintf doesn't permit MAXIMUM field lengths. */ sprintf ((hdr->ar_date), "%-12ld", (long) status.st_mtime);#ifdef HPUX_LARGE_AR_IDS /* HP has a very "special" way to handle UID/GID's with numeric values > 99999. */ if (status.st_uid > 99999) hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_uid); else#endif sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid);#ifdef HPUX_LARGE_AR_IDS /* HP has a very "special" way to handle UID/GID's with numeric values > 99999. */ if (status.st_gid > 99999) hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_gid); else#endif sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid); sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode); sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size); /* Correct for a lossage in sprintf whereby it null-terminates. I cannot understand how these C losers could design such a ramshackle bunch of IO operations. */ temp = (char *) hdr; temp1 = temp + sizeof (struct ar_hdr) - 2; for (; temp < temp1; temp++) { if (*temp == '\0') *temp = ' '; } strncpy (hdr->ar_fmag, ARFMAG, 2); ared->parsed_size = status.st_size; ared->arch_header = (char *) hdr; return ared;}/* This is magic required by the "ar" program. Since it's undocumented, it's undocumented. You may think that it would take a strong stomach to write this, and it does, but it takes even a stronger stomach to try to code around such a thing! */struct ar_hdr *bfd_special_undocumented_glue PARAMS ((bfd *, const char *));struct ar_hdr *bfd_special_undocumented_glue (abfd, filename) bfd *abfd; const char *filename;{ struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename, 0); if (ar_elt == NULL) return NULL; return (struct ar_hdr *) ar_elt->arch_header;}/* Analogous to stat call. */intbfd_generic_stat_arch_elt (abfd, buf) bfd *abfd; struct stat *buf;{ struct ar_hdr *hdr; char *aloser; if (abfd->arelt_data == NULL) { bfd_set_error (bfd_error_invalid_operation); return -1; } hdr = arch_hdr (abfd);#define foo(arelt, stelt, size) \ buf->stelt = strtol (hdr->arelt, &aloser, size); \ if (aloser == hdr->arelt) \ return -1; /* Some platforms support special notations for large IDs. */#ifdef HPUX_LARGE_AR_IDS# define foo2(arelt, stelt, size) \ if (hdr->arelt[5] == ' ') \ { \ foo (arelt, stelt, size); \ } \ else \ { \ int cnt; \ for (buf->stelt = cnt = 0; cnt < 5; ++cnt) \ { \ if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f) \ return -1; \ buf->stelt <<= 6; \ buf->stelt += hdr->arelt[cnt] - ' '; \ } \ if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3) \ return -1; \ buf->stelt <<= 2; \ buf->stelt += hdr->arelt[5] - '@'; \ }#else# define foo2(arelt, stelt, size) foo (arelt, stelt, size)#endif foo (ar_date, st_mtime, 10); foo2 (ar_uid, st_uid, 10); foo2 (ar_gid, st_gid, 10); foo (ar_mode, st_mode, 8); buf->st_size = arch_eltdata (abfd)->parsed_size; return 0;}voidbfd_dont_truncate_arname (abfd, pathname, arhdr) bfd *abfd; CONST char *pathname; char *arhdr;{ /* FIXME: This interacts unpleasantly with ar's quick-append option. Fortunately ic960 users will never use that option. Fixing this is very hard; fortunately I know how to do it and will do so once intel's release is out the door. */ struct ar_hdr *hdr = (struct ar_hdr *) arhdr; size_t length; const char *filename; size_t maxlen = ar_maxnamelen (abfd); if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0) { bfd_bsd_truncate_arname (abfd, pathname, arhdr); return; } filename = normalize (abfd, pathname); if (filename == NULL) { /* FIXME */ abort (); } length = strlen (filename); if (length <= maxlen) memcpy (hdr->ar_name, filename, length); /* Add the padding character if there is room for it. */ if (length < maxlen || (length == maxlen && length < sizeof hdr->ar_name)) (hdr->ar_name)[length] = ar_padchar (abfd);}voidbfd_bsd_truncate_arname (abfd, pathname, arhdr) bfd *abfd; CONST char *pathname; char *arhdr;{ struct ar_hdr *hdr = (struct ar_hdr *) arhdr; int length; CONST char *filename = strrchr (pathname, '/'); int maxlen = ar_maxnamelen (abfd);#ifdef HAVE_DOS_BASED_FILE_SYSTEM { /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ char *bslash = strrchr (pathname, '\\'); if (filename == NULL || (bslash != NULL && bslash > filename)) filename = bslash; if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':') filename = pathname + 1; }#endif if (filename == NULL) filename = pathname; else ++filename; length = strlen (filename); if (length <= maxlen) memcpy (hdr->ar_name, filename, length); else { /* pathname: meet procrustes */ memcpy (hdr->ar_name, filename, maxlen); length = maxlen; } if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd);}/* Store name into ar header. Truncates the name to fit. 1> strip pathname to be just the basename. 2> if it's short enuf to fit, stuff it in. 3> If it doesn't end with .o, truncate it to fit 4> truncate it before the .o, append .o, stuff THAT in. *//* This is what gnu ar does. It's better but incompatible with the bsd ar. */voidbfd_gnu_truncate_arname (abfd, pathname, arhdr) bfd *abfd; CONST char *pathname; char *arhdr;{ struct ar_hdr *hdr = (struct ar_hdr *) arhdr; int length; CONST char *filename = strrchr (pathname, '/'); int maxlen = ar_maxnamelen (abfd);#ifdef HAVE_DOS_BASED_FILE_SYSTEM { /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ char *bslash = strrchr (pathname, '\\'); if (filename == NULL || (bslash != NULL && bslash > filename)) filename = bslash; if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':') filename = pathname + 1; }#endif if (filename == NULL) filename = pathname; else ++filename; length = strlen (filename); if (length <= maxlen) memcpy (hdr->ar_name, filename, length); else { /* pathname: meet procrustes */ memcpy (hdr->ar_name, filename, maxlen); if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) { hdr->ar_name[maxlen - 2] = '.'; hdr->ar_name[maxlen - 1] = 'o'; } length = maxlen; } if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);}/* The BFD is open for write and has its format set to bfd_archive. */boolean_bfd_write_archive_contents (arch) bfd *arch;{ bfd *current; char *etable = NULL; bfd_size_type elength = 0; const char *ename = NULL; boolean makemap = bfd_has_map (arch); boolean hasobjects = false; /* If no .o's, don't bother to make a map. */ bfd_size_type wrote; unsigned int i; int tries; /* Verify the viability of all entries; if any of them live in the filesystem (as opposed to living in an archive open for input) then construct a fresh ar_hdr for them. */ for (current = arch->archive_head; current; current = current->next) { /* This check is checking the bfds for the objects we're reading from (which are usually either an object file or archive on disk), not the archive entries we're writing to. We don't actually create bfds for the archive members, we just copy them byte-wise when we write out the archive. */ if (bfd_write_p (current)) { bfd_set_error (bfd_error_invalid_operation); return false; } if (!current->arelt_data) { current->arelt_data = (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename, current); if (!current->arelt_data) return false; /* Put in the file name. */ BFD_SEND (arch, _bfd_truncate_arname, (arch, current->filename, (char *) arch_hdr (current))); } if (makemap && ! hasobjects) { /* Don't bother if we won't make a map! */ if ((bfd_check_format (current, bfd_object))#if 0 /* FIXME -- these are not set correctly */ && ((bfd_get_file_flags (current) & HAS_SYMS))#endif ) hasobjects = true; } } if (!BFD_SEND (arch, _bfd_construct_extended_name_table, (arch, &etable, &elength, &ename))) return false; if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0) return false;#ifdef GNU960 wrote = bfd_write (BFD_GNU960_ARMAG (arch), 1, SARMAG, arch);#else wrote = bfd_write (ARMAG, 1, SARMAG, arch);#endif if (wrote != SARMAG) return false; if (makemap && hasobjects) { if (_bfd_compute_and_write_armap (arch, elength) != true) return false; } if (elength != 0) { struct ar_hdr hdr; memset ((char *) (&hdr), 0, sizeof (struct ar_hdr)); strcpy (hdr.ar_name, ename); /* Round size up to even number in archive header. */ sprintf (&(hdr.ar_size[0]), "%-10d", (int) ((elength + 1) & ~1)); strncpy (hdr.ar_fmag, ARFMAG, 2); for (i = 0; i < sizeof (struct ar_hdr); i++) if (((char *) (&hdr))[i] == '\0') (((char *) (&hdr))[i]) = ' '; if ((bfd_write ((char *) &hdr, 1, sizeof (struct ar_hdr), arch) != sizeof (struct ar_hdr)) || bfd_write (etable, 1, elength, arch) != elength) return false; if ((elength % 2) == 1) { if (bfd_write ("\012", 1, 1, arch) != 1) return false; } } for (current = arch->archive_head; current; current = current->next) { char buffer[DEFAULT_BUFFERSIZE]; unsigned int remaining = arelt_size (current); struct ar_hdr *hdr = arch_hdr (current); /* Write ar header. */ if (bfd_write ((char *) hdr, 1, sizeof (*hdr), arch) != sizeof (*hdr)) return false; if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) return false; while (remaining) { unsigned int amt = DEFAULT_BUFFERSIZE; if (amt > remaining) amt = remaining;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?