/* Attempt to read a character from a stream. * Return true, and remove it from the stream if it is present. * Otherwise, return false. */ bool try_to_read(std::istream &s, char c_want) { char c_have; c_have = s.peek(); check_stream(s); if(c_have == c_want) { s.ignore(); check_stream(s); return true; } return false; }
void TrexStreamsCompiler::allocate_pass(const std::vector<TrexStream *> &streams, GraphNodeMap *nodes) { std::stringstream ss; uint32_t compressed_stream_id=0; /* first pass - allocate all nodes and check for duplicates */ for (auto stream : streams) { /* skip non enabled streams */ if (!stream->m_enabled) { continue; } /* sanity check on the stream itself */ check_stream(stream); /* duplicate stream id ? */ if (nodes->has(stream->m_stream_id)) { ss << "duplicate instance of stream id " << stream->m_stream_id; err(ss.str()); } GraphNode *node = new GraphNode(stream, NULL); /* allocate new compressed id */ node->m_compressed_stream_id = compressed_stream_id; compressed_stream_id++; /* add to the map */ assert(nodes->add(node)); } }
/* Read a character from a stream, and then check the stream for errors. */ char checked_stream_get(std::istream &s) { char c; s.get(c); check_stream(s); return c; }
/* Remove as much whitespace (tabs, newlines, carriage returns or spaces) * from the front of a string as possible. */ void eat_whitespace(std::istream &s) { char c; while(true) { c = s.peek(); check_stream(s); if(c == ' ' || c == '\t' || c == '\r' || c == '\n') { s.ignore(); check_stream(s); } else break; } }
Status unstore(Header *header, FILE *ifp, FILE *ofp) { /* BB changed next line: complen is a long */ /* register len = header->complen; */ #ifdef __MSDOS__ register long len = header->complen; #else register int len = header->complen; #endif /* __MSDOS__ */ register Byte byte; init_garble(); crc = 0; while (len--) { if (check_stream(ifp) != FNOERR) break; byte = read_byte(ifp); byte = ungarble(byte); calccrc(byte); if (!testing) write_byte(ofp, byte); } if (check_stream(ifp) == FRWERR) return (RERR); if (!testing && check_stream(ofp) == FRWERR) return (WERR); if ((Halfword) crc != header->crc) return (CRCERR); if (testing) { if (!quiet) printf("OK (stored)"); } else if (!quiet) printf("unstored"); return (NOERR); }
/* Read digits from a stream, ie: [0-9]* or [0-9]+ * If need_one is true, we must read at least one digit ([0-9]+) * Otherwise, no digits is acceptable ([0-9]*) * If need_one is true, and we can't read any digits, throw an exception. */ void read_digits_from_stream(std::istream &s, std::string &str, bool need_one) { while(true) { char c = s.peek(); check_stream(s); if(c >= '0' && c <= '9') { s.ignore(); check_stream(s); str += c; need_one = false; } else break; } if(need_one) { // We needed a digit, but one didn't get read... throw json::ParseException(); } }
/* Read in a JSON object or array start marker from the stream, * and create and return a JSON object/array to store it. */ json::Value *read_json_object_or_array(std::istream &s) { char c; c = s.peek(); check_stream(s); if(c == '[') { s.ignore(); check_stream(s); eat_whitespace(s); return new json::Array(); } else if(c == '{') { s.ignore(); check_stream(s); eat_whitespace(s); return new json::Object(); } else throw json::ParseException(); }
/* Read in a JSON value from the stream. We should be positioned right before * it. */ json::Value *read_json_value(std::istream &s) { // Peek a character - this tells us what type we're looking at. // All the JSON primitives differ in their first character. char c; c = s.peek(); check_stream(s); if(c == 'n') { read_string(s, "null"); return new json::Null(); } else if(c == 't') { read_string(s, "true"); return new json::Bool(true); } else if(c == 'f') { read_string(s, "false"); return new json::Bool(false); } else if(c == '\"') { std::string str; str = read_json_string_basic(s); return new json::String(str); } else if(c == '-' || (c >= '0' && c <= '9')) { return read_json_numeric(s); } // By now, it should be an array or an object -- this function will throw // if it isn't. else return read_json_object_or_array(s); }
void parse_item(std::istream &s, std::stack<json::Value *> &struct_stack) { // Get the object/array: json::Array *arr = NULL; json::Object *obj = NULL; if(struct_stack.top()->type() == json::TYPE_ARRAY) arr = dynamic_cast<json::Array *>(struct_stack.top()); else obj = dynamic_cast<json::Object *>(struct_stack.top()); // See if we've reached the end: char c = s.peek(); check_stream(s); if((arr && c == ']') || (obj && c == '}')) { s.ignore(); check_stream(s); struct_stack.pop(); if(!struct_stack.empty()) { eat_whitespace(s); } return; } // Check for a comma: if((arr && !arr->empty()) || (obj && !obj->empty())) { if(c != ',') throw json::ParseException("Expected \',\' token."); s.ignore(); check_stream(s); eat_whitespace(s); } // Read in a key if this is an object std::string key; if(obj) { key = read_json_string_basic(s); eat_whitespace(s); if(checked_stream_get(s) != ':') throw json::ParseException("Expected \':\' token."); eat_whitespace(s); } // Read in the actual value: json::Value *v = NULL; try { v = read_json_value(s); if(arr) arr->pushBackTake(v); else obj->takeValue(key, v); } catch(...) { delete v; throw; } if(v->type() == json::TYPE_ARRAY || v->type() == json::TYPE_OBJECT) { struct_stack.push(v); } eat_whitespace(s); }
/* Read a JSON string from a stream. This returns the actual string, and not * a json::String as it gets used to read keys in objects as well. * A JSON string is: * "text... " * ie, an opening quote, characters, a closing quote. There are some escape * sequences for things like quotes or slashes. */ std::string read_json_string_basic(std::istream &s) { char c; std::string text; // Read opening quote. c = s.get(); check_stream(s); if(!s || c != '\"') throw json::ParseException(); while(true) { c = s.get(); check_stream(s); if(c == '\"') break; // Characters below 0x20 must be escaped. if((unsigned char)c < 0x20) throw json::ParseException(); if(c == '\\') { char escape_code = s.get(); check_stream(s); if(escape_code == '\"') text += '\"'; else if(escape_code == '\\') text += '\\'; else if(escape_code == '/') text += '/'; else if(escape_code == 'b') text += 0x08; else if(escape_code == 'f') text += 0x0C; else if(escape_code == 'n') text += '\n'; else if(escape_code == 'r') text += '\r'; else if(escape_code == 't') text += '\t'; else if(escape_code == 'u') { char four_hex[5] = {0}; read_four_hex_digits(s, four_hex); unsigned int code = strtoul(four_hex, NULL, 16); int surrogate_type = is_surrogate_pair(code); if(surrogate_type == 0) text += to_utf8(code); else if(surrogate_type == 1) { // The last \u escape was the start marker of a surrogate pair. // Look for the second half of the pair. read_string(s, "\\u"); char four_hex_2[5] = {0}; read_four_hex_digits(s, four_hex_2); unsigned int code2 = strtoul(four_hex_2, NULL, 16); if(is_surrogate_pair(code2) != 2) // There was another \u escape, but it wasn't the second half // of the surrogate pair... throw json::ParseException(); uint32_t code_point = decode_surrogate_pair(code, code2); text += to_utf8(code); } else // We found the second half of a surrogate pair, but there wasn't // a first half... throw json::ParseException(); } else throw json::ParseException(); } else text += c; } check_is_valid_utf8(text); return text; }
/* Read a numeric value, either integer or floating point, from the stream. * Return it as a json::Value -- this will be either a json::Double or a * json::Integer. */ json::Value *read_json_numeric(std::istream &s) { std::string numeric_text; char c; if(try_to_read(s, '-')) numeric_text += '-'; if(!try_to_read(s, '0')) { // Read in whole digits c = s.peek(); check_stream(s); if(!(c >= '1' && c <= '9')) { throw json::ParseException(); } numeric_text += c; s.ignore(); check_stream(s); read_digits_from_stream(s, numeric_text, false); } else { // It was a 0. numeric_text += '0'; } if(try_to_read(s, '.')) { // A decimal point. numeric_text += '.'; // Read the digits! read_digits_from_stream(s, numeric_text, true); } c = s.peek(); check_stream(s); if(c == 'e' || c == 'E') { s.ignore(); check_stream(s); numeric_text += 'e'; read_digits_from_stream(s, numeric_text, true); } intmax_t ll; char *endptr; ll = strtoll(numeric_text.c_str(), &endptr, 10); if(endptr == numeric_text.c_str() + numeric_text.size()) { // Yay, a number. if(ll <= INT_MAX && ll >= INT_MIN) { return new json::Integer(ll); } else return new json::BigInteger(ll); } double d; d = strtod(numeric_text.c_str(), &endptr); if(endptr == numeric_text.c_str() + numeric_text.size()) { return new json::Double(d); } throw json::ParseException(); }
/* * read a compression-header from the file */ Header * read_header(FILE *ifp) { static Header header; register int i; register char *cptr; Byte byte; #ifdef BSD bzero((char *) &header, sizeof(header)); #else /* not BSD */ memset((char *) &header, '\0', sizeof(header)); #endif /* BSD */ if (arcfs) return (arcfs_read_header(ifp)); header.comptype = read_byte(ifp); if (!(header.comptype & ~ARCHPACK)) return (&header); /* EOF */ for (i = 0, cptr = header.name; i <= 12; i++, cptr++) { byte = read_byte(ifp); #ifdef RISCOS if (byte < ' ') #else if (byte < ' ' || byte > '~') #endif byte = '\0'; else if (byte == PATHSEP) /* illegal in filename */ byte = '_'; *cptr = byte; } *cptr = '\0'; /* null terminate */ if (singlecase) { for (i = 0, cptr = header.name; i <= 12; i++, cptr++) if (isascii(*cptr) && isupper(*cptr)) *cptr = tolower(*cptr); } header.complen = read_word(ifp); header.date = read_halfword(ifp); header.time = read_halfword(ifp); header.crc = read_halfword(ifp); if ((header.comptype & ~ARCHPACK) > CT_NOTCOMP) header.origlen = read_word(ifp); else header.origlen = header.complen; if (header.comptype & ARCHPACK) { header.load = read_word(ifp); header.exec = read_word(ifp); header.attr = read_word(ifp); } if (check_stream(ifp) == FRWERR) return (NULL); return (&header); }
/* test basic io on streams */ static BOOL test_stream_io(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { NTSTATUS status; union smb_open io; const char *fname = BASEDIR "\\stream.txt"; const char *sname1, *sname2; BOOL ret = True; int fnum = -1; ssize_t retsize; sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One"); sname2 = talloc_asprintf(mem_ctx, "%s:%s:$DaTa", fname, "Second Stream"); printf("opening non-existant directory stream\n"); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid = 0; io.ntcreatex.in.flags = 0; io.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = 0; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = sname1; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY); printf("creating a stream on a non-existant file\n"); io.ntcreatex.in.create_options = 0; io.ntcreatex.in.fname = sname1; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; ret &= check_stream(cli, mem_ctx, fname, "Stream One", NULL); printf("check that open of base file is allowed\n"); io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.fname = fname; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); smbcli_close(cli->tree, io.ntcreatex.out.file.fnum); printf("writing to stream\n"); retsize = smbcli_write(cli->tree, fnum, 0, "test data", 0, 9); CHECK_VALUE(retsize, 9); smbcli_close(cli->tree, fnum); ret &= check_stream(cli, mem_ctx, fname, "Stream One", "test data"); io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.fname = sname1; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; printf("modifying stream\n"); retsize = smbcli_write(cli->tree, fnum, 0, "MORE DATA ", 5, 10); CHECK_VALUE(retsize, 10); smbcli_close(cli->tree, fnum); ret &= check_stream(cli, mem_ctx, fname, "Stream One:$FOO", NULL); printf("creating a stream2 on a existing file\n"); io.ntcreatex.in.fname = sname2; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; printf("modifying stream\n"); retsize = smbcli_write(cli->tree, fnum, 0, "SECOND STREAM", 0, 13); CHECK_VALUE(retsize, 13); smbcli_close(cli->tree, fnum); ret &= check_stream(cli, mem_ctx, fname, "Stream One", "test MORE DATA "); ret &= check_stream(cli, mem_ctx, fname, "Stream One:$DATA", "test MORE DATA "); ret &= check_stream(cli, mem_ctx, fname, "Stream One:", NULL); ret &= check_stream(cli, mem_ctx, fname, "Second Stream", "SECOND STREAM"); ret &= check_stream(cli, mem_ctx, fname, "Second Stream:$DATA", "SECOND STREAM"); ret &= check_stream(cli, mem_ctx, fname, "Second Stream:", NULL); ret &= check_stream(cli, mem_ctx, fname, "Second Stream:$FOO", NULL); printf("deleting stream\n"); status = smbcli_unlink(cli->tree, sname1); CHECK_STATUS(status, NT_STATUS_OK); printf("delete a stream via delete-on-close\n"); io.ntcreatex.in.fname = sname2; io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; smbcli_close(cli->tree, fnum); status = smbcli_unlink(cli->tree, sname2); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); printf("deleting file\n"); status = smbcli_unlink(cli->tree, fname); CHECK_STATUS(status, NT_STATUS_OK); done: smbcli_close(cli->tree, fnum); return ret; }