1*a0ed5030SJason King /* 2*a0ed5030SJason King * This file and its contents are supplied under the terms of the 3*a0ed5030SJason King * Common Development and Distribution License ("CDDL"), version 1.0. 4*a0ed5030SJason King * You may only use this file in accordance with the terms of version 5*a0ed5030SJason King * 1.0 of the CDDL. 6*a0ed5030SJason King * 7*a0ed5030SJason King * A full copy of the text of the CDDL should have accompanied this 8*a0ed5030SJason King * source. A copy of the CDDL is also available via the Internet at 9*a0ed5030SJason King * http://www.illumos.org/license/CDDL. 10*a0ed5030SJason King */ 11*a0ed5030SJason King 12*a0ed5030SJason King /* 13*a0ed5030SJason King * Copyright 2011 Jason King. All rights reserved. 14*a0ed5030SJason King */ 15*a0ed5030SJason King 16*a0ed5030SJason King #include <stdlib.h> 17*a0ed5030SJason King #include <stdio.h> 18*a0ed5030SJason King #include <string.h> 19*a0ed5030SJason King #include <unistd.h> 20*a0ed5030SJason King #include <sys/types.h> 21*a0ed5030SJason King #include <sys/stat.h> 22*a0ed5030SJason King #include <sys/wait.h> 23*a0ed5030SJason King #include <fcntl.h> 24*a0ed5030SJason King #include <err.h> 25*a0ed5030SJason King #include <spawn.h> 26*a0ed5030SJason King 27*a0ed5030SJason King #define MCS "/usr/bin/mcs" 28*a0ed5030SJason King 29*a0ed5030SJason King #define ELFLEN 4 30*a0ed5030SJason King static const char elf_signature[] = "\177ELF"; 31*a0ed5030SJason King static posix_spawnattr_t attr; 32*a0ed5030SJason King static const char *cmd[] = { MCS, "-d", "-n", ".SUNW_ctf", NULL, NULL }; 33*a0ed5030SJason King 34*a0ed5030SJason King extern char **environ; 35*a0ed5030SJason King 36*a0ed5030SJason King static boolean_t check_file(const char *, mode_t *); 37*a0ed5030SJason King static boolean_t fix_file(const char *, mode_t); 38*a0ed5030SJason King static void usage(const char *); 39*a0ed5030SJason King 40*a0ed5030SJason King int 41*a0ed5030SJason King main(int argc, const char **argv) 42*a0ed5030SJason King { 43*a0ed5030SJason King const char **p; 44*a0ed5030SJason King int rc = 0; 45*a0ed5030SJason King mode_t mode; 46*a0ed5030SJason King 47*a0ed5030SJason King if (argc < 2) 48*a0ed5030SJason King usage(argv[0]); 49*a0ed5030SJason King 50*a0ed5030SJason King rc = posix_spawnattr_init(&attr); 51*a0ed5030SJason King if (rc != 0) { 52*a0ed5030SJason King errx(EXIT_FAILURE, "Spawn attribute initialization failed: %s", 53*a0ed5030SJason King strerror(rc)); 54*a0ed5030SJason King } 55*a0ed5030SJason King 56*a0ed5030SJason King for (p = argv + 1; *p != NULL; p++) { 57*a0ed5030SJason King if (!check_file(*p, &mode)) 58*a0ed5030SJason King continue; 59*a0ed5030SJason King if (!fix_file(*p, mode)) 60*a0ed5030SJason King rc = 1; 61*a0ed5030SJason King } 62*a0ed5030SJason King 63*a0ed5030SJason King return (rc); 64*a0ed5030SJason King } 65*a0ed5030SJason King 66*a0ed5030SJason King static boolean_t 67*a0ed5030SJason King check_file(const char *filename, mode_t *mode) 68*a0ed5030SJason King { 69*a0ed5030SJason King char elfbuf[4]; 70*a0ed5030SJason King struct stat sb; 71*a0ed5030SJason King int fd; 72*a0ed5030SJason King 73*a0ed5030SJason King fd = open(filename, O_RDONLY); 74*a0ed5030SJason King if (fd == -1) { 75*a0ed5030SJason King warn("Unable to open %s", filename); 76*a0ed5030SJason King return (B_FALSE); 77*a0ed5030SJason King } 78*a0ed5030SJason King 79*a0ed5030SJason King if (fstat(fd, &sb) == -1) { 80*a0ed5030SJason King warn("stat(2) failed on %s", filename); 81*a0ed5030SJason King (void) close(fd); 82*a0ed5030SJason King return (B_FALSE); 83*a0ed5030SJason King } 84*a0ed5030SJason King 85*a0ed5030SJason King if (!S_ISREG(sb.st_mode)) { 86*a0ed5030SJason King warnx("%s is not a regular file", filename); 87*a0ed5030SJason King (void) close(fd); 88*a0ed5030SJason King return (B_FALSE); 89*a0ed5030SJason King } 90*a0ed5030SJason King 91*a0ed5030SJason King if (sb.st_size < ELFLEN) { 92*a0ed5030SJason King warnx("%s is not an ELF file", filename); 93*a0ed5030SJason King (void) close(fd); 94*a0ed5030SJason King return (B_FALSE); 95*a0ed5030SJason King } 96*a0ed5030SJason King 97*a0ed5030SJason King if (read(fd, elfbuf, ELFLEN) != ELFLEN) { 98*a0ed5030SJason King warn("Error reading %s", filename); 99*a0ed5030SJason King (void) close(fd); 100*a0ed5030SJason King return (B_FALSE); 101*a0ed5030SJason King } 102*a0ed5030SJason King 103*a0ed5030SJason King if (strncmp(elfbuf, elf_signature, ELFLEN) != 0) { 104*a0ed5030SJason King warnx("%s is not an ELF file", filename); 105*a0ed5030SJason King (void) close(fd); 106*a0ed5030SJason King return (B_FALSE); 107*a0ed5030SJason King } 108*a0ed5030SJason King 109*a0ed5030SJason King *mode = sb.st_mode & S_IAMB; 110*a0ed5030SJason King (void) close(fd); 111*a0ed5030SJason King return (B_TRUE); 112*a0ed5030SJason King } 113*a0ed5030SJason King 114*a0ed5030SJason King static boolean_t 115*a0ed5030SJason King fix_file(const char *filename, mode_t mode) 116*a0ed5030SJason King { 117*a0ed5030SJason King pid_t pid; 118*a0ed5030SJason King int i, rc; 119*a0ed5030SJason King int stat = 0; 120*a0ed5030SJason King 121*a0ed5030SJason King if ((mode & S_IWUSR) == 0) { 122*a0ed5030SJason King if (chmod(filename, mode | S_IWUSR) == -1) { 123*a0ed5030SJason King warn("failed to make %s writable", filename); 124*a0ed5030SJason King return (B_FALSE); 125*a0ed5030SJason King } 126*a0ed5030SJason King } 127*a0ed5030SJason King 128*a0ed5030SJason King cmd[4] = filename; 129*a0ed5030SJason King if ((rc = posix_spawn(&pid, MCS, NULL, &attr, 130*a0ed5030SJason King (char *const *)cmd, environ)) != 0) { 131*a0ed5030SJason King warnx("could not exec mcs: %s", strerror(rc)); 132*a0ed5030SJason King return (B_FALSE); 133*a0ed5030SJason King } 134*a0ed5030SJason King 135*a0ed5030SJason King waitpid(pid, &stat, 0); 136*a0ed5030SJason King if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) { 137*a0ed5030SJason King warnx("Removing CTF information from %s failed", filename); 138*a0ed5030SJason King return (B_FALSE); 139*a0ed5030SJason King } 140*a0ed5030SJason King 141*a0ed5030SJason King if ((mode & S_IWUSR) == 0) { 142*a0ed5030SJason King if (chmod(filename, mode) == -1) { 143*a0ed5030SJason King warn("could not reset permissions of %s", filename); 144*a0ed5030SJason King return (B_FALSE); 145*a0ed5030SJason King } 146*a0ed5030SJason King } 147*a0ed5030SJason King 148*a0ed5030SJason King return (B_TRUE); 149*a0ed5030SJason King } 150*a0ed5030SJason King 151*a0ed5030SJason King static void 152*a0ed5030SJason King usage(const char *name) 153*a0ed5030SJason King { 154*a0ed5030SJason King (void) fprintf(stderr, "Usage: %s file...\n", name); 155*a0ed5030SJason King exit(EXIT_FAILURE); 156*a0ed5030SJason King } 157