// Copyright (c) 1999-2002 David Muse
// See the COPYING file for more information

#include <rudiments/permissions.h>
#include <rudiments/charstring.h>
#include <rudiments/error.h>
#include <rudiments/file.h>

#include <stdlib.h>
#include <sys/stat.h>

#ifdef RUDIMENTS_NAMESPACE
namespace rudiments {
#endif

bool permissions::setFilePermissions(const char *filename, mode_t perms) {
	file	fl;
	return (fl.open(filename,O_RDWR) &&
		setFilePermissions(fl.getFileDescriptor(),perms));
}

bool permissions::setFilePermissions(int fd, mode_t perms) {
	int	result;
	do {
		result=fchmod(fd,perms);
	} while (result==-1 && error::getErrorNumber()==EINTR);
	return !result;
}

mode_t permissions::everyoneReadWrite() {
	return S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
}

mode_t permissions::everyoneReadWriteExecute() {
	return S_IRUSR|S_IWUSR|S_IXUSR|
		S_IRGRP|S_IWGRP|S_IXGRP|
		S_IROTH|S_IWOTH|S_IXOTH;
}

mode_t permissions::ownerRead() {
	return S_IRUSR;
}

mode_t permissions::ownerWrite() {
	return S_IWUSR;
}

mode_t permissions::ownerExecute() {
	return S_IXUSR;
}

mode_t permissions::ownerReadWrite() {
	return S_IRUSR|S_IWUSR;
}

mode_t permissions::ownerReadExecute() {
	return S_IRUSR|S_IXUSR;
}

mode_t permissions::ownerReadWriteExecute() {
	return S_IRUSR|S_IWUSR|S_IXUSR;
}

mode_t permissions::groupRead() {
	return S_IRGRP;
}

mode_t permissions::groupWrite() {
	return S_IWGRP;
}

mode_t permissions::groupExecute() {
	return S_IXGRP;
}

mode_t permissions::groupReadWrite() {
	return S_IRGRP|S_IWGRP;
}

mode_t permissions::groupReadExecute() {
	return S_IRGRP|S_IXGRP;
}

mode_t permissions::groupReadWriteExecute() {
	return S_IRGRP|S_IWGRP|S_IXGRP;
}

mode_t permissions::othersRead() {
	return S_IROTH;
}

mode_t permissions::othersWrite() {
	return S_IWOTH;
}

mode_t permissions::othersExecute() {
	return S_IXOTH;
}

mode_t permissions::othersReadWrite() {
	return S_IROTH|S_IWOTH;
}

mode_t permissions::othersReadExecute() {
	return S_IROTH|S_IXOTH;
}

mode_t permissions::othersReadWriteExecute() {
	return S_IROTH|S_IWOTH|S_IXOTH;
}

mode_t permissions::saveInSwapSpace() {
	return S_ISVTX;
}

mode_t permissions::setUserId() {
	return S_ISUID;
}

mode_t permissions::setGroupId() {
	return S_ISGID;
}

mode_t permissions::evalPermString(const char *permstring) {
	mode_t	retval=0;
	if (charstring::length(permstring)==9) {

		// handle user permissions
		if (permstring[0]=='r') {
			retval=retval|S_IRUSR;
		}
		if (permstring[1]=='w') {
			retval=retval|S_IWUSR;
		}
		if (permstring[2]=='x') {
			retval=retval|S_IXUSR;
		} else if (permstring[2]=='X' || permstring[2]=='S') {
			retval=retval|S_IXUSR;
			retval=retval|S_ISUID;
		}

		// handle group permissions
		if (permstring[3]=='r') {
			retval=retval|S_IRGRP;
		}
		if (permstring[4]=='w') {
			retval=retval|S_IWGRP;
		}
		if (permstring[5]=='x') {
			retval=retval|S_IXGRP;
		} else if (permstring[5]=='X' || permstring[5]=='S') {
			retval=retval|S_IXGRP;
		}

		// handle others permissions
		if (permstring[6]=='r') {
			retval=retval|S_IROTH;
		}
		if (permstring[7]=='w') {
			retval=retval|S_IWOTH;
		}
		if (permstring[8]=='x') {
			retval=retval|S_IXOTH;

		// handle sticky bit
		} else if (permstring[5]=='t') {
			retval=retval|S_ISVTX;
		}
	}
	return retval;
}

char *permissions::evalPermOctal(mode_t permoctal) {

	char	*permstring=new char[10];
	permstring[9]='\0';

	mode_t	shift=permoctal;
	for (int i=8; i>=0; i--) {
		int	pos=i%3;
		permstring[i]=(shift&1)?((pos==2)?'x':(pos==1)?'w':'r'):'-';
		shift=shift>>1;
	}
	return permstring;
}

#ifdef RUDIMENTS_NAMESPACE
}
#endif


syntax highlighted by Code2HTML, v. 0.9.1