int is_string_of_radix(char *string, int radix)
{
	if (radix == 16)
		return is_hex_string(string);
	else if (radix == 10)
		return is_decimal_string(string);
	else if (radix == 8)
		return is_octal_string(string);
	else if (radix == 2)
		return is_binary_string(string);
	else
		return FALSE;
}
/*
 * Parses the given little endian octal string into a little endian bit string padded or truncated to
 * binary_size bits. Throws an error if the string contains non-octal digits.
 */
char *convert_oct_string_of_size_to_bit_string(char *orig_string, int binary_size)
{
	if (!is_octal_string(orig_string))
		error_message(PARSE_ERROR, -1, -1, "Invalid octal number: %s.\n", orig_string);

	char *bit_string = (char *)calloc(1,sizeof(char));
	char *string     = strdup(orig_string);
	int   size       = strlen(string);

	// Change to big endian. (We want to add higher order bits at the end.)
	reverse_string(string, size);

	int count = 0;
	int i;
	for (i = 0; i < size; i++)
	{
		char temp[] = {string[i],'\0'};

		unsigned long value = strtoul(temp, NULL, 8);
		int k;
		for (k = 0; k < 3; k++)
		{
			char bit = value % 2;
			value /= 2;
			bit_string = (char *)realloc(bit_string, sizeof(char) * (count + 2));
			bit_string[count++] = '0' + bit;
			bit_string[count]   = '\0';
		}
	}
	free(string);

	// Pad with zeros to binary_size.
	while (count < binary_size)
	{
		bit_string = (char *)realloc(bit_string, sizeof(char) * (count + 2));
		bit_string[count++] = '0';
		bit_string[count]   = '\0';
	}

	// Truncate to binary_size
	bit_string[binary_size] = '\0';
	// Change to little endian
	reverse_string(bit_string, binary_size);
	// Copy out only the bits before the truncation.
	char *return_string = strdup(bit_string);
	free(bit_string);
	return return_string;
}
Ejemplo n.º 3
0
static mode_t execute_modespec(const char* str,
                               mode_t mode,
                               mode_t type,
                               mode_t umask)
{
	if ( is_octal_string(str) )
	{
		errno = 0;
		uintmax_t input = strtoumax((char*) str, NULL, 8);
		if ( errno == ERANGE )
			return (mode_t) -1;
		if ( input & ~((uintmax_t) 07777) )
			return (mode_t) -1;
		return (mode_t) input;
	}

	size_t index = 0;
	do
	{
		mode_t who_mask = 01000;
		while ( true )
		{
			if ( str[index] == 'u' && (index++, true) )
				who_mask |= 04700;
			else if ( str[index] == 'g' && (index++, true) )
				who_mask |= 02070;
			else if ( str[index] == 'o' && (index++, true) )
				who_mask |= 00007;
			else if ( str[index] == 'a' && (index++, true) )
				who_mask |= 06777;
			else
				break;
		}
		if ( !(who_mask & 0777) )
			who_mask |= 06777 & ~umask;
		do
		{
			char op;
			switch ( (op = str[index++]) )
			{
			case '+': break;
			case '-': break;
			case '=': break;
			default: return (mode_t) -1;
			};
			mode_t operand = 0;
			if ( str[index] == 'u' || str[index] == 'g' || str[index] == 'o' )
			{
				char permcopy = str[index++];
				switch ( permcopy )
				{
				case 'u': operand = mode >> 6 & 07; break;
				case 'g': operand = mode >> 3 & 07; break;
				case 'o': operand = mode >> 0 & 07; break;
				default: __builtin_unreachable();
				};
				operand = operand << 0 | operand << 3 | operand << 6;
				switch ( permcopy )
				{
				case 'u': if ( mode & 04000) operand |= 06000; break;
				case 'g': if ( mode & 02000) operand |= 06000; break;
				};
				who_mask &= ~((mode_t) 01000);
			}
			else
			{
				bool unknown = false;
				do
				{
					switch ( str[index] )
					{
					case 'r': operand |= 00444; break;
					case 'w': operand |= 00222; break;
					case 'x': operand |= 00111; break;
					case 'X':
						if ( S_ISDIR(type) || (mode & 0111) )
							operand |= 00111;
						break;
					case 's': operand |= 06000; break;
					case 't': operand |= 00000; break;
					default: unknown = true; break;
					}
				} while ( !unknown && (index++, true) );
			}
			switch ( op )
			{
			case '+': mode |= (operand & who_mask); break;
			case '-': mode &= ~(operand & who_mask); break;
			case '=': mode = (mode & ~who_mask) | (operand & who_mask); break;
			default: __builtin_unreachable();
			}
		} while ( str[index] == '+' ||
		          str[index] == '-' ||
		          str[index] == '=' );
	} while ( str[index] == ',' && (index++, true) );