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; }
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) );