⛏️ index : haiku.git

/*
 * Copyright 2001-2009, Haiku, Inc. All Rights Reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		JΓ©rΓ΄me Duval, jerome.duval@free.fr
 *		Axel DΓΆrfler, axeld@pinc-software.de
 */

/*! Remove an attribute from a file */

#include <fs_attr.h>

#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


extern const char *__progname;
const char *kProgramName = __progname;

int gCurrentFile;


void
usage()
{
	printf("usage: %s [-P] [-p] attr filename1 [filename2...]\n"
		"\t'attr' is the name of an attribute of the file\n"
		"\t-P : Don't resolve links\n"
		"\tIf '-p' is specified, 'attr' is regarded as a pattern.\n", kProgramName);

	exit(1);	
}


void *
open_attr_dir(const char* /*path*/)
{
	return fs_fopen_attr_dir(gCurrentFile);
}


int
stat_attr(const char* /*attribute*/, struct stat* stat)
{
	memset(stat, 0, sizeof(struct stat));
	stat->st_mode = S_IFREG;
	return 0;
}


int
remove_attribute(int fd, const char* attribute, bool isPattern)
{
	if (!isPattern)
		return fs_remove_attr(fd, attribute);

	glob_t glob;
	memset(&glob, 0, sizeof(glob_t));

	glob.gl_closedir = (void (*)(void *))fs_close_attr_dir;
	glob.gl_readdir = (dirent* (*)(void*))fs_read_attr_dir;
	glob.gl_opendir = open_attr_dir;
	glob.gl_lstat = stat_attr;
	glob.gl_stat = stat_attr;

	// for open_attr_dir():
	gCurrentFile = fd;

	int result = ::glob(attribute, GLOB_ALTDIRFUNC, NULL, &glob);
	if (result < 0) {
		errno = B_BAD_VALUE;
		return -1;
	}

	bool error = false;

	for (int i = 0; i < glob.gl_pathc; i++) {
		if (fs_remove_attr(fd, glob.gl_pathv[i]) != 0)
			error = true;
	}

	return error ? -1 : 0;
}


int
main(int argc, const char **argv)
{
	bool isPattern = false;
	bool resolveLinks = true;

	/* get all options */

	while (*++argv) {
		const char *arg = *argv;
		argc--;
		if (*arg != '-')
			break;
		if (!strcmp(arg, "-P"))
			resolveLinks = false;
		else if (!strcmp(arg, "-p"))
			isPattern = true;
	}

	// Make sure we have the minimum number of arguments.
	if (argc < 2)
		usage();

	for (int32 i = 1; i < argc; i++) {
		int fd = open(argv[i], O_RDONLY | (resolveLinks ? 0 : O_NOTRAVERSE));
		if (fd < 0) {
			fprintf(stderr, "%s: can\'t open file %s to remove attribute: %s\n", 
				kProgramName, argv[i], strerror(errno));
			return 1;
		}

		if (remove_attribute(fd, argv[0], isPattern) != B_OK) {
			fprintf(stderr, "%s: error removing attribute %s from %s: %s\n", 
				kProgramName, argv[0], argv[i], strerror(errno));
		}

		close(fd);
	}

	return 0;
}