1 /* $OpenBSD: mlinks.c,v 1.3 2016/11/05 16:43:50 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * Some operating systems need MLINKS for pages with more than one name. 18 * Extract these in a format suitable for portable LibreSSL. 19 */ 20 #include <err.h> 21 #include <regex.h> 22 #include <stdint.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 #include "dbm_map.h" 27 #include "dbm.h" 28 29 int 30 main(int argc, char *argv[]) 31 { 32 const int32_t *pp; /* Page record in the pages table. */ 33 const char *np; /* Names of the page. */ 34 const char *fp; /* Primary filename of the page. */ 35 const char *ep; /* Filname extension including the dot. */ 36 size_t flen, nlen; 37 int32_t i, npages; 38 39 if (argc != 2) 40 errx(1, "usage: mlinks filename"); 41 42 if (dbm_open(argv[1]) == -1) 43 err(1, "%s", argv[1]); 44 45 pp = dbm_getint(4); 46 npages = be32toh(*pp++); 47 if (npages <= 0) 48 errx(1, "database empty or corrupt: %d pages", npages); 49 50 for (i = 0; i < npages; i++, pp += 5) { 51 np = dbm_get(pp[0]); 52 if (np == NULL) 53 errx(1, "database corrupt: bad name pointer"); 54 55 /* Skip files with just one name. */ 56 if (strchr(np, '\0')[1] == '\0') 57 continue; 58 59 fp = dbm_get(pp[4]); 60 if (fp == NULL) 61 errx(1, "database corrupt: bad file pointer"); 62 63 /* Skip the file type byte. */ 64 fp++; 65 66 /* Skip directory parts of filenames. */ 67 ep = strrchr(fp, '/'); 68 if (ep != NULL) 69 fp = ep + 1; 70 71 ep = strrchr(fp, '.'); 72 if (ep == NULL) 73 errx(1, "no filename extension: %s", fp); 74 flen = ep - fp; 75 76 while (*np != '\0') { 77 78 /* Skip the name type byte. */ 79 np++; 80 81 /* Skip the primary filename. */ 82 nlen = strlen(np); 83 if (nlen == flen && strncmp(fp, np, nlen) == 0) { 84 np = strchr(np, '\0') + 1; 85 continue; 86 } 87 88 /* Describe the desired mlink. */ 89 printf("%s,", fp); 90 while (*np != '\0') 91 putchar(*np++); 92 np++; 93 puts(ep); 94 } 95 } 96 dbm_close(); 97 return 0; 98 } 99