1 /* 2 * Copyright 2001-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval, jerome.duval@free.fr 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 /*! Remove an attribute from a file */ 11 12 #include <fs_attr.h> 13 14 #include <errno.h> 15 #include <fcntl.h> 16 #include <glob.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 22 23 extern const char *__progname; 24 const char *kProgramName = __progname; 25 26 int gCurrentFile; 27 28 29 void 30 usage() 31 { 32 printf("usage: %s [-P] [-p] attr filename1 [filename2...]\n" 33 "\t'attr' is the name of an attribute of the file\n" 34 "\t-P : Don't resolve links\n" 35 "\tIf '-p' is specified, 'attr' is regarded as a pattern.\n", kProgramName); 36 37 exit(1); 38 } 39 40 41 void * 42 open_attr_dir(const char* /*path*/) 43 { 44 return fs_fopen_attr_dir(gCurrentFile); 45 } 46 47 48 int 49 stat_attr(const char* /*attribute*/, struct stat* stat) 50 { 51 memset(stat, 0, sizeof(struct stat)); 52 stat->st_mode = S_IFREG; 53 return 0; 54 } 55 56 57 int 58 remove_attribute(int fd, const char* attribute, bool isPattern) 59 { 60 if (!isPattern) 61 return fs_remove_attr(fd, attribute); 62 63 glob_t glob; 64 memset(&glob, 0, sizeof(glob_t)); 65 66 glob.gl_closedir = (void (*)(void *))fs_close_attr_dir; 67 glob.gl_readdir = (dirent* (*)(void*))fs_read_attr_dir; 68 glob.gl_opendir = open_attr_dir; 69 glob.gl_lstat = stat_attr; 70 glob.gl_stat = stat_attr; 71 72 // for open_attr_dir(): 73 gCurrentFile = fd; 74 75 int result = ::glob(attribute, GLOB_ALTDIRFUNC, NULL, &glob); 76 if (result < 0) { 77 errno = B_BAD_VALUE; 78 return -1; 79 } 80 81 bool error = false; 82 83 for (int i = 0; i < glob.gl_pathc; i++) { 84 if (fs_remove_attr(fd, glob.gl_pathv[i]) != 0) 85 error = true; 86 } 87 88 return error ? -1 : 0; 89 } 90 91 92 int 93 main(int argc, const char **argv) 94 { 95 bool isPattern = false; 96 bool resolveLinks = true; 97 98 /* get all options */ 99 100 while (*++argv) { 101 const char *arg = *argv; 102 argc--; 103 if (*arg != '-') 104 break; 105 if (!strcmp(arg, "-P")) 106 resolveLinks = false; 107 else if (!strcmp(arg, "-p")) 108 isPattern = true; 109 } 110 111 // Make sure we have the minimum number of arguments. 112 if (argc < 2) 113 usage(); 114 115 for (int32 i = 1; i < argc; i++) { 116 int fd = open(argv[i], O_RDONLY | (resolveLinks ? 0 : O_NOTRAVERSE)); 117 if (fd < 0) { 118 fprintf(stderr, "%s: can\'t open file %s to remove attribute: %s\n", 119 kProgramName, argv[i], strerror(errno)); 120 return 1; 121 } 122 123 if (remove_attribute(fd, argv[0], isPattern) != B_OK) { 124 fprintf(stderr, "%s: error removing attribute %s from %s: %s\n", 125 kProgramName, argv[0], argv[i], strerror(errno)); 126 } 127 128 close(fd); 129 } 130 131 return 0; 132 } 133