179b25dd7SAxel Dörfler /*
2*3db68fb0SJérôme Duval * Copyright 2001-2009, Haiku, Inc. All Rights Reserved.
379b25dd7SAxel Dörfler * Distributed under the terms of the MIT License.
479b25dd7SAxel Dörfler *
579b25dd7SAxel Dörfler * Authors:
679b25dd7SAxel Dörfler * Jérôme Duval, jerome.duval@free.fr
779b25dd7SAxel Dörfler * Axel Dörfler, axeld@pinc-software.de
879b25dd7SAxel Dörfler */
917049c45SAxel Dörfler
1079b25dd7SAxel Dörfler /*! Remove an attribute from a file */
1179b25dd7SAxel Dörfler
1279b25dd7SAxel Dörfler #include <fs_attr.h>
1379b25dd7SAxel Dörfler
1479b25dd7SAxel Dörfler #include <errno.h>
1579b25dd7SAxel Dörfler #include <fcntl.h>
1679b25dd7SAxel Dörfler #include <glob.h>
1717049c45SAxel Dörfler #include <stdio.h>
18338b8dc3SIngo Weinhold #include <stdlib.h>
1979b25dd7SAxel Dörfler #include <string.h>
2079b25dd7SAxel Dörfler #include <unistd.h>
2117049c45SAxel Dörfler
2279b25dd7SAxel Dörfler
2379b25dd7SAxel Dörfler extern const char *__progname;
2479b25dd7SAxel Dörfler const char *kProgramName = __progname;
2579b25dd7SAxel Dörfler
2679b25dd7SAxel Dörfler int gCurrentFile;
2779b25dd7SAxel Dörfler
2879b25dd7SAxel Dörfler
2979b25dd7SAxel Dörfler void
usage()3079b25dd7SAxel Dörfler usage()
3179b25dd7SAxel Dörfler {
32*3db68fb0SJérôme Duval printf("usage: %s [-P] [-p] attr filename1 [filename2...]\n"
3379b25dd7SAxel Dörfler "\t'attr' is the name of an attribute of the file\n"
34*3db68fb0SJérôme Duval "\t-P : Don't resolve links\n"
3579b25dd7SAxel Dörfler "\tIf '-p' is specified, 'attr' is regarded as a pattern.\n", kProgramName);
3679b25dd7SAxel Dörfler
37383b5f43SJérôme Duval exit(1);
3879b25dd7SAxel Dörfler }
3979b25dd7SAxel Dörfler
4079b25dd7SAxel Dörfler
4179b25dd7SAxel Dörfler void *
open_attr_dir(const char *)4279b25dd7SAxel Dörfler open_attr_dir(const char* /*path*/)
4379b25dd7SAxel Dörfler {
4479b25dd7SAxel Dörfler return fs_fopen_attr_dir(gCurrentFile);
4579b25dd7SAxel Dörfler }
4679b25dd7SAxel Dörfler
4779b25dd7SAxel Dörfler
4879b25dd7SAxel Dörfler int
stat_attr(const char *,struct stat * stat)4979b25dd7SAxel Dörfler stat_attr(const char* /*attribute*/, struct stat* stat)
5079b25dd7SAxel Dörfler {
5179b25dd7SAxel Dörfler memset(stat, 0, sizeof(struct stat));
5279b25dd7SAxel Dörfler stat->st_mode = S_IFREG;
5379b25dd7SAxel Dörfler return 0;
5479b25dd7SAxel Dörfler }
5579b25dd7SAxel Dörfler
5679b25dd7SAxel Dörfler
5779b25dd7SAxel Dörfler int
remove_attribute(int fd,const char * attribute,bool isPattern)5879b25dd7SAxel Dörfler remove_attribute(int fd, const char* attribute, bool isPattern)
5979b25dd7SAxel Dörfler {
6079b25dd7SAxel Dörfler if (!isPattern)
6179b25dd7SAxel Dörfler return fs_remove_attr(fd, attribute);
6279b25dd7SAxel Dörfler
6379b25dd7SAxel Dörfler glob_t glob;
6479b25dd7SAxel Dörfler memset(&glob, 0, sizeof(glob_t));
6579b25dd7SAxel Dörfler
6679b25dd7SAxel Dörfler glob.gl_closedir = (void (*)(void *))fs_close_attr_dir;
676c05095cSIthamar R. Adema glob.gl_readdir = (dirent* (*)(void*))fs_read_attr_dir;
6879b25dd7SAxel Dörfler glob.gl_opendir = open_attr_dir;
6979b25dd7SAxel Dörfler glob.gl_lstat = stat_attr;
7079b25dd7SAxel Dörfler glob.gl_stat = stat_attr;
7179b25dd7SAxel Dörfler
7279b25dd7SAxel Dörfler // for open_attr_dir():
7379b25dd7SAxel Dörfler gCurrentFile = fd;
7479b25dd7SAxel Dörfler
7579b25dd7SAxel Dörfler int result = ::glob(attribute, GLOB_ALTDIRFUNC, NULL, &glob);
7679b25dd7SAxel Dörfler if (result < 0) {
7779b25dd7SAxel Dörfler errno = B_BAD_VALUE;
7879b25dd7SAxel Dörfler return -1;
7979b25dd7SAxel Dörfler }
8079b25dd7SAxel Dörfler
8179b25dd7SAxel Dörfler bool error = false;
8279b25dd7SAxel Dörfler
8379b25dd7SAxel Dörfler for (int i = 0; i < glob.gl_pathc; i++) {
8479b25dd7SAxel Dörfler if (fs_remove_attr(fd, glob.gl_pathv[i]) != 0)
8579b25dd7SAxel Dörfler error = true;
8679b25dd7SAxel Dörfler }
8779b25dd7SAxel Dörfler
8879b25dd7SAxel Dörfler return error ? -1 : 0;
8979b25dd7SAxel Dörfler }
9079b25dd7SAxel Dörfler
9179b25dd7SAxel Dörfler
9279b25dd7SAxel Dörfler int
main(int argc,const char ** argv)9306447030SMichael Lotz main(int argc, const char **argv)
9417049c45SAxel Dörfler {
9579b25dd7SAxel Dörfler bool isPattern = false;
96*3db68fb0SJérôme Duval bool resolveLinks = true;
9779b25dd7SAxel Dörfler
98*3db68fb0SJérôme Duval /* get all options */
99*3db68fb0SJérôme Duval
100*3db68fb0SJérôme Duval while (*++argv) {
101*3db68fb0SJérôme Duval const char *arg = *argv;
102*3db68fb0SJérôme Duval argc--;
103*3db68fb0SJérôme Duval if (*arg != '-')
104*3db68fb0SJérôme Duval break;
105*3db68fb0SJérôme Duval if (!strcmp(arg, "-P"))
106*3db68fb0SJérôme Duval resolveLinks = false;
107*3db68fb0SJérôme Duval else if (!strcmp(arg, "-p"))
108*3db68fb0SJérôme Duval isPattern = true;
10917049c45SAxel Dörfler }
11017049c45SAxel Dörfler
111*3db68fb0SJérôme Duval // Make sure we have the minimum number of arguments.
112*3db68fb0SJérôme Duval if (argc < 2)
113*3db68fb0SJérôme Duval usage();
114*3db68fb0SJérôme Duval
115*3db68fb0SJérôme Duval for (int32 i = 1; i < argc; i++) {
116*3db68fb0SJérôme Duval int fd = open(argv[i], O_RDONLY | (resolveLinks ? 0 : O_NOTRAVERSE));
11717049c45SAxel Dörfler if (fd < 0) {
11879b25dd7SAxel Dörfler fprintf(stderr, "%s: can\'t open file %s to remove attribute: %s\n",
11979b25dd7SAxel Dörfler kProgramName, argv[i], strerror(errno));
120383b5f43SJérôme Duval return 1;
12117049c45SAxel Dörfler }
12217049c45SAxel Dörfler
123*3db68fb0SJérôme Duval if (remove_attribute(fd, argv[0], isPattern) != B_OK) {
12479b25dd7SAxel Dörfler fprintf(stderr, "%s: error removing attribute %s from %s: %s\n",
125*3db68fb0SJérôme Duval kProgramName, argv[0], argv[i], strerror(errno));
12617049c45SAxel Dörfler }
12717049c45SAxel Dörfler
12879b25dd7SAxel Dörfler close(fd);
12979b25dd7SAxel Dörfler }
13079b25dd7SAxel Dörfler
13179b25dd7SAxel Dörfler return 0;
13217049c45SAxel Dörfler }
133