/[gentoo-projects]/pax-utils/scanmacho.c
Gentoo

Diff of /pax-utils/scanmacho.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.11 Revision 1.20
1/* 1/*
2 * Copyright 2008 Gentoo Foundation 2 * Copyright 2008 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2 3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanmacho.c,v 1.11 2008/12/30 13:13:15 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/Attic/scanmacho.c,v 1.20 2010/12/08 01:16:01 vapier Exp $
5 * 5 *
6 * based on scanelf by: 6 * based on scanelf by:
7 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org> 7 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org>
8 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org> 8 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org>
9 * for Darwin specific fun: 9 * for Darwin specific fun:
10 * 2008 Fabian Groffen - <grobian@gentoo.org> 10 * 2008-2010 Fabian Groffen - <grobian@gentoo.org>
11 */ 11 */
12 12
13static const char *rcsid = "$Id: scanmacho.c,v 1.11 2008/12/30 13:13:15 vapier Exp $"; 13static const char *rcsid = "$Id: scanmacho.c,v 1.20 2010/12/08 01:16:01 vapier Exp $";
14const char * const argv0 = "scanmacho"; 14const char argv0[] = "scanmacho";
15 15
16#include "paxinc.h" 16#include "paxinc.h"
17 17
18#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+') 18#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+')
19 19
20/* prototypes */ 20/* prototypes */
21static int scanmacho_fatobj(fatobj *fobj); 21static int scanmacho_fatobj(fatobj *fobj);
22static int scanmacho_file(const char *filename, const struct stat *st_cache); 22static int scanmacho_file(const char *filename, const struct stat *st_cache);
23static int scanmacho_from_file(const char *filename); 23static int scanmacho_from_file(const char *filename);
24static int scanmacho_dir(const char *path); 24static int scanmacho_dir(const char *path);
25static void scanelf_envpath(void); 25static void scanmacho_envpath(void);
26static void usage(int status); 26static void usage(int status);
27static int parseargs(int argc, char *argv[]); 27static int parseargs(int argc, char *argv[]);
28 28
29/* variables to control behavior */ 29/* variables to control behavior */
30static char match_etypes[126] = ""; 30static char match_etypes[126] = "";
51static char g_match = 0; 51static char g_match = 0;
52 52
53static int match_bits = 0; 53static int match_bits = 0;
54static unsigned int match_perms = 0; 54static unsigned int match_perms = 0;
55 55
56static const char *getstr_perms(const char *fname)
57{
58 struct stat st;
59 static char buf[8];
60
61 if (stat(fname, &st) == -1)
62 return "";
63
64 snprintf(buf, sizeof(buf), "%o", st.st_mode);
65
66 return buf + 2;
67}
68
69static const char *macho_file_needed_lib( 56static const char *macho_file_needed_lib(
70 fatobj *fobj, 57 fatobj *fobj,
71 char *found_needed, 58 char *found_needed,
72 char *found_lib, 59 char *found_lib,
73 int op, 60 int op,
74 char **ret, 61 char **ret,
75 size_t *ret_len 62 size_t *ret_len
76) { 63) {
77 char *needed;
78 loadcmd *lcmd; 64 loadcmd *lcmd;
79 struct dylib_command *dlcmd;
80 uint32_t lc_load_dylib = LC_LOAD_DYLIB; 65 uint32_t lc_load_dylib;
81 66
82 if ((op == 0 && !show_needed) || (op == 1 && !find_lib)) 67 if ((op == 0 && !show_needed) || (op == 1 && !find_lib))
83 return NULL; 68 return NULL;
84 69
85 lcmd = firstloadcmd(fobj); 70 lcmd = firstloadcmd(fobj);
86 71 lc_load_dylib = MGET(fobj->swapped, LC_LOAD_DYLIB);
87 if (fobj->swapped)
88 lc_load_dylib = bswap_32(lc_load_dylib);
89 72
90 do { 73 do {
91 if (lcmd->lcmd->cmd == lc_load_dylib) { 74 if (lcmd->lcmd->cmd == lc_load_dylib) {
92 dlcmd = (struct dylib_command*)lcmd->data; 75 struct dylib_command *dlcmd = lcmd->data;
93 if (fobj->swapped) { 76 char *needed;
94 needed = (char *)(lcmd->data +
95 bswap_32(dlcmd->dylib.name.offset));
96 } else {
97 needed = (char *)(lcmd->data + dlcmd->dylib.name.offset); 77 needed = lcmd->data + MGET(fobj->swapped, dlcmd->dylib.name.offset);
98 }
99 if (op == 0) { 78 if (op == 0) {
100 if (!be_wewy_wewy_quiet) { 79 if (!be_wewy_wewy_quiet) {
101 if (*found_needed) 80 if (*found_needed)
102 xchrcat(ret, ',', ret_len); 81 xchrcat(ret, ',', ret_len);
103 xstrcat(ret, needed, ret_len); 82 xstrcat(ret, needed, ret_len);
122} 101}
123 102
124static char *macho_file_interp(fatobj *fobj, char *found_interp) 103static char *macho_file_interp(fatobj *fobj, char *found_interp)
125{ 104{
126 loadcmd *lcmd; 105 loadcmd *lcmd;
127 uint32_t lc_load_dylinker = LC_LOAD_DYLINKER; 106 uint32_t lc_load_dylinker;
128 107
129 if (!show_interp) 108 if (!show_interp)
130 return NULL; 109 return NULL;
131 110
132 lcmd = firstloadcmd(fobj); 111 lcmd = firstloadcmd(fobj);
133 112 lc_load_dylinker = MGET(fobj->swapped, LC_LOAD_DYLINKER);
134 if (fobj->swapped)
135 lc_load_dylinker = bswap_32(lc_load_dylinker);
136 113
137 do { 114 do {
138 if (lcmd->lcmd->cmd == lc_load_dylinker) { 115 if (lcmd->lcmd->cmd == lc_load_dylinker) {
139 struct dylinker_command *dlcmd =
140 (struct dylinker_command*)lcmd->data; 116 struct dylinker_command *dlcmd = lcmd->data;
141 char *dylinker; 117 char *dylinker;
142 if (fobj->swapped) {
143 dylinker = (char *)(lcmd->data +
144 bswap_32(dlcmd->name.offset));
145 } else {
146 dylinker = (char *)(lcmd->data + dlcmd->name.offset); 118 dylinker = lcmd->data + MGET(fobj->swapped, dlcmd->name.offset);
147 }
148 *found_interp = 1; 119 *found_interp = 1;
149 free(lcmd); 120 free(lcmd);
150 return (be_wewy_wewy_quiet ? NULL : dylinker); 121 return (be_wewy_wewy_quiet ? NULL : dylinker);
151 } 122 }
152 } while (nextloadcmd(lcmd)); 123 } while (nextloadcmd(lcmd));
155} 126}
156 127
157static char *macho_file_soname(fatobj *fobj, char *found_soname) 128static char *macho_file_soname(fatobj *fobj, char *found_soname)
158{ 129{
159 loadcmd *lcmd; 130 loadcmd *lcmd;
160 char *soname;
161 uint32_t lc_id_dylib = LC_ID_DYLIB; 131 uint32_t lc_id_dylib;
162 132
163 if (!show_soname) 133 if (!show_soname)
164 return NULL; 134 return NULL;
165 135
166 lcmd = firstloadcmd(fobj); 136 lcmd = firstloadcmd(fobj);
167 137 lc_id_dylib = MGET(fobj->swapped, LC_ID_DYLIB);
168 if (fobj->swapped)
169 lc_id_dylib = bswap_32(lc_id_dylib);
170 138
171 do { 139 do {
172 if (lcmd->lcmd->cmd == lc_id_dylib) { 140 if (lcmd->lcmd->cmd == lc_id_dylib) {
173 struct dylib_command *dlcmd = (struct dylib_command*)lcmd->data; 141 struct dylib_command *dlcmd = lcmd->data;
174 if (fobj->swapped) { 142 char *soname;
175 soname = (char *)(lcmd->data +
176 bswap_32(dlcmd->dylib.name.offset));
177 } else {
178 soname = (char *)(lcmd->data + dlcmd->dylib.name.offset); 143 soname = lcmd->data + MGET(fobj->swapped, dlcmd->dylib.name.offset);
179 }
180 *found_soname = 1; 144 *found_soname = 1;
181 free(lcmd); 145 free(lcmd);
182 return (be_wewy_wewy_quiet ? NULL : soname); 146 return (be_wewy_wewy_quiet ? NULL : soname);
183 } 147 }
184 } while (nextloadcmd(lcmd)); 148 } while (nextloadcmd(lcmd));
185 149
186 return NULL; 150 return NULL;
187} 151}
188 152
189/* scan a macho file and show all the fun stuff */ 153/* scan a macho file and show all the fun stuff */
190#define prints(str) write(fileno(stdout), str, strlen(str)) 154#define prints(str) ({ ssize_t ret = write(fileno(stdout), str, strlen(str)); ret; })
191static int scanmacho_fatobj(fatobj *fobj) 155static int scanmacho_fatobj(fatobj *fobj)
192{ 156{
193 unsigned long i; 157 unsigned long i;
194 char found_needed, found_interp, found_soname, found_lib, found_file; 158 char found_needed, found_interp, found_soname, found_lib, found_file;
195 static char *out_buffer = NULL; 159 static char *out_buffer = NULL;
287 xstrcat(&out_buffer, fobj->base_filename, &out_len); 251 xstrcat(&out_buffer, fobj->base_filename, &out_len);
288 break; 252 break;
289 case 'o': out = get_machomhtype(fobj); break; 253 case 'o': out = get_machomhtype(fobj); break;
290 case 'M': out = get_machocputype(fobj); break; 254 case 'M': out = get_machocputype(fobj); break;
291 case 'D': out = get_machoendian(fobj); break; 255 case 'D': out = get_machoendian(fobj); break;
292 case 'O': out = getstr_perms(fobj->filename); break; 256 case 'O': out = strfileperms(fobj->filename); break;
293 case 'n': 257 case 'n':
294 case 'N': out = macho_file_needed_lib(fobj, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break; 258 case 'N': out = macho_file_needed_lib(fobj, &found_needed, &found_lib, (out_format[i]=='N'), &out_buffer, &out_len); break;
295 case 'i': out = macho_file_interp(fobj, &found_interp); break; 259 case 'i': out = macho_file_interp(fobj, &found_interp); break;
296 case 'b': get_machomhflags(fobj, &out_buffer, &out_len); break; 260 case 'b': get_machomhflags(fobj, &out_buffer, &out_len); break;
297 case 'S': out = macho_file_soname(fobj, &found_soname); break; 261 case 'S': out = macho_file_soname(fobj, &found_soname); break;
456 if (be_verbose > 2) printf("%s: does not exist\n", path); 420 if (be_verbose > 2) printf("%s: does not exist\n", path);
457 return 1; 421 return 1;
458 } 422 }
459 423
460 /* ok, if it isn't a directory, assume we can open it */ 424 /* ok, if it isn't a directory, assume we can open it */
461 if (!S_ISDIR(st_top.st_mode)) { 425 if (!S_ISDIR(st_top.st_mode))
462 return scanmacho_file(path, &st_top); 426 return scanmacho_file(path, &st_top);
463 }
464 427
465 /* now scan the dir looking for fun stuff */ 428 /* now scan the dir looking for fun stuff */
466 if ((dir = opendir(path)) == NULL) { 429 if ((dir = opendir(path)) == NULL) {
467 warnf("could not opendir %s: %s", path, strerror(errno)); 430 warnf("could not opendir %s: %s", path, strerror(errno));
468 return 1; 431 return 1;
515 fclose(fp); 478 fclose(fp);
516 return ret; 479 return ret;
517} 480}
518 481
519/* scan env PATH for paths */ 482/* scan env PATH for paths */
520static void scanelf_envpath(void) 483static void scanmacho_envpath(void)
521{ 484{
522 char *path, *p; 485 char *path, *p;
523 486
524 path = getenv("PATH"); 487 path = getenv("PATH");
525 if (!path) 488 if (!path)
532 } 495 }
533 496
534 free(path); 497 free(path);
535} 498}
536 499
537/* usage / invocation handling functions */ /* Free Flags: c d e j k l r s t u w x z C G H I J K L P Q T U W X Y */ 500/* usage / invocation handling functions */ /* Free Flags: c d e j k l r s t u w x z G H I J K L P Q T U W X Y */
538#define PARSE_FLAGS "pRmyAnibSN:gE:M:DO:ZaqvF:f:o:BhV" 501#define PARSE_FLAGS "pRmyAnibSN:gE:M:DO:ZaqvF:f:o:CBhV"
539#define a_argument required_argument 502#define a_argument required_argument
540static struct option const long_opts[] = { 503static struct option const long_opts[] = {
541 {"path", no_argument, NULL, 'p'}, 504 {"path", no_argument, NULL, 'p'},
542 {"recursive", no_argument, NULL, 'R'}, 505 {"recursive", no_argument, NULL, 'R'},
543 {"mount", no_argument, NULL, 'm'}, 506 {"mount", no_argument, NULL, 'm'},
558 {"quiet", no_argument, NULL, 'q'}, 521 {"quiet", no_argument, NULL, 'q'},
559 {"verbose", no_argument, NULL, 'v'}, 522 {"verbose", no_argument, NULL, 'v'},
560 {"format", a_argument, NULL, 'F'}, 523 {"format", a_argument, NULL, 'F'},
561 {"from", a_argument, NULL, 'f'}, 524 {"from", a_argument, NULL, 'f'},
562 {"file", a_argument, NULL, 'o'}, 525 {"file", a_argument, NULL, 'o'},
526 {"nocolor", no_argument, NULL, 'C'},
563 {"nobanner", no_argument, NULL, 'B'}, 527 {"nobanner", no_argument, NULL, 'B'},
564 {"help", no_argument, NULL, 'h'}, 528 {"help", no_argument, NULL, 'h'},
565 {"version", no_argument, NULL, 'V'}, 529 {"version", no_argument, NULL, 'V'},
566 {NULL, no_argument, NULL, 0x0} 530 {NULL, no_argument, NULL, 0x0}
567}; 531};
569static const char *opts_help[] = { 533static const char *opts_help[] = {
570 "Scan all directories in PATH environment", 534 "Scan all directories in PATH environment",
571 "Scan directories recursively", 535 "Scan directories recursively",
572 "Don't recursively cross mount points", 536 "Don't recursively cross mount points",
573 "Don't scan symlinks", 537 "Don't scan symlinks",
574 "Scan archives (.a files)", 538 "Scan archives (.a files)\n",
575 "Print LC_LOAD_DYLIB information (ELF: NEEDED)", 539 "Print LC_LOAD_DYLIB information (ELF: NEEDED)",
576 "Print LC_LOAD_DYLINKER information (ELF: INTERP)", 540 "Print LC_LOAD_DYLINKER information (ELF: INTERP)",
577 "Print flags from mach_header (ELF: BIND)", 541 "Print flags from mach_header (ELF: BIND)",
578 "Print LC_ID_DYLIB information (ELF: SONAME)", 542 "Print LC_ID_DYLIB information (ELF: SONAME)",
579 "Find a specified library", 543 "Find a specified library",
582 " MH_OBJECT,MH_EXECUTE ... (ELF: etype)", 546 " MH_OBJECT,MH_EXECUTE ... (ELF: etype)",
583 "Print only Mach-O files matching numeric bits", 547 "Print only Mach-O files matching numeric bits",
584 "Print Endianness", 548 "Print Endianness",
585 "Print only Mach-O files matching octal permissions", 549 "Print only Mach-O files matching octal permissions",
586 "Print Mach-O file size", 550 "Print Mach-O file size",
587 "Print all scanned info (-F\"%o %O %D %b %F\")\n", 551 "Print all useful/simple info\n",
588 "Only output 'bad' things", 552 "Only output 'bad' things",
589 "Be verbose (can be specified more than once)", 553 "Be verbose (can be specified more than once)",
590 "Use specified format for output", 554 "Use specified format for output",
591 "Read input stream from a filename", 555 "Read input stream from a filename",
592 "Write output stream to a filename", 556 "Write output stream to a filename",
557 "Don't emit color in output",
593 "Don't display the header", 558 "Don't display the header",
594 "Print this help and exit", 559 "Print this help and exit",
595 "Print version and exit", 560 "Print version and exit",
596 NULL 561 NULL
597}; 562};
664 } 629 }
665 case 'Z': show_size = 1; break; 630 case 'Z': show_size = 1; break;
666 case 'g': g_match = 1; break; 631 case 'g': g_match = 1; break;
667 case 'y': scan_symlink = 0; break; 632 case 'y': scan_symlink = 0; break;
668 case 'A': scan_archives = 1; break; 633 case 'A': scan_archives = 1; break;
634 case 'C': color_init(true); break;
669 case 'B': show_banner = 0; break; 635 case 'B': show_banner = 0; break;
670 case 'p': scan_envpath = 1; break; 636 case 'p': scan_envpath = 1; break;
671 case 'R': dir_recurse = 1; break; 637 case 'R': dir_recurse = 1; break;
672 case 'm': dir_crossmount = 0; break; 638 case 'm': dir_crossmount = 0; break;
673 case 'n': show_needed = 1; break; 639 case 'n': show_needed = 1; break;
737 } 703 }
738 if (be_verbose > 2) printf("Format: %s\n", out_format); 704 if (be_verbose > 2) printf("Format: %s\n", out_format);
739 705
740 /* now lets actually do the scanning */ 706 /* now lets actually do the scanning */
741 if (scan_envpath) 707 if (scan_envpath)
742 scanelf_envpath(); 708 scanmacho_envpath();
743 if (!from_file && optind == argc && ttyname(0) == NULL && !scan_envpath) 709 if (!from_file && optind == argc && ttyname(0) == NULL && !scan_envpath)
744 from_file = "-"; 710 from_file = "-";
745 if (from_file) { 711 if (from_file) {
746 scanmacho_from_file(from_file); 712 scanmacho_from_file(from_file);
747 from_file = *argv; 713 from_file = *argv;
759int main(int argc, char *argv[]) 725int main(int argc, char *argv[])
760{ 726{
761 int ret; 727 int ret;
762 if (argc < 2) 728 if (argc < 2)
763 usage(EXIT_FAILURE); 729 usage(EXIT_FAILURE);
730 color_init(false);
764 ret = parseargs(argc, argv); 731 ret = parseargs(argc, argv);
765 fclose(stdout); 732 fclose(stdout);
766 return ret; 733 return ret;
767} 734}

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.20

  ViewVC Help
Powered by ViewVC 1.1.20