1/* 2 Copyright (c) 2009 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#include <dirent.h> 28#include <fcntl.h> 29#include <ctype.h> 30#include <pwd.h> 31#include <grp.h> 32#include <time.h> 33 34#include <atalk/adouble.h> 35#include <atalk/cnid.h> 36#include "ad.h" 37 38#define ADv2_DIRNAME ".AppleDouble" 39 40#define DIR_DOT_OR_DOTDOT(a) \ 41 ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0)) 42 43static const char *labels[] = { 44 "none", 45 "grey", 46 "green", 47 "violet", 48 "blue", 49 "yellow", 50 "red", 51 "orange", 52 NULL 53}; 54 55static char *new_label; 56static char *new_type; 57static char *new_creator; 58static char *new_flags; 59static char *new_attributes; 60 61static void usage_set(void) 62{ 63 printf( 64 "Usage: ad set [-t TYPE] [-c CREATOR] [-l label] [-f flags] [-a attributes] file|dir \n\n" 65 " Color Label:\n" 66 " none | grey | green | violet | blue | yellow | red | orange\n\n" 67 " FinderFlags:\n" 68 " d = On Desktop (f/d)\n" 69 " e = Hidden extension (f/d)\n" 70 " m = Shared (can run multiple times) (f)\n" 71 " n = No INIT resources (f)\n" 72 " i = Inited (f/d)\n" 73 " c = Custom icon (f/d)\n" 74 " t = Stationery (f)\n" 75 " s = Name locked (f/d)\n" 76 " b = Bundle (f/d)\n" 77 " v = Invisible (f/d)\n" 78 " a = Alias file (f/d)\n\n" 79 " AFPAttributes:\n" 80 " y = System (f/d)\n" 81 " w = No write (f)\n" 82 " p = Needs backup (f/d)\n" 83 " r = No rename (f/d)\n" 84 " l = No delete (f/d)\n" 85 " o = No copy (f)\n\n" 86 " Uppercase letter sets the flag, lowercase removes the flag\n" 87 " f = valid for files\n" 88 " d = valid for directories\n" 89 90 ); 91} 92 93static void change_type(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_type) 94{ 95 char *FinderInfo; 96 97 if ((FinderInfo = ad_entry(ad, ADEID_FINDERI))) 98 memcpy(FinderInfo, new_type, 4); 99} 100 101static void change_creator(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_creator) 102{ 103 char *FinderInfo; 104 105 if ((FinderInfo = ad_entry(ad, ADEID_FINDERI))) 106 memcpy(FinderInfo + 4, new_creator, 4); 107 108} 109 110static void change_label(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_label) 111{ 112 char *FinderInfo; 113 const char **color = &labels[0]; 114 uint16_t FinderFlags; 115 unsigned char color_count = 0; 116 117 if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)) == NULL) 118 return; 119 120 while (*color) { 121 if (strcasecmp(*color, new_label) == 0) { 122 /* get flags */ 123 memcpy(&FinderFlags, FinderInfo + 8, 2); 124 FinderFlags = ntohs(FinderFlags); 125 126 /* change value */ 127 FinderFlags &= ~FINDERINFO_COLOR; 128 FinderFlags |= color_count << 1; 129 130 /* copy it back */ 131 FinderFlags = ntohs(FinderFlags); 132 memcpy(FinderInfo + 8, &FinderFlags, 2); 133 134 break; 135 } 136 color++; 137 color_count++; 138 } 139} 140 141static void change_attributes(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_attributes) 142{ 143 uint16_t AFPattributes; 144 145 ad_getattr(ad, &AFPattributes); 146 AFPattributes = ntohs(AFPattributes); 147 148 if (S_ISREG(st->st_mode)) { 149 if (strchr(new_attributes, 'W')) 150 AFPattributes |= ATTRBIT_NOWRITE; 151 if (strchr(new_attributes, 'w')) 152 AFPattributes &= ~ATTRBIT_NOWRITE; 153 154 if (strchr(new_attributes, 'O')) 155 AFPattributes |= ATTRBIT_NOCOPY; 156 if (strchr(new_attributes, 'o')) 157 AFPattributes &= ~ATTRBIT_NOCOPY; 158 } 159 160 if (strchr(new_attributes, 'Y')) 161 AFPattributes |= ATTRBIT_SYSTEM; 162 if (strchr(new_attributes, 'y')) 163 AFPattributes &= ~ATTRBIT_SYSTEM; 164 165 if (strchr(new_attributes, 'P')) 166 AFPattributes |= ATTRBIT_BACKUP; 167 if (strchr(new_attributes, 'p')) 168 AFPattributes &= ~ATTRBIT_BACKUP; 169 170 if (strchr(new_attributes, 'R')) 171 AFPattributes |= ATTRBIT_NORENAME; 172 if (strchr(new_attributes, 'r')) 173 AFPattributes &= ~ATTRBIT_NORENAME; 174 175 if (strchr(new_attributes, 'L')) 176 AFPattributes |= ATTRBIT_NODELETE; 177 if (strchr(new_attributes, 'l')) 178 AFPattributes &= ~ATTRBIT_NODELETE; 179 180 AFPattributes = ntohs(AFPattributes); 181 ad_setattr(ad, AFPattributes); 182} 183 184static void change_flags(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_flags) 185{ 186 char *FinderInfo; 187 uint16_t FinderFlags; 188 189 if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)) == NULL) 190 return; 191 192 memcpy(&FinderFlags, FinderInfo + 8, 2); 193 FinderFlags = ntohs(FinderFlags); 194 195 if (S_ISREG(st->st_mode)) { 196 if (strchr(new_flags, 'M')) 197 FinderFlags |= FINDERINFO_ISHARED; 198 if (strchr(new_flags, 'm')) 199 FinderFlags &= ~FINDERINFO_ISHARED; 200 201 if (strchr(new_flags, 'N')) 202 FinderFlags |= FINDERINFO_HASNOINITS; 203 if (strchr(new_flags, 'n')) 204 FinderFlags &= ~FINDERINFO_HASNOINITS; 205 206 if (strchr(new_flags, 'T')) 207 FinderFlags |= FINDERINFO_ISSTATIONNERY; 208 if (strchr(new_flags, 't')) 209 FinderFlags &= ~FINDERINFO_ISSTATIONNERY; 210 } 211 212 if (strchr(new_flags, 'D')) 213 FinderFlags |= FINDERINFO_ISONDESK; 214 if (strchr(new_flags, 'd')) 215 FinderFlags &= ~FINDERINFO_ISONDESK; 216 217 if (strchr(new_flags, 'E')) 218 FinderFlags |= FINDERINFO_HIDEEXT; 219 if (strchr(new_flags, 'e')) 220 FinderFlags &= ~FINDERINFO_HIDEEXT; 221 222 if (strchr(new_flags, 'I')) 223 FinderFlags |= FINDERINFO_HASBEENINITED; 224 if (strchr(new_flags, 'i')) 225 FinderFlags &= ~FINDERINFO_HASBEENINITED; 226 227 if (strchr(new_flags, 'C')) 228 FinderFlags |= FINDERINFO_HASCUSTOMICON; 229 if (strchr(new_flags, 'c')) 230 FinderFlags &= ~FINDERINFO_HASCUSTOMICON; 231 232 if (strchr(new_flags, 'S')) 233 FinderFlags |= FINDERINFO_NAMELOCKED; 234 if (strchr(new_flags, 's')) 235 FinderFlags &= ~FINDERINFO_NAMELOCKED; 236 237 if (strchr(new_flags, 'B')) 238 FinderFlags |= FINDERINFO_HASBUNDLE; 239 if (strchr(new_flags, 'b')) 240 FinderFlags &= ~FINDERINFO_HASBUNDLE; 241 242 if (strchr(new_flags, 'V')) 243 FinderFlags |= FINDERINFO_INVISIBLE; 244 if (strchr(new_flags, 'v')) 245 FinderFlags &= ~FINDERINFO_INVISIBLE; 246 247 if (strchr(new_flags, 'A')) 248 FinderFlags |= FINDERINFO_ISALIAS; 249 if (strchr(new_flags, 'a')) 250 FinderFlags &= ~FINDERINFO_ISALIAS; 251 252 FinderFlags = ntohs(FinderFlags); 253 memcpy(FinderInfo + 8, &FinderFlags, 2); 254} 255 256int ad_set(int argc, char **argv, AFPObj *obj) 257{ 258 int c; 259 afpvol_t vol; 260 struct stat st; 261 int adflags = 0; 262 struct adouble ad; 263 264 while ((c = getopt(argc, argv, ":l:t:c:f:a:")) != -1) { 265 switch(c) { 266 case 'l': 267 new_label = strdup(optarg); 268 break; 269 case 't': 270 new_type = strdup(optarg); 271 break; 272 case 'c': 273 new_creator = strdup(optarg); 274 break; 275 case 'f': 276 new_flags = strdup(optarg); 277 break; 278 case 'a': 279 new_attributes = strdup(optarg); 280 break; 281 case ':': 282 case '?': 283 usage_set(); 284 return -1; 285 break; 286 } 287 288 } 289 290 if (argc <= optind) 291 exit(1); 292 293 cnid_init(); 294 295 openvol(obj, argv[optind], &vol); 296 if (vol.vol->v_path == NULL) 297 exit(1); 298 299 if (stat(argv[optind], &st) != 0) { 300 perror("stat"); 301 exit(1); 302 } 303 304 if (S_ISDIR(st.st_mode)) 305 adflags = ADFLAGS_DIR; 306 307 ad_init(&ad, vol.vol); 308 309 if (ad_open(&ad, argv[optind], adflags | ADFLAGS_HF | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666) < 0) 310 goto exit; 311 312 if (new_label) 313 change_label(argv[optind], &vol, &st, &ad, new_label); 314 if (new_type) 315 change_type(argv[optind], &vol, &st, &ad, new_type); 316 if (new_creator) 317 change_creator(argv[optind], &vol, &st, &ad, new_creator); 318 if (new_flags) 319 change_flags(argv[optind], &vol, &st, &ad, new_flags); 320 if (new_attributes) 321 change_attributes(argv[optind], &vol, &st, &ad, new_attributes); 322 323 ad_flush(&ad); 324 ad_close(&ad, ADFLAGS_HF); 325 326exit: 327 closevol(&vol); 328 329 return 0; 330} 331