1/* 2 Copyright (c) 2010 Frank Lahm <franklahm@gmail.com> 3 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; either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13*/ 14 15#ifdef HAVE_CONFIG_H 16#include "config.h" 17#endif /* HAVE_CONFIG_H */ 18 19#include <unistd.h> 20#include <sys/types.h> 21#include <stdlib.h> 22#include <stdio.h> 23#include <stdarg.h> 24#include <limits.h> 25#include <string.h> 26#include <errno.h> 27 28#include <atalk/adouble.h> 29#include <atalk/cnid.h> 30#include <atalk/cnid_dbd_private.h> 31#include <atalk/volinfo.h> 32#include <atalk/bstrlib.h> 33#include <atalk/bstradd.h> 34#include <atalk/directory.h> 35#include <atalk/util.h> 36#include <atalk/unicode.h> 37#include "ad.h" 38 39static volatile sig_atomic_t alarmed; 40 41/* 42 SIGNAL handling: 43 catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. 44*/ 45 46static void sig_handler(int signo) 47{ 48 alarmed = 1; 49 return; 50} 51 52static void set_signal(void) 53{ 54 struct sigaction sv; 55 56 sv.sa_handler = sig_handler; 57 sv.sa_flags = SA_RESTART; 58 sigemptyset(&sv.sa_mask); 59 if (sigaction(SIGTERM, &sv, NULL) < 0) 60 ERROR("error in sigaction(SIGTERM): %s", strerror(errno)); 61 62 if (sigaction(SIGINT, &sv, NULL) < 0) 63 ERROR("error in sigaction(SIGINT): %s", strerror(errno)); 64 65 memset(&sv, 0, sizeof(struct sigaction)); 66 sv.sa_handler = SIG_IGN; 67 sigemptyset(&sv.sa_mask); 68 69 if (sigaction(SIGABRT, &sv, NULL) < 0) 70 ERROR("error in sigaction(SIGABRT): %s", strerror(errno)); 71 72 if (sigaction(SIGHUP, &sv, NULL) < 0) 73 ERROR("error in sigaction(SIGHUP): %s", strerror(errno)); 74 75 if (sigaction(SIGQUIT, &sv, NULL) < 0) 76 ERROR("error in sigaction(SIGQUIT): %s", strerror(errno)); 77} 78 79static void usage_find(void) 80{ 81 printf( 82 "Usage: ad find [-v VOLUME_PATH] NAME\n" 83 ); 84} 85 86int ad_find(int argc, char **argv) 87{ 88 int c, ret; 89 afpvol_t vol; 90 const char *srchvol = getcwdpath(); 91 92 while ((c = getopt(argc-1, &argv[1], ":v:")) != -1) { 93 switch(c) { 94 case 'v': 95 srchvol = strdup(optarg); 96 break; 97 case ':': 98 case '?': 99 usage_find(); 100 return -1; 101 break; 102 } 103 104 } 105 optind++; 106 107 if ((argc - optind) != 1) { 108 usage_find(); 109 exit(1); 110 } 111 112 set_signal(); 113 cnid_init(); 114 115 if (openvol(srchvol, &vol) != 0) 116 ERROR("Cant open volume \"%s\"", srchvol); 117 118 uint16_t flags = CONV_TOLOWER; 119 char namebuf[MAXPATHLEN + 1]; 120 if (convert_charset(vol.volinfo.v_volcharset, 121 vol.volinfo.v_volcharset, 122 vol.volinfo.v_maccharset, 123 argv[optind], 124 strlen(argv[optind]), 125 namebuf, 126 MAXPATHLEN, 127 &flags) == (size_t)-1) { 128 ERROR("conversion error"); 129 } 130 131 int count; 132 char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)]; 133 if ((count = cnid_find(vol.volume.v_cdb, 134 namebuf, 135 strlen(namebuf), 136 resbuf, 137 sizeof(resbuf))) < 1) { 138 ret = 1; 139 } else { 140 ret = 0; 141 cnid_t cnid; 142 char *bufp = resbuf; 143 bstring sep = bfromcstr("/"); 144 while (count--) { 145 memcpy(&cnid, bufp, sizeof(cnid_t)); 146 bufp += sizeof(cnid_t); 147 148 bstring path = NULL; 149 bstring volpath = bfromcstr(vol.volinfo.v_path); 150 BSTRING_STRIP_SLASH(volpath); 151 char buffer[12 + MAXPATHLEN + 1]; 152 int buflen = 12 + MAXPATHLEN + 1; 153 char *name; 154 cnid_t did = cnid; 155 struct bstrList *pathlist = bstrListCreateMin(32); 156 157 while (did != DIRDID_ROOT) { 158 if ((name = cnid_resolve(vol.volume.v_cdb, &did, buffer, buflen)) == NULL) 159 goto next; 160 bstrListPush(pathlist, bfromcstr(name)); 161 } 162 bstrListPush(pathlist, volpath); 163 path = bjoinInv(pathlist, sep); 164 165 printf("%s\n", cfrombstr(path)); 166 167 next: 168 bstrListDestroy(pathlist); 169 bdestroy(path); 170 } 171 bdestroy(sep); 172 } 173 174 closevol(&vol); 175 176 return ret; 177} 178