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
23extern const char *__progname;
24const char *kProgramName = __progname;
25
26int gCurrentFile;
27
28
29void
30usage()
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
41void *
42open_attr_dir(const char* /*path*/)
43{
44	return fs_fopen_attr_dir(gCurrentFile);
45}
46
47
48int
49stat_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
57int
58remove_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
92int
93main(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