int pr_str2gid(const char *val, gid_t *gid) { #ifdef HAVE_STRTOULL unsigned long long ull = 0ULL; #endif /* HAVE_STRTOULL */ unsigned long ul = 0UL; if (val == NULL || gid == NULL) { errno = EINVAL; return -1; } #if SIZEOF_GID_T == SIZEOF_LONG_LONG # ifdef HAVE_STRTOULL if (parse_ull(val, &ull) < 0) { return -1; } *gid = ull; # else if (parse_ul(val, &ul) < 0) { return -1; } *gid = ul; # endif /* HAVE_STRTOULL */ #else (void) ull; if (parse_ul(val, &ul) < 0) { return -1; } *gid = ul; #endif /* sizeof(gid_t) != sizeof(long long) */ return 0; }
uint32_t parse_codepoint( char const *s ) { assert( s ); if ( s[0] && !s[1] ) // assume single-char ASCII return (uint32_t)s[0]; char const *const s0 = s; if ( (s[0] == 'U' || s[0] == 'u') && s[1] == '+' ) { // convert [uU]+NNNN to 0xNNNN so strtoull() will grok it char *const t = freelist_add( check_strdup( s ) ); s = memcpy( t, "0x", 2 ); } uint64_t const codepoint = parse_ull( s ); if ( codepoint_is_valid( codepoint ) ) return (uint32_t)codepoint; PMESSAGE_EXIT( USAGE, "\"%s\": invalid Unicode code-point for -%c\n", s0, 'U' ); }
// parses the memwatch data format from a string unsigned long long read_string_data(const char* in, void** vdata, void** vmask) { *vdata = NULL; if (vmask) *vmask = NULL; unsigned char** data = (unsigned char**)vdata; unsigned char** mask = (unsigned char**)vmask; int read, chr = 0; int string = 0, unicode_string = 0, comment = 0, multiline_comment = 0, high = 1; int filename = 0, filename_start; unsigned long size = 0; int endian = 0; while (in[0]) { read = 0; // if between // and a newline, don't write to output buffer if (comment) { if (in[0] == '\n') comment = 0; in++; // if between /* and */, don't write to output buffer } else if (multiline_comment) { if (in[0] == '*' && in[1] == '/') { multiline_comment = 0; in++; } in++; // if between quotes, read bytes to output buffer, unescaping } else if (string) { if (in[0] == '\"') string = 0; else if (in[0] == '\\') { // unescape char after a backslash if (!in[1]) return size; if (in[1] == 'n') { write_byte('\n'); } else if (in[1] == 'r') { write_byte('\r'); } else if (in[1] == 't') { write_byte('\t'); } else { write_byte(in[1]); } in++; } else write_byte(in[0]); in++; // if between single quotes, word-expand bytes to output buffer, unescaping } else if (unicode_string) { if (in[0] == '\'') unicode_string = 0; else if (in[0] == '\\') { // unescape char after a backslash if (!in[1]) return size; if (in[1] == 'n') { write_short('\n'); } else if (in[1] == 'r') { write_short('\r'); } else if (in[1] == 't') { write_short('\t'); } else { write_short(in[1]); } if (endian) bswap(&(*data)[size - 2], 2); in++; } else { write_short(in[0]); if (endian) bswap(&(*data)[size - 2], 2); } in++; // if between <>, read a file name, then stick that file into the buffer } else if (filename) { if (in[0] == '>') { filename = 0; write_byte(0); // null-terminate the filename // TODO: support <filename@offset:size> syntax // open the file, read it into the buffer, close the file FILE* f = fopen((char*)(*data + filename_start), "rb"); if (!f) { if (data) free(data); return 0; } fseek(f, 0, SEEK_END); int file_size = ftell(f); size = filename_start + file_size; *data = realloc(*data, size); fseek(f, 0, SEEK_SET); fread((*data + filename_start), 1, file_size, f); fclose(f); } else write_byte(in[0]); in++; // ? is an unknown byte, but only if the caller wants a mask } else if (in[0] == '?' && vmask) { write_blank(); in++; // $ changes the endian-ness } else if (in[0] == '$') { endian = !endian; in++; // # signifies a decimal number } else if (in[0] == '#') { // 8-bit unsigned long long value; in++; if (in[0] == '#') { // 16-bit in++; if (in[0] == '#') { // 32-bit in++; if (in[0] == '#') { // 64-bit in++; expand(8); parse_ull(in, (unsigned long long*)(&((*data)[size - 8])), 0); if (endian) bswap(&((*data)[size - 8]), 8); if (mask) *(unsigned long long*)(&((*mask)[size - 8])) = 0xFFFFFFFFFFFFFFFF; } else { expand(4); parse_ull(in, &value, 0); if (endian) bswap(&value, 4); *(int32_t*)(&((*data)[size - 4])) = value; if (mask) *(uint32_t*)(&((*mask)[size - 4])) = 0xFFFFFFFF; } } else { expand(2); parse_ull(in, &value, 0); if (endian) bswap(&value, 2); *(int16_t*)(&((*data)[size - 2])) = value; if (mask) *(uint16_t*)(&((*mask)[size - 2])) = 0xFFFF; } } else { expand(1); parse_ull(in, &value, 0); *(int8_t*)(&((*data)[size - 1])) = value; if (mask) *(uint8_t*)(&((*mask)[size - 1])) = 0xFF; } if (in[0] == '-') in++; while (isdigit(in[0])) in++; // % is a float, %% is a double } else if (in[0] == '%') { in++; if (in[0] == '%') { in++; expand(8); double* value = (double*)(&((*data)[size - 8])); sscanf(in, "%lf", value); if (endian) bswap(value, 8); if (mask) *(unsigned long long*)(&((*mask)[size - 8])) = 0xFFFFFFFFFFFFFFFF; } else { expand(4); float* value = (float*)(&((*data)[size - 4])); sscanf(in, "%f", value); if (endian) bswap(value, 4); if (mask) *(uint32_t*)(&((*mask)[size - 4])) = 0xFFFFFFFF; } if (in[0] == '-') in++; while (isdigit(in[0]) || (in[0] == '.')) in++; // anything else is a hex digit } else { if ((in[0] >= '0') && (in[0] <= '9')) { read = 1; chr |= (in[0] - '0'); } if ((in[0] >= 'A') && (in[0] <= 'F')) { read = 1; chr |= (in[0] - 'A' + 0x0A); } if ((in[0] >= 'a') && (in[0] <= 'f')) { read = 1; chr |= (in[0] - 'a' + 0x0A); } if (in[0] == '\"') string = 1; if (in[0] == '\'') unicode_string = 1; if (in[0] == '/' && in[1] == '/') comment = 1; if (in[0] == '/' && in[1] == '*') multiline_comment = 1; if (in[0] == '<') { filename = 1; filename_start = size; } in++; } if (read) { if (high) chr = chr << 4; else { write_byte(chr); chr = 0; } high = !high; } } return size; }