1/* Authors: Karl MacMillan <kmacmillan@tresys.com> 2 * 3 * Copyright (C) 2004 Tresys Technology, LLC 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, version 2. 7 */ 8 9#include <sepol/module.h> 10 11#include <getopt.h> 12#include <fcntl.h> 13#include <stdio.h> 14#include <errno.h> 15#include <sys/mman.h> 16#include <sys/types.h> 17#include <sys/stat.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <string.h> 21 22#define LINKPOLICY_VERSION "1.0" 23 24char *progname; 25extern char *optarg; 26extern int optind; 27 28static void usage(char *program_name) 29{ 30 printf("usage: %s [-Vv] [-o outfile] basemodpkg modpkg1 [modpkg2]...\n", 31 program_name); 32 exit(1); 33} 34 35static sepol_module_package_t *load_module(char *filename) 36{ 37 int ret; 38 FILE *fp = NULL; 39 struct sepol_policy_file *pf = NULL; 40 sepol_module_package_t *p = NULL; 41 42 if (sepol_module_package_create(&p)) { 43 fprintf(stderr, "%s: Out of memory\n", progname); 44 goto bad; 45 } 46 if (sepol_policy_file_create(&pf)) { 47 fprintf(stderr, "%s: Out of memory\n", progname); 48 goto bad; 49 } 50 fp = fopen(filename, "r"); 51 if (!fp) { 52 fprintf(stderr, "%s: Could not open package %s: %s", progname, 53 filename, strerror(errno)); 54 goto bad; 55 } 56 sepol_policy_file_set_fp(pf, fp); 57 58 printf("%s: loading package from file %s\n", progname, filename); 59 60 ret = sepol_module_package_read(p, pf, 0); 61 if (ret) { 62 fprintf(stderr, "%s: Error while reading package from %s\n", 63 progname, filename); 64 goto bad; 65 } 66 fclose(fp); 67 sepol_policy_file_free(pf); 68 return p; 69 bad: 70 sepol_module_package_free(p); 71 sepol_policy_file_free(pf); 72 if (fp) 73 fclose(fp); 74 return NULL; 75} 76 77int main(int argc, char **argv) 78{ 79 int ch, i, show_version = 0, verbose = 0, num_mods; 80 char *basename, *outname = NULL; 81 sepol_module_package_t *base, **mods; 82 FILE *outfile; 83 struct sepol_policy_file *pf; 84 85 progname = argv[0]; 86 87 while ((ch = getopt(argc, argv, "o:Vv")) != EOF) { 88 switch (ch) { 89 case 'V': 90 show_version = 1; 91 break; 92 case 'v': 93 verbose = 1; 94 break; 95 case 'o': 96 outname = optarg; 97 break; 98 default: 99 usage(argv[0]); 100 } 101 } 102 103 if (show_version) { 104 printf("%s\n", LINKPOLICY_VERSION); 105 exit(0); 106 } 107 108 /* check args */ 109 if (argc < 3 || !(optind != (argc - 1))) { 110 fprintf(stderr, 111 "%s: You must provide the base module package and at least one other module package\n", 112 argv[0]); 113 usage(argv[0]); 114 } 115 116 basename = argv[optind++]; 117 base = load_module(basename); 118 if (!base) { 119 fprintf(stderr, 120 "%s: Could not load base module from file %s\n", 121 argv[0], basename); 122 exit(1); 123 } 124 125 num_mods = argc - optind; 126 mods = 127 (sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *) 128 * num_mods); 129 if (!mods) { 130 fprintf(stderr, "%s: Out of memory\n", argv[0]); 131 exit(1); 132 } 133 memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods); 134 135 for (i = 0; optind < argc; optind++, i++) { 136 mods[i] = load_module(argv[optind]); 137 if (!mods[i]) { 138 fprintf(stderr, 139 "%s: Could not load module from file %s\n", 140 argv[0], argv[optind]); 141 exit(1); 142 } 143 } 144 145 if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) { 146 fprintf(stderr, "%s: Error while linking packages\n", argv[0]); 147 exit(1); 148 } 149 150 if (outname) { 151 outfile = fopen(outname, "w"); 152 if (!outfile) { 153 perror(outname); 154 exit(1); 155 } 156 157 if (sepol_policy_file_create(&pf)) { 158 fprintf(stderr, "%s: Out of memory\n", argv[0]); 159 exit(1); 160 } 161 sepol_policy_file_set_fp(pf, outfile); 162 if (sepol_module_package_write(base, pf)) { 163 fprintf(stderr, "%s: Error writing linked package.\n", 164 argv[0]); 165 exit(1); 166 } 167 sepol_policy_file_free(pf); 168 fclose(outfile); 169 } 170 171 sepol_module_package_free(base); 172 for (i = 0; i < num_mods; i++) 173 sepol_module_package_free(mods[i]); 174 free(mods); 175 exit(0); 176} 177