mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #if DEBUG_PRINT DEBUG_printf("__import__:\n"); for (size_t i = 0; i < n_args; i++) { DEBUG_printf(" "); mp_obj_print(args[i], PRINT_REPR); DEBUG_printf("\n"); } #endif mp_obj_t module_name = args[0]; mp_obj_t fromtuple = mp_const_none; mp_int_t level = 0; if (n_args >= 4) { fromtuple = args[3]; if (n_args >= 5) { level = MP_OBJ_SMALL_INT_VALUE(args[4]); if (level < 0) { mp_raise_ValueError(NULL); } } } size_t mod_len; const char *mod_str = mp_obj_str_get_data(module_name, &mod_len); if (level != 0) { // What we want to do here is to take name of current module, // chop <level> trailing components, and concatenate with passed-in // module name, thus resolving relative import name into absolute. // This even appears to be correct per // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name // "Relative imports use a module's __name__ attribute to determine that // module's position in the package hierarchy." level--; mp_obj_t this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__)); assert(this_name_q != MP_OBJ_NULL); #if MICROPY_CPYTHON_COMPAT if (MP_OBJ_QSTR_VALUE(this_name_q) == MP_QSTR___main__) { // This is a module run by -m command-line switch, get its real name from backup attribute this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); } #endif mp_map_t *globals_map = &mp_globals_get()->map; mp_map_elem_t *elem = mp_map_lookup(globals_map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP); bool is_pkg = (elem != NULL); #if DEBUG_PRINT DEBUG_printf("Current module/package: "); mp_obj_print(this_name_q, PRINT_REPR); DEBUG_printf(", is_package: %d", is_pkg); DEBUG_printf("\n"); #endif size_t this_name_l; const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l); const char *p = this_name + this_name_l; if (!is_pkg) { // We have module, but relative imports are anchored at package, so // go there. chop_component(this_name, &p); } while (level--) { chop_component(this_name, &p); } // We must have some component left over to import from if (p == this_name) { mp_raise_ValueError("cannot perform relative import"); } uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len); char *new_mod = mp_local_alloc(new_mod_l); memcpy(new_mod, this_name, p - this_name); if (mod_len != 0) { new_mod[p - this_name] = '.'; memcpy(new_mod + (p - this_name) + 1, mod_str, mod_len); } qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l); mp_local_free(new_mod); DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q)); module_name = MP_OBJ_NEW_QSTR(new_mod_q); mod_str = qstr_str(new_mod_q); mod_len = new_mod_l; } // check if module already exists qstr module_name_qstr = mp_obj_str_get_qstr(module_name); mp_obj_t module_obj = mp_module_get(module_name_qstr); if (module_obj != MP_OBJ_NULL) { DEBUG_printf("Module already loaded\n"); // If it's not a package, return module right away char *p = strchr(mod_str, '.'); if (p == NULL) { return module_obj; } // If fromlist is not empty, return leaf module if (fromtuple != mp_const_none) { return module_obj; } // Otherwise, we need to return top-level package qstr pkg_name = qstr_from_strn(mod_str, p - mod_str); return mp_module_get(pkg_name); } DEBUG_printf("Module not yet loaded\n"); uint last = 0; VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX) module_obj = MP_OBJ_NULL; mp_obj_t top_module_obj = MP_OBJ_NULL; mp_obj_t outer_module_obj = MP_OBJ_NULL; uint i; for (i = 1; i <= mod_len; i++) { if (i == mod_len || mod_str[i] == '.') { // create a qstr for the module name up to this depth qstr mod_name = qstr_from_strn(mod_str, i); DEBUG_printf("Processing module: %s\n", qstr_str(mod_name)); DEBUG_printf("Previous path: =%.*s=\n", vstr_len(&path), vstr_str(&path)); // find the file corresponding to the module name mp_import_stat_t stat; if (vstr_len(&path) == 0) { // first module in the dotted-name; search for a directory or file stat = find_file(mod_str, i, &path); } else { // latter module in the dotted-name; append to path vstr_add_char(&path, PATH_SEP_CHAR); vstr_add_strn(&path, mod_str + last, i - last); stat = stat_dir_or_file(&path); } DEBUG_printf("Current path: %.*s\n", vstr_len(&path), vstr_str(&path)); if (stat == MP_IMPORT_STAT_NO_EXIST) { #if MICROPY_MODULE_WEAK_LINKS // check if there is a weak link to this module if (i == mod_len) { mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP); if (el == NULL) { goto no_exist; } // found weak linked module module_obj = el->value; mp_module_call_init(mod_name, module_obj); } else { no_exist: #else { #endif // couldn't find the file, so fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_ImportError, "module not found"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%q'", mod_name)); } } } else { // found the file, so get the module module_obj = mp_module_get(mod_name); } if (module_obj == MP_OBJ_NULL) { // module not already loaded, so load it! module_obj = mp_obj_new_module(mod_name); // if args[3] (fromtuple) has magic value False, set up // this module for command-line "-m" option (set module's // name to __main__ instead of real name). Do this only // for *modules* however - packages never have their names // replaced, instead they're -m'ed using a special __main__ // submodule in them. (This all apparently is done to not // touch package name itself, which is important for future // imports). if (i == mod_len && fromtuple == mp_const_false && stat != MP_IMPORT_STAT_DIR) { mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj); mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); #if MICROPY_CPYTHON_COMPAT // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules). mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj); // Store real name in "__main__" attribute. Chosen semi-randonly, to reuse existing qstr's. mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name)); #endif } if (stat == MP_IMPORT_STAT_DIR) { DEBUG_printf("%.*s is dir\n", vstr_len(&path), vstr_str(&path)); // https://docs.python.org/3/reference/import.html // "Specifically, any module that contains a __path__ attribute is considered a package." mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path))); size_t orig_path_len = path.len; vstr_add_char(&path, PATH_SEP_CHAR); vstr_add_str(&path, "__init__.py"); if (stat_file_py_or_mpy(&path) != MP_IMPORT_STAT_FILE) { //mp_warning("%s is imported as namespace package", vstr_str(&path)); } else { do_load(module_obj, &path); } path.len = orig_path_len; } else { // MP_IMPORT_STAT_FILE do_load(module_obj, &path); // This should be the last component in the import path. If there are // remaining components then it's an ImportError because the current path // (the module that was just loaded) is not a package. This will be caught // on the next iteration because the file will not exist. } } if (outer_module_obj != MP_OBJ_NULL) { qstr s = qstr_from_strn(mod_str + last, i - last); mp_store_attr(outer_module_obj, s, module_obj); } outer_module_obj = module_obj; if (top_module_obj == MP_OBJ_NULL) { top_module_obj = module_obj; } last = i + 1; } }
int /* O - Number of options found */ cupsParseOptions( const char *arg, /* I - Argument to parse */ int num_options, /* I - Number of options */ cups_option_t **options) /* O - Options found */ { char *copyarg, /* Copy of input string */ *ptr, /* Pointer into string */ *name, /* Pointer to name */ *value, /* Pointer to value */ sep, /* Separator character */ quote; /* Quote character */ DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, options)); /* * Range check input... */ if (!arg) { DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); } if (!options || num_options < 0) { DEBUG_puts("1cupsParseOptions: Returning 0"); return (0); } /* * Make a copy of the argument string and then divide it up... */ if ((copyarg = strdup(arg)) == NULL) { DEBUG_puts("1cupsParseOptions: Unable to copy arg string"); DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); } if (*copyarg == '{') { /* * Remove surrounding {} so we can parse "{name=value ... name=value}"... */ if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}') { *ptr = '\0'; ptr = copyarg + 1; } else ptr = copyarg; } else ptr = copyarg; /* * Skip leading spaces... */ while (_cups_isspace(*ptr)) ptr ++; /* * Loop through the string... */ while (*ptr != '\0') { /* * Get the name up to a SPACE, =, or end-of-string... */ name = ptr; while (!strchr("\f\n\r\t\v =", *ptr) && *ptr) ptr ++; /* * Avoid an empty name... */ if (ptr == name) break; /* * Skip trailing spaces... */ while (_cups_isspace(*ptr)) *ptr++ = '\0'; if ((sep = *ptr) == '=') *ptr++ = '\0'; DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name)); if (sep != '=') { /* * Boolean option... */ if (!_cups_strncasecmp(name, "no", 2)) num_options = cupsAddOption(name + 2, "false", num_options, options); else num_options = cupsAddOption(name, "true", num_options, options); continue; } /* * Remove = and parse the value... */ value = ptr; while (*ptr && !_cups_isspace(*ptr)) { if (*ptr == ',') ptr ++; else if (*ptr == '\'' || *ptr == '\"') { /* * Quoted string constant... */ quote = *ptr; _cups_strcpy(ptr, ptr + 1); while (*ptr != quote && *ptr) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); ptr ++; } if (*ptr) _cups_strcpy(ptr, ptr + 1); } else if (*ptr == '{') { /* * Collection value... */ int depth; for (depth = 0; *ptr; ptr ++) { if (*ptr == '{') depth ++; else if (*ptr == '}') { depth --; if (!depth) { ptr ++; break; } } else if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); } } else { /* * Normal space-delimited string... */ while (*ptr && !_cups_isspace(*ptr)) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); ptr ++; } } } if (*ptr != '\0') *ptr++ = '\0'; DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value)); /* * Skip trailing whitespace... */ while (_cups_isspace(*ptr)) ptr ++; /* * Add the string value... */ num_options = cupsAddOption(name, value, num_options, options); } /* * Free the copy of the argument we made and return the number of options * found. */ free(copyarg); DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); }
static int /* O - Index of match */ cups_find_option( const char *name, /* I - Option name */ int num_options, /* I - Number of options */ cups_option_t *options, /* I - Options */ int prev, /* I - Previous index */ int *rdiff) /* O - Difference of match */ { int left, /* Low mark for binary search */ right, /* High mark for binary search */ current, /* Current index */ diff; /* Result of comparison */ cups_option_t key; /* Search key */ DEBUG_printf(("7cups_find_option(name=\"%s\", num_options=%d, options=%p, " "prev=%d, rdiff=%p)", name, num_options, options, prev, rdiff)); #ifdef DEBUG for (left = 0; left < num_options; left ++) DEBUG_printf(("9cups_find_option: options[%d].name=\"%s\", .value=\"%s\"", left, options[left].name, options[left].value)); #endif /* DEBUG */ key.name = (char *)name; if (prev >= 0) { /* * Start search on either side of previous... */ if ((diff = cups_compare_options(&key, options + prev)) == 0 || (diff < 0 && prev == 0) || (diff > 0 && prev == (num_options - 1))) { *rdiff = diff; return (prev); } else if (diff < 0) { /* * Start with previous on right side... */ left = 0; right = prev; } else { /* * Start wih previous on left side... */ left = prev; right = num_options - 1; } } else { /* * Start search in the middle... */ left = 0; right = num_options - 1; } do { current = (left + right) / 2; diff = cups_compare_options(&key, options + current); if (diff == 0) break; else if (diff < 0) right = current; else left = current; } while ((right - left) > 1); if (diff != 0) { /* * Check the last 1 or 2 elements... */ if ((diff = cups_compare_options(&key, options + left)) <= 0) current = left; else { diff = cups_compare_options(&key, options + right); current = right; } } /* * Return the closest destination and the difference... */ *rdiff = diff; return (current); }
cups_dentry_t * /* O - Directory entry or @code NULL@ when there are no more */ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */ { struct dirent *entry; /* Pointer to entry */ char filename[1024]; /* Full filename */ # ifdef HAVE_PTHREAD_H char buffer[sizeof(struct dirent) + 1024]; /* Directory entry buffer */ # endif /* HAVE_PTHREAD_H */ DEBUG_printf(("2cupsDirRead(dp=%p)", (void *)dp)); /* * Range check input... */ if (!dp) return (NULL); /* * Try reading an entry that is not "." or ".."... */ for (;;) { # ifdef HAVE_PTHREAD_H /* * Read the next entry using the reentrant version of readdir... */ if (readdir_r(dp->dir, (struct dirent *)buffer, &entry)) { DEBUG_printf(("3cupsDirRead: readdir_r() failed - %s\n", strerror(errno))); return (NULL); } if (!entry) { DEBUG_puts("3cupsDirRead: readdir_r() returned a NULL pointer!"); return (NULL); } DEBUG_printf(("4cupsDirRead: readdir_r() returned \"%s\"...", entry->d_name)); # else /* * Read the next entry using the original version of readdir... */ if ((entry = readdir(dp->dir)) == NULL) { DEBUG_puts("3cupsDirRead: readdir() returned a NULL pointer!"); return (NULL); } DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name)); # endif /* HAVE_PTHREAD_H */ /* * Skip "." and ".."... */ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue; /* * Copy the name over and get the file information... */ strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename)); snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name); if (stat(filename, &(dp->entry.fileinfo))) { DEBUG_printf(("3cupsDirRead: stat() failed for \"%s\" - %s...", filename, strerror(errno))); continue; } /* * Return the entry... */ return (&(dp->entry)); } }
void _cupsRasterAddError(const char *f, /* I - Printf-style error message */ ...) /* I - Additional arguments as needed */ { _cups_raster_error_t *buf = get_error_buffer(); /* Error buffer */ va_list ap; /* Pointer to additional arguments */ char s[2048]; /* Message string */ ssize_t bytes; /* Bytes in message string */ DEBUG_printf(("_cupsRasterAddError(f=\"%s\", ...)", f)); va_start(ap, f); bytes = vsnprintf(s, sizeof(s), f, ap); va_end(ap); if (bytes <= 0) return; DEBUG_printf(("1_cupsRasterAddError: %s", s)); bytes ++; if ((size_t)bytes >= sizeof(s)) return; if (bytes > (ssize_t)(buf->end - buf->current)) { /* * Allocate more memory... */ char *temp; /* New buffer */ size_t size; /* Size of buffer */ size = (size_t)(buf->end - buf->start + 2 * bytes + 1024); if (buf->start) temp = realloc(buf->start, size); else temp = malloc(size); if (!temp) return; /* * Update pointers... */ buf->end = temp + size; buf->current = temp + (buf->current - buf->start); buf->start = temp; } /* * Append the message to the end of the current string... */ memcpy(buf->current, s, (size_t)bytes); buf->current += bytes - 1; }
int /* O - 1 on success, 0 on failure */ pwgFormatSizeName(char *keyword, /* I - Keyword buffer */ size_t keysize, /* I - Size of keyword buffer */ const char *prefix, /* I - Prefix for PWG size or @code NULL@ for automatic */ const char *name, /* I - Size name or @code NULL@ */ int width, /* I - Width of page in 2540ths */ int length, /* I - Length of page in 2540ths */ const char *units) /* I - Units - "in", "mm", or @code NULL@ for automatic */ { char usize[12 + 1 + 12 + 3], /* Unit size: NNNNNNNNNNNNxNNNNNNNNNNNNuu */ *uptr; /* Pointer into unit size */ char *(*format)(char *, size_t, int); /* Formatting function */ /* * Range check input... */ DEBUG_printf(("pwgFormatSize(keyword=%p, keysize=" CUPS_LLFMT ", prefix=\"%s\", name=\"%s\", width=%d, length=%d, units=\"%s\")", (void *)keyword, CUPS_LLCAST keysize, prefix, name, width, length, units)); if (keyword) *keyword = '\0'; if (!keyword || keysize < 32 || width < 0 || length < 0 || (units && strcmp(units, "in") && strcmp(units, "mm"))) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid media name arguments."), 1); return (0); } if (name) { /* * Validate name... */ const char *nameptr; /* Pointer into name */ for (nameptr = name; *nameptr; nameptr ++) if (!(*nameptr >= 'a' && *nameptr <= 'z') && !(*nameptr >= '0' && *nameptr <= '9') && *nameptr != '.' && *nameptr != '-') { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid media name arguments."), 1); return (0); } } else name = usize; if (prefix && !strcmp(prefix, "disc")) width = 4000; /* Disc sizes use hardcoded 40mm inner diameter */ if (!units) { if ((width % 635) == 0 && (length % 635) == 0) { /* * Use inches since the size is a multiple of 1/4 inch. */ units = "in"; } else { /* * Use millimeters since the size is not a multiple of 1/4 inch. */ units = "mm"; } } if (!strcmp(units, "in")) { format = pwg_format_inches; if (!prefix) prefix = "oe"; } else { format = pwg_format_millimeters; if (!prefix) prefix = "om"; } /* * Format the size string... */ uptr = usize; (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), width); uptr += strlen(uptr); *uptr++ = 'x'; (*format)(uptr, sizeof(usize) - (size_t)(uptr - usize), length); uptr += strlen(uptr); /* * Safe because usize can hold up to 12 + 1 + 12 + 4 bytes. */ memcpy(uptr, units, 3); /* * Format the name... */ snprintf(keyword, keysize, "%s_%s_%s", prefix, name, usize); return (1); }
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { // This function is pretty complicated. It's main aim is to be efficient in speed and RAM // usage for the common case of positional only args. // // extra_args layout: def_args, var_arg tuple, kwonly args, var_kw dict DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw); DEBUG_printf("Input pos args: "); dump_args(args, n_args); DEBUG_printf("Input kw args: "); dump_args(args + n_args, n_kw * 2); mp_obj_fun_bc_t *self = self_in; DEBUG_printf("Func n_def_args: %d\n", self->n_def_args); const mp_obj_t *kwargs = args + n_args; mp_obj_t *extra_args = self->extra_args + self->n_def_args; uint n_extra_args = 0; // check positional arguments if (n_args > self->n_pos_args) { // given more than enough arguments if (!self->takes_var_args) { fun_pos_args_mismatch(self, self->n_pos_args, n_args); } // put extra arguments in varargs tuple *extra_args = mp_obj_new_tuple(n_args - self->n_pos_args, args + self->n_pos_args); n_extra_args = 1; n_args = self->n_pos_args; } else { if (self->takes_var_args) { DEBUG_printf("passing empty tuple as *args\n"); *extra_args = mp_const_empty_tuple; n_extra_args = 1; } // Apply processing and check below only if we don't have kwargs, // otherwise, kw handling code below has own extensive checks. if (n_kw == 0) { if (n_args >= self->n_pos_args - self->n_def_args) { // given enough arguments, but may need to use some default arguments extra_args -= self->n_pos_args - n_args; n_extra_args += self->n_pos_args - n_args; } else { fun_pos_args_mismatch(self, self->n_pos_args - self->n_def_args, n_args); } } } // check keyword arguments if (n_kw != 0) { // We cannot use dynamically-sized array here, because GCC indeed // deallocates it on leaving defining scope (unlike most static stack allocs). // So, we have 2 choices: allocate it unconditionally at the top of function // (wastes stack), or use alloca which is guaranteed to dealloc on func exit. //mp_obj_t flat_args[self->n_args]; mp_obj_t *flat_args = alloca((self->n_pos_args + self->n_kwonly_args) * sizeof(mp_obj_t)); for (int i = self->n_pos_args + self->n_kwonly_args - 1; i >= 0; i--) { flat_args[i] = MP_OBJ_NULL; } memcpy(flat_args, args, sizeof(*args) * n_args); DEBUG_printf("Initial args: "); dump_args(flat_args, self->n_pos_args + self->n_kwonly_args); mp_obj_t dict = MP_OBJ_NULL; if (self->takes_kw_args) { dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0? } for (uint i = 0; i < n_kw; i++) { qstr arg_name = MP_OBJ_QSTR_VALUE(kwargs[2 * i]); for (uint j = 0; j < self->n_pos_args + self->n_kwonly_args; j++) { if (arg_name == self->args[j]) { if (flat_args[j] != MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function got multiple values for argument '%s'", qstr_str(arg_name))); } flat_args[j] = kwargs[2 * i + 1]; goto continue2; } } // Didn't find name match with positional args if (!self->takes_kw_args) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); } mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]); continue2:; } DEBUG_printf("Args with kws flattened: "); dump_args(flat_args, self->n_pos_args + self->n_kwonly_args); // Now fill in defaults for positional args mp_obj_t *d = &flat_args[self->n_pos_args - 1]; mp_obj_t *s = &self->extra_args[self->n_def_args - 1]; for (int i = self->n_def_args; i > 0; i--, d--, s--) { if (*d == MP_OBJ_NULL) { *d = *s; } } DEBUG_printf("Args after filling defaults: "); dump_args(flat_args, self->n_pos_args + self->n_kwonly_args); // Check that all mandatory positional args are specified while (d >= flat_args) { if (*d-- == MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function missing required positional argument #%d", d - flat_args)); } } // Check that all mandatory keyword args are specified for (int i = 0; i < self->n_kwonly_args; i++) { if (flat_args[self->n_pos_args + i] == MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function missing required keyword argument '%s'", qstr_str(self->args[self->n_pos_args + i]))); } } args = flat_args; n_args = self->n_pos_args + self->n_kwonly_args; if (self->takes_kw_args) { extra_args[n_extra_args] = dict; n_extra_args += 1; } } else { // no keyword arguments given if (self->n_kwonly_args != 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function missing keyword-only argument")); } if (self->takes_kw_args) { extra_args[n_extra_args] = mp_obj_new_dict(0); n_extra_args += 1; } } mp_obj_dict_t *old_globals = mp_globals_get(); mp_globals_set(self->globals); mp_obj_t result; DEBUG_printf("Calling: args=%p, n_args=%d, extra_args=%p, n_extra_args=%d\n", args, n_args, extra_args, n_extra_args); dump_args(args, n_args); dump_args(extra_args, n_extra_args); mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code(self->bytecode, args, n_args, extra_args, n_extra_args, &result); mp_globals_set(old_globals); if (vm_return_kind == MP_VM_RETURN_NORMAL) { return result; } else { // MP_VM_RETURN_EXCEPTION nlr_raise(result); } }
char * /* O - Line read or @code NULL@ on end of file or error */ cupsFileGetConf(cups_file_t *fp, /* I - CUPS file */ char *buf, /* O - String buffer */ size_t buflen, /* I - Size of string buffer */ char **value, /* O - Pointer to value */ int *linenum) /* IO - Current line number */ { char *ptr; /* Pointer into line */ /* * Range check input... */ DEBUG_printf(("2cupsFileGetConf(fp=%p, buf=%p, buflen=" CUPS_LLFMT ", value=%p, linenum=%p)", fp, buf, CUPS_LLCAST buflen, value, linenum)); if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 2 || !value) { if (value) *value = NULL; return (NULL); } /* * Read the next non-comment line... */ *value = NULL; while (cupsFileGets(fp, buf, buflen)) { (*linenum) ++; /* * Strip any comments... */ if ((ptr = strchr(buf, '#')) != NULL) { if (ptr > buf && ptr[-1] == '\\') { // Unquote the #... _cups_strcpy(ptr - 1, ptr); } else { // Strip the comment and any trailing whitespace... while (ptr > buf) { if (!_cups_isspace(ptr[-1])) break; ptr --; } *ptr = '\0'; } } /* * Strip leading whitespace... */ for (ptr = buf; _cups_isspace(*ptr); ptr ++); if (ptr > buf) _cups_strcpy(buf, ptr); /* * See if there is anything left... */ if (buf[0]) { /* * Yes, grab any value and return... */ for (ptr = buf; *ptr; ptr ++) if (_cups_isspace(*ptr)) break; if (*ptr) { /* * Have a value, skip any other spaces... */ while (_cups_isspace(*ptr)) *ptr++ = '\0'; if (*ptr) *value = ptr; /* * Strip trailing whitespace and > for lines that begin with <... */ ptr += strlen(ptr) - 1; if (buf[0] == '<' && *ptr == '>') *ptr-- = '\0'; else if (buf[0] == '<' && *ptr != '>') { /* * Syntax error... */ *value = NULL; return (buf); } while (ptr > *value && _cups_isspace(*ptr)) *ptr-- = '\0'; } /* * Return the line... */ return (buf); } } return (NULL); }
size_t /* O - Number of bytes on line or 0 on end of file */ cupsFileGetLine(cups_file_t *fp, /* I - File to read from */ char *buf, /* I - Buffer */ size_t buflen) /* I - Size of buffer */ { int ch; /* Character from file */ char *ptr, /* Current position in line buffer */ *end; /* End of line buffer */ /* * Range check input... */ DEBUG_printf(("2cupsFileGetLine(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")", fp, buf, CUPS_LLCAST buflen)); if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 3) return (0); /* * Now loop until we have a valid line... */ for (ptr = buf, end = buf + buflen - 2; ptr < end ;) { if (fp->ptr >= fp->end) if (cups_fill(fp) <= 0) break; *ptr++ = ch = *(fp->ptr)++; fp->pos ++; if (ch == '\r') { /* * Check for CR LF... */ if (fp->ptr >= fp->end) if (cups_fill(fp) <= 0) break; if (*(fp->ptr) == '\n') { *ptr++ = *(fp->ptr)++; fp->pos ++; } break; } else if (ch == '\n') { /* * Line feed ends a line... */ break; } } *ptr = '\0'; DEBUG_printf(("4cupsFileGetLine: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); return (ptr - buf); }
ipp_status_t /* O - Request status - @code IPP_OK@ on success. */ cupsGetDevices( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ int timeout, /* I - Timeout in seconds or @code CUPS_TIMEOUT_DEFAULT@ */ const char *include_schemes, /* I - Comma-separated URI schemes to include or @code CUPS_INCLUDE_ALL@ */ const char *exclude_schemes, /* I - Comma-separated URI schemes to exclude or @code CUPS_EXCLUDE_NONE@ */ cups_device_cb_t callback, /* I - Callback function */ void *user_data) /* I - User data pointer */ { ipp_t *request, /* CUPS-Get-Devices request */ *response; /* CUPS-Get-Devices response */ ipp_attribute_t *attr; /* Current attribute */ const char *device_class, /* device-class value */ *device_id, /* device-id value */ *device_info, /* device-info value */ *device_location, /* device-location value */ *device_make_and_model, /* device-make-and-model value */ *device_uri; /* device-uri value */ int blocking; /* Current blocking-IO mode */ cups_option_t option; /* in/exclude-schemes option */ http_status_t status; /* HTTP status of request */ ipp_state_t state; /* IPP response state */ /* * Range check input... */ DEBUG_printf(("cupsGetDevices(http=%p, timeout=%d, include_schemes=\"%s\", exclude_schemes=\"%s\", callback=%p, user_data=%p)", (void *)http, timeout, include_schemes, exclude_schemes, (void *)callback, user_data)); if (!callback) return (IPP_STATUS_ERROR_INTERNAL); if (!http) http = _cupsConnect(); if (!http) return (IPP_STATUS_ERROR_SERVICE_UNAVAILABLE); /* * Create a CUPS-Get-Devices request... */ request = ippNewRequest(IPP_OP_CUPS_GET_DEVICES); if (timeout > 0) ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "timeout", timeout); if (include_schemes) { option.name = "include-schemes"; option.value = (char *)include_schemes; cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); } if (exclude_schemes) { option.name = "exclude-schemes"; option.value = (char *)exclude_schemes; cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); } /* * Send the request and do any necessary authentication... */ do { DEBUG_puts("2cupsGetDevices: Sending request..."); status = cupsSendRequest(http, request, "/", ippLength(request)); DEBUG_puts("2cupsGetDevices: Waiting for response status..."); while (status == HTTP_STATUS_CONTINUE) status = httpUpdate(http); if (status != HTTP_STATUS_OK) { httpFlush(http); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * See if we can do authentication... */ DEBUG_puts("2cupsGetDevices: Need authorization..."); if (!cupsDoAuthentication(http, "POST", "/")) httpReconnect2(http, 30000, NULL); else { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; } } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* * Force a reconnect with encryption... */ DEBUG_puts("2cupsGetDevices: Need encryption..."); if (!httpReconnect2(http, 30000, NULL)) httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); } #endif /* HAVE_SSL */ } } while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED); DEBUG_printf(("2cupsGetDevices: status=%d", status)); ippDelete(request); if (status != HTTP_STATUS_OK) { _cupsSetHTTPError(status); return (cupsLastError()); } /* * Read the response in non-blocking mode... */ blocking = httpGetBlocking(http); httpBlocking(http, 0); response = ippNew(); device_class = NULL; device_id = NULL; device_info = NULL; device_location = ""; device_make_and_model = NULL; device_uri = NULL; attr = NULL; DEBUG_puts("2cupsGetDevices: Reading response..."); do { if ((state = ippRead(http, response)) == IPP_STATE_ERROR) break; DEBUG_printf(("2cupsGetDevices: state=%d, response->last=%p", state, (void *)response->last)); if (!response->attrs) continue; while (attr != response->last) { if (!attr) attr = response->attrs; else attr = attr->next; DEBUG_printf(("2cupsGetDevices: attr->name=\"%s\", attr->value_tag=%d", attr->name, attr->value_tag)); if (!attr->name) { if (device_class && device_id && device_info && device_make_and_model && device_uri) (*callback)(device_class, device_id, device_info, device_make_and_model, device_uri, device_location, user_data); device_class = NULL; device_id = NULL; device_info = NULL; device_location = ""; device_make_and_model = NULL; device_uri = NULL; } else if (!strcmp(attr->name, "device-class") && attr->value_tag == IPP_TAG_KEYWORD) device_class = attr->values[0].string.text; else if (!strcmp(attr->name, "device-id") && attr->value_tag == IPP_TAG_TEXT) device_id = attr->values[0].string.text; else if (!strcmp(attr->name, "device-info") && attr->value_tag == IPP_TAG_TEXT) device_info = attr->values[0].string.text; else if (!strcmp(attr->name, "device-location") && attr->value_tag == IPP_TAG_TEXT) device_location = attr->values[0].string.text; else if (!strcmp(attr->name, "device-make-and-model") && attr->value_tag == IPP_TAG_TEXT) device_make_and_model = attr->values[0].string.text; else if (!strcmp(attr->name, "device-uri") && attr->value_tag == IPP_TAG_URI) device_uri = attr->values[0].string.text; } } while (state != IPP_STATE_DATA); DEBUG_printf(("2cupsGetDevices: state=%d, response->last=%p", state, (void *)response->last)); if (device_class && device_id && device_info && device_make_and_model && device_uri) (*callback)(device_class, device_id, device_info, device_make_and_model, device_uri, device_location, user_data); /* * Set the IPP status and return... */ httpBlocking(http, blocking); httpFlush(http); if (status == HTTP_STATUS_ERROR) _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(http->error), 0); else { attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT); DEBUG_printf(("cupsGetDevices: status-code=%s, status-message=\"%s\"", ippErrorString(response->request.status.status_code), attr ? attr->values[0].string.text : "")); _cupsSetError(response->request.status.status_code, attr ? attr->values[0].string.text : ippErrorString(response->request.status.status_code), 0); } ippDelete(response); return (cupsLastError()); }
const char * /* O - Full path to file or @code NULL@ if not found */ cupsFileFind(const char *filename, /* I - File to find */ const char *path, /* I - Colon/semicolon-separated path */ int executable, /* I - 1 = executable files, 0 = any file/dir */ char *buffer, /* I - Filename buffer */ int bufsize) /* I - Size of filename buffer */ { char *bufptr, /* Current position in buffer */ *bufend; /* End of buffer */ /* * Range check input... */ DEBUG_printf(("cupsFileFind(filename=\"%s\", path=\"%s\", executable=%d, " "buffer=%p, bufsize=%d)", filename, path, executable, buffer, bufsize)); if (!filename || !buffer || bufsize < 2) return (NULL); if (!path) { /* * No path, so check current directory... */ if (!access(filename, 0)) { strlcpy(buffer, filename, bufsize); return (buffer); } else return (NULL); } /* * Now check each path and return the first match... */ bufend = buffer + bufsize - 1; bufptr = buffer; while (*path) { #ifdef WIN32 if (*path == ';' || (*path == ':' && ((bufptr - buffer) > 1 || !isalpha(buffer[0] & 255)))) #else if (*path == ';' || *path == ':') #endif /* WIN32 */ { if (bufptr > buffer && bufptr[-1] != '/' && bufptr < bufend) *bufptr++ = '/'; strlcpy(bufptr, filename, bufend - bufptr); #ifdef WIN32 if (!access(buffer, 0)) #else if (!access(buffer, executable ? X_OK : 0)) #endif /* WIN32 */ { DEBUG_printf(("1cupsFileFind: Returning \"%s\"", buffer)); return (buffer); } bufptr = buffer; } else if (bufptr < bufend) *bufptr++ = *path; path ++; } /* * Check the last path... */ if (bufptr > buffer && bufptr[-1] != '/' && bufptr < bufend) *bufptr++ = '/'; strlcpy(bufptr, filename, bufend - bufptr); if (!access(buffer, 0)) { DEBUG_printf(("1cupsFileFind: Returning \"%s\"", buffer)); return (buffer); } else { DEBUG_puts("1cupsFileFind: Returning NULL"); return (NULL); } }
void cupsdAddCert(int pid, /* I - Process ID */ const char *username, /* I - Username */ int type) /* I - AuthType for username */ { int i; /* Looping var */ cupsd_cert_t *cert; /* Current certificate */ int fd; /* Certificate file */ char filename[1024]; /* Certificate filename */ static const char hex[] = "0123456789ABCDEF"; /* Hex constants... */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: Adding certificate for PID %d", pid); /* * Allocate memory for the certificate... */ if ((cert = calloc(sizeof(cupsd_cert_t), 1)) == NULL) return; /* * Fill in the certificate information... */ cert->pid = pid; cert->type = type; strlcpy(cert->username, username, sizeof(cert->username)); for (i = 0; i < 32; i ++) cert->certificate[i] = hex[CUPS_RAND() & 15]; /* * Save the certificate to a file readable only by the User and Group * (or root and SystemGroup for PID == 0)... */ snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid); unlink(filename); if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create certificate file %s - %s", filename, strerror(errno)); free(cert); return; } if (pid == 0) { #ifdef HAVE_ACL_INIT acl_t acl; /* ACL information */ acl_entry_t entry; /* ACL entry */ acl_permset_t permset; /* Permissions */ # ifdef HAVE_MBR_UID_TO_UUID uuid_t group; /* Group ID */ # endif /* HAVE_MBR_UID_TO_UUID */ static int acls_not_supported = 0; /* Only warn once */ #endif /* HAVE_ACL_INIT */ /* * Root certificate... */ fchmod(fd, 0440); fchown(fd, RunUser, SystemGroupIDs[0]); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d", NumSystemGroups); #ifdef HAVE_ACL_INIT if (NumSystemGroups > 1) { /* * Set POSIX ACLs for the root certificate so that all system * groups can access it... */ int j; /* Looping var */ # ifdef HAVE_MBR_UID_TO_UUID /* * On MacOS X, ACLs use UUIDs instead of GIDs... */ acl = acl_init(NumSystemGroups - 1); for (i = 1; i < NumSystemGroups; i ++) { /* * Add each group ID to the ACL... */ for (j = 0; j < i; j ++) if (SystemGroupIDs[j] == SystemGroupIDs[i]) break; if (j < i) continue; /* Skip duplicate groups */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ_DATA); acl_set_tag_type(entry, ACL_EXTENDED_ALLOW); mbr_gid_to_uuid((gid_t)SystemGroupIDs[i], group); acl_set_qualifier(entry, &group); acl_set_permset(entry, permset); } # else /* * POSIX ACLs need permissions for owner, group, other, and mask * in addition to the rest of the system groups... */ acl = acl_init(NumSystemGroups + 3); /* Owner */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_USER_OBJ); acl_set_permset(entry, permset); /* Group */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_GROUP_OBJ); acl_set_permset(entry, permset); /* Others */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, 0); acl_set_tag_type(entry, ACL_OTHER); acl_set_permset(entry, permset); /* Mask */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_MASK); acl_set_permset(entry, permset); for (i = 1; i < NumSystemGroups; i ++) { /* * Add each group ID to the ACL... */ for (j = 0; j < i; j ++) if (SystemGroupIDs[j] == SystemGroupIDs[i]) break; if (j < i) continue; /* Skip duplicate groups */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_GROUP); acl_set_qualifier(entry, SystemGroupIDs + i); acl_set_permset(entry, permset); } if (acl_valid(acl)) { char *text, *textptr; /* Temporary string */ cupsdLogMessage(CUPSD_LOG_ERROR, "ACL did not validate: %s", strerror(errno)); text = acl_to_text(acl, NULL); for (textptr = strchr(text, '\n'); textptr; textptr = strchr(textptr + 1, '\n')) *textptr = ','; cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text); acl_free(text); } # endif /* HAVE_MBR_UID_TO_UUID */ if (acl_set_fd(fd, acl)) { if (errno != EOPNOTSUPP || !acls_not_supported) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set ACLs on root certificate \"%s\" - %s", filename, strerror(errno)); if (errno == EOPNOTSUPP) acls_not_supported = 1; } acl_free(acl); } #endif /* HAVE_ACL_INIT */ RootCertTime = time(NULL); } else { /* * CGI certificate... */ fchmod(fd, 0400); fchown(fd, User, Group); } DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username, cert->certificate)); write(fd, cert->certificate, strlen(cert->certificate)); close(fd); /* * Insert the certificate at the front of the list... */ cert->next = Certs; Certs = cert; }
void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { if (MP_STATE_MEM(gc_lock_depth) > 0) { return NULL; } // check for pure allocation if (ptr_in == NULL) { return gc_alloc(n_bytes, false); } // check for pure free if (n_bytes == 0) { gc_free(ptr_in); return NULL; } void *ptr = ptr_in; // sanity check the ptr if (!VERIFY_PTR(ptr)) { return NULL; } // get first block size_t block = BLOCK_FROM_PTR(ptr); // sanity check the ptr is pointing to the head of a block if (ATB_GET_KIND(block) != AT_HEAD) { return NULL; } // compute number of new blocks that are requested size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; // Get the total number of consecutive blocks that are already allocated to // this chunk of memory, and then count the number of free blocks following // it. Stop if we reach the end of the heap, or if we find enough extra // free blocks to satisfy the realloc. Note that we need to compute the // total size of the existing memory chunk so we can correctly and // efficiently shrink it (see below for shrinking code). size_t n_free = 0; size_t n_blocks = 1; // counting HEAD block size_t max_block = MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; for (size_t bl = block + n_blocks; bl < max_block; bl++) { byte block_type = ATB_GET_KIND(bl); if (block_type == AT_TAIL) { n_blocks++; continue; } if (block_type == AT_FREE) { n_free++; if (n_blocks + n_free >= new_blocks) { // stop as soon as we find enough blocks for n_bytes break; } continue; } break; } // return original ptr if it already has the requested number of blocks if (new_blocks == n_blocks) { return ptr_in; } // check if we can shrink the allocated area if (new_blocks < n_blocks) { // free unneeded tail blocks for (size_t bl = block + new_blocks, count = n_blocks - new_blocks; count > 0; bl++, count--) { ATB_ANY_TO_FREE(bl); } // set the last_free pointer to end of this block if it's earlier in the heap if ((block + new_blocks) / BLOCKS_PER_ATB < MP_STATE_MEM(gc_last_free_atb_index)) { MP_STATE_MEM(gc_last_free_atb_index) = (block + new_blocks) / BLOCKS_PER_ATB; } #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); #endif return ptr_in; } // check if we can expand in place if (new_blocks <= n_blocks + n_free) { // mark few more blocks as used tail for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) { assert(ATB_GET_KIND(bl) == AT_FREE); ATB_FREE_TO_TAIL(bl); } // zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc) memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes); #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); #endif return ptr_in; } if (!allow_move) { // not allowed to move memory block so return failure return NULL; } // can't resize inplace; try to find a new contiguous chain void *ptr_out = gc_alloc(n_bytes, #if MICROPY_ENABLE_FINALISER FTB_GET(block) #else false #endif ); // check that the alloc succeeded if (ptr_out == NULL) { return NULL; } DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out); memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK); gc_free(ptr_in); return ptr_out; }
void *gc_alloc(size_t n_bytes, bool has_finaliser) { size_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK; DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks); // check if GC is locked if (MP_STATE_MEM(gc_lock_depth) > 0) { return NULL; } // check for 0 allocation if (n_blocks == 0) { return NULL; } size_t i; size_t end_block; size_t start_block; size_t n_free = 0; int collected = !MP_STATE_MEM(gc_auto_collect_enabled); for (;;) { // look for a run of n_blocks available blocks for (i = MP_STATE_MEM(gc_last_free_atb_index); i < MP_STATE_MEM(gc_alloc_table_byte_len); i++) { byte a = MP_STATE_MEM(gc_alloc_table_start)[i]; if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; } if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; } if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; } if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; } } // nothing found! if (collected) { return NULL; } DEBUG_printf("gc_alloc(" UINT_FMT "): no free mem, triggering GC\n", n_bytes); gc_collect(); collected = 1; } // found, ending at block i inclusive found: // get starting and end blocks, both inclusive end_block = i; start_block = i - n_free + 1; // Set last free ATB index to block after last block we found, for start of // next scan. To reduce fragmentation, we only do this if we were looking // for a single free block, which guarantees that there are no free blocks // before this one. Also, whenever we free or shink a block we must check // if this index needs adjusting (see gc_realloc and gc_free). if (n_free == 1) { MP_STATE_MEM(gc_last_free_atb_index) = (i + 1) / BLOCKS_PER_ATB; } // mark first block as used head ATB_FREE_TO_HEAD(start_block); // mark rest of blocks as used tail // TODO for a run of many blocks can make this more efficient for (size_t bl = start_block + 1; bl <= end_block; bl++) { ATB_FREE_TO_TAIL(bl); } // get pointer to first block void *ret_ptr = (void*)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK); DEBUG_printf("gc_alloc(%p)\n", ret_ptr); // zero out the additional bytes of the newly allocated blocks // This is needed because the blocks may have previously held pointers // to the heap and will not be set to something else if the caller // doesn't actually use the entire block. As such they will continue // to point to the heap and may prevent other blocks from being reclaimed. memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes); #if MICROPY_ENABLE_FINALISER if (has_finaliser) { // clear type pointer in case it is never set ((mp_obj_base_t*)ret_ptr)->type = NULL; // set mp_obj flag only if it has a finaliser FTB_SET(start_block); } #else (void)has_finaliser; #endif #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); #endif return ret_ptr; }
STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { lwip_socket_obj_t *socket = self_in; mp_uint_t ret; if (request == MP_STREAM_POLL) { uintptr_t flags = arg; ret = 0; if (flags & MP_STREAM_POLL_RD && socket->incoming.pbuf != NULL) { ret |= MP_STREAM_POLL_RD; } // Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf if (flags & MP_STREAM_POLL_WR && socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) { ret |= MP_STREAM_POLL_WR; } if (socket->state == STATE_NEW) { // New sockets are not connected so set HUP ret |= flags & MP_STREAM_POLL_HUP; } else if (socket->state == STATE_PEER_CLOSED) { // Peer-closed socket is both readable and writable: read will // return EOF, write - error. Without this poll will hang on a // socket which was closed by peer. ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR); } else if (socket->state == ERR_RST) { // Socket was reset by peer, a write will return an error ret |= flags & (MP_STREAM_POLL_WR | MP_STREAM_POLL_HUP); } else if (socket->state < 0) { // Socket in some other error state, use catch-all ERR flag // TODO: may need to set other return flags here ret |= flags & MP_STREAM_POLL_ERR; } } else if (request == MP_STREAM_CLOSE) { bool socket_is_listener = false; if (socket->pcb.tcp == NULL) { return 0; } switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { if (socket->pcb.tcp->state == LISTEN) { socket_is_listener = true; } if (tcp_close(socket->pcb.tcp) != ERR_OK) { DEBUG_printf("lwip_close: had to call tcp_abort()\n"); tcp_abort(socket->pcb.tcp); } break; } case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break; //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; } socket->pcb.tcp = NULL; socket->state = _ERR_BADF; if (socket->incoming.pbuf != NULL) { if (!socket_is_listener) { pbuf_free(socket->incoming.pbuf); } else { tcp_abort(socket->incoming.connection); } socket->incoming.pbuf = NULL; } ret = 0; } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; } return ret; }
char * /* O - Line read or @code NULL@ on end of file or error */ cupsFileGets(cups_file_t *fp, /* I - CUPS file */ char *buf, /* O - String buffer */ size_t buflen) /* I - Size of string buffer */ { int ch; /* Character from file */ char *ptr, /* Current position in line buffer */ *end; /* End of line buffer */ /* * Range check input... */ DEBUG_printf(("2cupsFileGets(fp=%p, buf=%p, buflen=" CUPS_LLFMT ")", fp, buf, CUPS_LLCAST buflen)); if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 2) return (NULL); /* * Now loop until we have a valid line... */ for (ptr = buf, end = buf + buflen - 1; ptr < end ;) { if (fp->ptr >= fp->end) if (cups_fill(fp) <= 0) { if (ptr == buf) return (NULL); else break; } ch = *(fp->ptr)++; fp->pos ++; if (ch == '\r') { /* * Check for CR LF... */ if (fp->ptr >= fp->end) if (cups_fill(fp) <= 0) break; if (*(fp->ptr) == '\n') { fp->ptr ++; fp->pos ++; } break; } else if (ch == '\n') { /* * Line feed ends a line... */ break; } else *ptr++ = ch; } *ptr = '\0'; DEBUG_printf(("4cupsFileGets: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); return (buf); }
static int /* O - 1 if form data was read */ cgi_initialize_multipart( const char *boundary) /* I - Boundary string */ { char line[10240], /* MIME header line */ name[1024], /* Form variable name */ filename[1024], /* Form filename */ mimetype[1024], /* MIME media type */ bstring[256], /* Boundary string to look for */ *ptr, /* Pointer into name/filename */ *end; /* End of buffer */ int ch, /* Character from file */ fd; /* Temporary file descriptor */ size_t blen; /* Length of boundary string */ DEBUG_printf(("cgi_initialize_multipart(boundary=\"%s\")\n", boundary)); /* * Read multipart form data until we run out... */ name[0] = '\0'; filename[0] = '\0'; mimetype[0] = '\0'; snprintf(bstring, sizeof(bstring), "\r\n--%s", boundary); blen = strlen(bstring); while (fgets(line, sizeof(line), stdin)) { if (!strcmp(line, "\r\n")) { /* * End of headers, grab value... */ if (filename[0]) { /* * Read an embedded file... */ if (form_file) { /* * Remove previous file... */ cgi_unlink_file(); } /* * Allocate memory for the new file... */ if ((form_file = calloc(1, sizeof(cgi_file_t))) == NULL) return (0); form_file->name = strdup(name); form_file->filename = strdup(filename); form_file->mimetype = strdup(mimetype); fd = cupsTempFd(form_file->tempfile, sizeof(form_file->tempfile)); if (fd < 0) return (0); atexit(cgi_unlink_file); /* * Copy file data to the temp file... */ ptr = line; while ((ch = getchar()) != EOF) { *ptr++ = (char)ch; if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) { ptr -= blen; break; } if ((ptr - line - (int)blen) >= 8192) { /* * Write out the first 8k of the buffer... */ write(fd, line, 8192); memmove(line, line + 8192, (size_t)(ptr - line - 8192)); ptr -= 8192; } } /* * Write the rest of the data and close the temp file... */ if (ptr > line) write(fd, line, (size_t)(ptr - line)); close(fd); } else { /* * Just get a form variable; the current code only handles * form values up to 10k in size... */ ptr = line; end = line + sizeof(line) - 1; while ((ch = getchar()) != EOF) { if (ptr < end) *ptr++ = (char)ch; if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) { ptr -= blen; break; } } *ptr = '\0'; /* * Set the form variable... */ if ((ptr = strrchr(name, '-')) != NULL && isdigit(ptr[1] & 255)) { /* * Set a specific index in the array... */ *ptr++ = '\0'; if (line[0]) cgiSetArray(name, atoi(ptr) - 1, line); } else if (cgiGetVariable(name)) { /* * Add another element in the array... */ cgiSetArray(name, cgiGetSize(name), line); } else { /* * Just set the line... */ cgiSetVariable(name, line); } } /* * Read the rest of the current line... */ fgets(line, sizeof(line), stdin); /* * Clear the state vars... */ name[0] = '\0'; filename[0] = '\0'; mimetype[0] = '\0'; } else if (!_cups_strncasecmp(line, "Content-Disposition:", 20)) { if ((ptr = strstr(line + 20, " name=\"")) != NULL) { strlcpy(name, ptr + 7, sizeof(name)); if ((ptr = strchr(name, '\"')) != NULL) *ptr = '\0'; } if ((ptr = strstr(line + 20, " filename=\"")) != NULL) { strlcpy(filename, ptr + 11, sizeof(filename)); if ((ptr = strchr(filename, '\"')) != NULL) *ptr = '\0'; } } else if (!_cups_strncasecmp(line, "Content-Type:", 13)) { for (ptr = line + 13; isspace(*ptr & 255); ptr ++); strlcpy(mimetype, ptr, sizeof(mimetype)); for (ptr = mimetype + strlen(mimetype) - 1; ptr > mimetype && isspace(*ptr & 255); *ptr-- = '\0'); } } /* * Return 1 for "form data found"... */ return (1); }
cups_file_t * /* O - CUPS file or @code NULL@ if the file or socket cannot be opened */ cupsFileOpen(const char *filename, /* I - Name of file */ const char *mode) /* I - Open mode */ { cups_file_t *fp; /* New CUPS file */ int fd; /* File descriptor */ char hostname[1024], /* Hostname */ *portname; /* Port "name" (number or service) */ http_addrlist_t *addrlist; /* Host address list */ DEBUG_printf(("cupsFileOpen(filename=\"%s\", mode=\"%s\")", filename, mode)); /* * Range check input... */ if (!filename || !mode || (*mode != 'r' && *mode != 'w' && *mode != 'a' && *mode != 's') || (*mode == 'a' && isdigit(mode[1] & 255))) return (NULL); /* * Open the file... */ switch (*mode) { case 'a' : /* Append file */ fd = cups_open(filename, O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY); break; case 'r' : /* Read file */ fd = open(filename, O_RDONLY | O_LARGEFILE | O_BINARY, 0); break; case 'w' : /* Write file */ fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY); if (fd < 0 && errno == ENOENT) { fd = cups_open(filename, O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY); if (fd < 0 && errno == EEXIST) fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY); } if (fd >= 0) #ifdef WIN32 _chsize(fd, 0); #else ftruncate(fd, 0); #endif /* WIN32 */ break; case 's' : /* Read/write socket */ strlcpy(hostname, filename, sizeof(hostname)); if ((portname = strrchr(hostname, ':')) != NULL) *portname++ = '\0'; else return (NULL); /* * Lookup the hostname and service... */ if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL) return (NULL); /* * Connect to the server... */ if (!httpAddrConnect(addrlist, &fd)) { httpAddrFreeList(addrlist); return (NULL); } httpAddrFreeList(addrlist); break; default : /* Remove bogus compiler warning... */ return (NULL); } if (fd < 0) return (NULL); /* * Create the CUPS file structure... */ if ((fp = cupsFileOpenFd(fd, mode)) == NULL) { if (*mode == 's') closesocket(fd); else close(fd); } /* * Return it... */ return (fp); }
int write_bb_black_respond(char* fileName,char *rev) { long len; char sw[15]; char uid[60]; char ip_s[20]; char port_s[10]; char port_l[10]; char* pContent; //First read the old config FILE* fp = fopen(fileName, "rb+"); if(fp==NULL) { DEBUG_printf("open error\n"); exit(1); } fseek(fp,0,SEEK_END); len=ftell(fp); if(0 == len) { return 0; } fseek(fp,0,SEEK_SET); pContent = (char*) malloc(sizeof(char)*len+100); fread(pContent,1,len,fp); fclose(fp); cJSON *jsonroot = cJSON_Parse(pContent); //json strcpy(sw,cJSON_GetObjectItem(jsonroot,"api-switch")->valuestring); strcpy(uid,cJSON_GetObjectItem(jsonroot,"api-uid")->valuestring); strcpy(ip_s,cJSON_GetObjectItem(jsonroot,"ip_server")->valuestring); strcpy(port_s,cJSON_GetObjectItem(jsonroot,"port_server")->valuestring); strcpy(port_l,cJSON_GetObjectItem(jsonroot,"port_local")->valuestring); cJSON_Delete(jsonroot); //Write configuration, update fp = fopen(fileName, "w+"); if(fp==NULL) { DEBUG_printf("open error\n"); } cJSON *root; char *out; root=cJSON_CreateObject(); cJSON_AddStringToObject(root, "api-switch" , sw); cJSON_AddStringToObject(root, "api-uid", uid); cJSON_AddStringToObject(root, "auth", rev); cJSON_AddStringToObject(root, "ip_server" ,ip_s); cJSON_AddStringToObject(root, "port_server", port_s); cJSON_AddStringToObject(root, "port_local", port_l); out=cJSON_Print(root); fprintf(fp,"%s",out); fclose(fp); cJSON_Delete(root); free(out); out = NULL; root = NULL; free(pContent); return 1; }
int /* O - 0 on success, -1 on error */ cupsFileClose(cups_file_t *fp) /* I - CUPS file */ { int fd; /* File descriptor */ char mode; /* Open mode */ int status; /* Return status */ int is_stdio; /* Is a stdio file? */ DEBUG_printf(("cupsFileClose(fp=%p)", fp)); /* * Range check... */ if (!fp) return (-1); /* * Flush pending write data... */ if (fp->mode == 'w') status = cupsFileFlush(fp); else status = 0; #ifdef HAVE_LIBZ if (fp->compressed && status >= 0) { if (fp->mode == 'r') { /* * Free decompression data... */ inflateEnd(&fp->stream); } else { /* * Flush any remaining compressed data... */ unsigned char trailer[8]; /* Trailer CRC and length */ int done; /* Done writing... */ fp->stream.avail_in = 0; for (done = 0;;) { if (fp->stream.next_out > fp->cbuf) { if (cups_write(fp, (char *)fp->cbuf, fp->stream.next_out - fp->cbuf) < 0) status = -1; fp->stream.next_out = fp->cbuf; fp->stream.avail_out = sizeof(fp->cbuf); } if (done || status < 0) break; done = deflate(&fp->stream, Z_FINISH) == Z_STREAM_END && fp->stream.next_out == fp->cbuf; } /* * Write the CRC and length... */ trailer[0] = fp->crc; trailer[1] = fp->crc >> 8; trailer[2] = fp->crc >> 16; trailer[3] = fp->crc >> 24; trailer[4] = fp->pos; trailer[5] = fp->pos >> 8; trailer[6] = fp->pos >> 16; trailer[7] = fp->pos >> 24; if (cups_write(fp, (char *)trailer, 8) < 0) status = -1; /* * Free all memory used by the compression stream... */ deflateEnd(&(fp->stream)); } } #endif /* HAVE_LIBZ */ /* * Save the file descriptor we used and free memory... */ fd = fp->fd; mode = fp->mode; is_stdio = fp->is_stdio; if (fp->printf_buffer) free(fp->printf_buffer); free(fp); /* * Close the file, returning the close status... */ if (mode == 's') { if (closesocket(fd) < 0) status = -1; } else if (!is_stdio) { if (close(fd) < 0) status = -1; } return (status); }
void * /* O - Search context */ cgiCompileSearch(const char *query) /* I - Query string */ { regex_t *re; /* Regular expression */ char *s, /* Regular expression string */ *sptr, /* Pointer into RE string */ *sword; /* Pointer to start of word */ int slen; /* Allocated size of RE string */ const char *qptr, /* Pointer into query string */ *qend; /* End of current word */ const char *prefix; /* Prefix to add to next word */ int quoted; /* Word is quoted */ int wlen; /* Word length */ char *lword; /* Last word in query */ DEBUG_printf(("cgiCompileSearch(query=\"%s\")\n", query)); /* * Range check input... */ if (!query) return (NULL); /* * Allocate a regular expression storage structure... */ if ((re = (regex_t *)calloc(1, sizeof(regex_t))) == NULL) return (NULL); /* * Allocate a buffer to hold the regular expression string, starting * at 1024 bytes or 3 times the length of the query string, whichever * is greater. We'll expand the string as needed... */ slen = strlen(query) * 3; if (slen < 1024) slen = 1024; if ((s = (char *)malloc(slen)) == NULL) { free(re); return (NULL); } /* * Copy the query string to the regular expression, handling basic * AND and OR logic... */ prefix = ".*"; qptr = query; sptr = s; lword = NULL; while (*qptr) { /* * Skip leading whitespace... */ while (isspace(*qptr & 255)) qptr ++; if (!*qptr) break; /* * Find the end of the current word... */ if (*qptr == '\"' || *qptr == '\'') { /* * Scan quoted string... */ quoted = *qptr ++; for (qend = qptr; *qend && *qend != quoted; qend ++); if (!*qend) { /* * No closing quote, error out! */ free(s); free(re); if (lword) free(lword); return (NULL); } } else { /* * Scan whitespace-delimited string... */ quoted = 0; for (qend = qptr + 1; *qend && !isspace(*qend); qend ++); } wlen = qend - qptr; /* * Look for logic words: AND, OR */ if (wlen == 3 && !_cups_strncasecmp(qptr, "AND", 3)) { /* * Logical AND with the following text... */ if (sptr > s) prefix = ".*"; qptr = qend; } else if (wlen == 2 && !_cups_strncasecmp(qptr, "OR", 2)) { /* * Logical OR with the following text... */ if (sptr > s) prefix = ".*|.*"; qptr = qend; } else { /* * Add a search word, making sure we have enough room for the * string + RE overhead... */ wlen = (sptr - s) + 2 * 4 * wlen + 2 * strlen(prefix) + 11; if (lword) wlen += strlen(lword); if (wlen > slen) { /* * Expand the RE string buffer... */ char *temp; /* Temporary string pointer */ slen = wlen + 128; temp = (char *)realloc(s, slen); if (!temp) { free(s); free(re); if (lword) free(lword); return (NULL); } sptr = temp + (sptr - s); s = temp; } /* * Add the prefix string... */ memcpy(sptr, prefix, strlen(prefix) + 1); sptr += strlen(sptr); /* * Then quote the remaining word characters as needed for the * RE... */ sword = sptr; while (qptr < qend) { /* * Quote: ^ . [ $ ( ) | * + ? { \ */ if (strchr("^.[$()|*+?{\\", *qptr)) *sptr++ = '\\'; *sptr++ = *qptr++; } *sptr = '\0'; /* * For "word1 AND word2", add reciprocal "word2 AND word1"... */ if (!strcmp(prefix, ".*") && lword) { char *lword2; /* New "last word" */ if ((lword2 = strdup(sword)) == NULL) { free(lword); free(s); free(re); return (NULL); } memcpy(sptr, ".*|.*", 6); sptr += 5; memcpy(sptr, lword2, strlen(lword2) + 1); sptr += strlen(sptr); memcpy(sptr, ".*", 3); sptr += 2; memcpy(sptr, lword, strlen(lword) + 1); sptr += strlen(sptr); free(lword); lword = lword2; } else { if (lword) free(lword); lword = strdup(sword); } prefix = ".*|.*"; } /* * Advance to the next string... */ if (quoted) qptr ++; } if (lword) free(lword); if (sptr > s) memcpy(sptr, ".*", 3); else { /* * No query data, return NULL... */ free(s); free(re); return (NULL); } /* * Compile the regular expression... */ DEBUG_printf((" s=\"%s\"\n", s)); if (regcomp(re, s, REG_EXTENDED | REG_ICASE)) { free(re); free(s); return (NULL); } /* * Free the RE string and return the new regular expression we compiled... */ free(s); return ((void *)re); }
cups_file_t * /* O - CUPS file or @code NULL@ if the file could not be opened */ cupsFileOpenFd(int fd, /* I - File descriptor */ const char *mode) /* I - Open mode */ { cups_file_t *fp; /* New CUPS file */ DEBUG_printf(("cupsFileOpenFd(fd=%d, mode=\"%s\")", fd, mode)); /* * Range check input... */ if (fd < 0 || !mode || (*mode != 'r' && *mode != 'w' && *mode != 'a' && *mode != 's') || (*mode == 'a' && isdigit(mode[1] & 255))) return (NULL); /* * Allocate memory... */ if ((fp = calloc(1, sizeof(cups_file_t))) == NULL) return (NULL); /* * Open the file... */ fp->fd = fd; switch (*mode) { case 'a' : fp->pos = lseek(fd, 0, SEEK_END); case 'w' : fp->mode = 'w'; fp->ptr = fp->buf; fp->end = fp->buf + sizeof(fp->buf); #ifdef HAVE_LIBZ if (mode[1] >= '1' && mode[1] <= '9') { /* * Open a compressed stream, so write the standard gzip file * header... */ unsigned char header[10]; /* gzip file header */ time_t curtime; /* Current time */ curtime = time(NULL); header[0] = 0x1f; header[1] = 0x8b; header[2] = Z_DEFLATED; header[3] = 0; header[4] = curtime; header[5] = curtime >> 8; header[6] = curtime >> 16; header[7] = curtime >> 24; header[8] = 0; header[9] = 0x03; cups_write(fp, (char *)header, 10); /* * Initialize the compressor... */ deflateInit2(&(fp->stream), mode[1] - '0', Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); fp->stream.next_out = fp->cbuf; fp->stream.avail_out = sizeof(fp->cbuf); fp->compressed = 1; fp->crc = crc32(0L, Z_NULL, 0); } #endif /* HAVE_LIBZ */ break; case 'r' : fp->mode = 'r'; break; case 's' : fp->mode = 's'; break; default : /* Remove bogus compiler warning... */ return (NULL); }
STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { // We know that os.dupterm always calls with size = 1 assert(size == 1); mp_obj_webrepl_t *self = self_in; const mp_stream_p_t *sock_stream = mp_get_stream_raise(self->sock, MP_STREAM_OP_READ); mp_uint_t out_sz = sock_stream->read(self->sock, buf, size, errcode); //DEBUG_printf("webrepl: Read %d initial bytes from websocket\n", out_sz); if (out_sz == 0 || out_sz == MP_STREAM_ERROR) { return out_sz; } if (self->state == STATE_PASSWD) { char c = *(char*)buf; if (c == '\r' || c == '\n') { self->hdr.fname[self->data_to_recv] = 0; DEBUG_printf("webrepl: entered password: %s\n", self->hdr.fname); if (strcmp(self->hdr.fname, webrepl_passwd) != 0) { write_webrepl_str(self->sock, SSTR(denied_prompt)); return 0; } self->state = STATE_NORMAL; self->data_to_recv = 0; write_webrepl_str(self->sock, SSTR(connected_prompt)); } else if (self->data_to_recv < 10) { self->hdr.fname[self->data_to_recv++] = c; } return -2; } // If last read data belonged to text record (== REPL) int err; if (sock_stream->ioctl(self->sock, MP_STREAM_GET_DATA_OPTS, 0, &err) == 1) { return out_sz; } DEBUG_printf("webrepl: received bin data, hdr_to_recv: %d, data_to_recv=%d\n", self->hdr_to_recv, self->data_to_recv); if (self->hdr_to_recv != 0) { char *p = (char*)&self->hdr + sizeof(self->hdr) - self->hdr_to_recv; *p++ = *(char*)buf; if (--self->hdr_to_recv != 0) { mp_uint_t hdr_sz = sock_stream->read(self->sock, p, self->hdr_to_recv, errcode); if (hdr_sz == MP_STREAM_ERROR) { return hdr_sz; } self->hdr_to_recv -= hdr_sz; if (self->hdr_to_recv != 0) { return -2; } } DEBUG_printf("webrepl: op: %d, file: %s, chunk @%x, sz=%d\n", self->hdr.type, self->hdr.fname, (uint32_t)self->hdr.offset, self->hdr.size); handle_op(self); return -2; } if (self->data_to_recv != 0) { static byte filebuf[512]; filebuf[0] = *(byte*)buf; mp_uint_t buf_sz = 1; if (--self->data_to_recv != 0) { size_t to_read = MIN(sizeof(filebuf) - 1, self->data_to_recv); mp_uint_t sz = sock_stream->read(self->sock, filebuf + 1, to_read, errcode); if (sz == MP_STREAM_ERROR) { return sz; } self->data_to_recv -= sz; buf_sz += sz; } DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz); int err; mp_uint_t res = mp_stream_writeall(self->cur_file, filebuf, buf_sz, &err); if(res == MP_STREAM_ERROR) { assert(0); } if (self->data_to_recv == 0) { close_meth(self->cur_file); self->hdr_to_recv = sizeof(struct webrepl_file); DEBUG_printf("webrepl: Finished writing file\n"); write_webrepl_resp(self->sock, 0); } #ifdef MICROPY_PY_WEBREPL_DELAY // Some platforms may have broken drivers and easily gets // overloaded with modest traffic WebREPL file transfers // generate. The basic workaround is a crude rate control // done in such way. mp_hal_delay_ms(MICROPY_PY_WEBREPL_DELAY); #endif } return -2; }
ipp_status_t /* O - IPP status code */ cupsCreateDestJob( http_t *http, /* I - Connection to destination */ cups_dest_t *dest, /* I - Destination */ cups_dinfo_t *info, /* I - Destination information */ int *job_id, /* O - Job ID or 0 on error */ const char *title, /* I - Job name */ int num_options, /* I - Number of job options */ cups_option_t *options) /* I - Job options */ { ipp_t *request, /* Create-Job request */ *response; /* Create-Job response */ ipp_attribute_t *attr; /* job-id attribute */ DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, " "job_id=%p, title=\"%s\", num_options=%d, options=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, (void *)job_id, title, num_options, (void *)options)); /* * Range check input... */ if (job_id) *job_id = 0; if (!http || !dest || !info || !job_id) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); DEBUG_puts("1cupsCreateDestJob: Bad arguments."); return (IPP_STATUS_ERROR_INTERNAL); } /* * Build a Create-Job request... */ if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0); DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request."); return (IPP_STATUS_ERROR_INTERNAL); } ippSetVersion(request, info->version / 10, info->version % 10); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (title) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION); cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB); cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION); /* * Send the request and get the job-id... */ response = cupsDoRequest(http, request, info->resource); if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL) { *job_id = attr->values[0].integer; DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id)); } ippDelete(response); /* * Return the status code from the Create-Job request... */ DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()), cupsLastErrorString())); return (cupsLastError()); }
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { // This function is pretty complicated. It's main aim is to be efficient in speed and RAM // usage for the common case of positional only args. DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw); DEBUG_printf("Input pos args: "); dump_args(args, n_args); DEBUG_printf("Input kw args: "); dump_args(args + n_args, n_kw * 2); mp_obj_fun_bc_t *self = self_in; DEBUG_printf("Func n_def_args: %d\n", self->n_def_args); const byte *ip = self->bytecode; // get code info size, and skip line number table machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24); ip += code_info_size; // bytecode prelude: state size and exception stack size; 16 bit uints machine_uint_t n_state = ip[0] | (ip[1] << 8); machine_uint_t n_exc_stack = ip[2] | (ip[3] << 8); ip += 4; #if VM_DETECT_STACK_OVERFLOW n_state += 1; #endif // allocate state for locals and stack uint state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); mp_code_state *code_state; if (state_size > VM_MAX_STATE_ON_STACK) { code_state = m_new_obj_var(mp_code_state, byte, state_size); } else { code_state = alloca(sizeof(mp_code_state) + state_size); } code_state->code_info = self->bytecode; code_state->sp = &code_state->state[0] - 1; code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1; code_state->n_state = n_state; // zero out the local stack to begin with memset(code_state->state, 0, n_state * sizeof(*code_state->state)); const mp_obj_t *kwargs = args + n_args; // var_pos_kw_args points to the stack where the var-args tuple, and var-kw dict, should go (if they are needed) mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - self->n_pos_args - self->n_kwonly_args]; // check positional arguments if (n_args > self->n_pos_args) { // given more than enough arguments if (!self->takes_var_args) { fun_pos_args_mismatch(self, self->n_pos_args, n_args); } // put extra arguments in varargs tuple *var_pos_kw_args-- = mp_obj_new_tuple(n_args - self->n_pos_args, args + self->n_pos_args); n_args = self->n_pos_args; } else { if (self->takes_var_args) { DEBUG_printf("passing empty tuple as *args\n"); *var_pos_kw_args-- = mp_const_empty_tuple; } // Apply processing and check below only if we don't have kwargs, // otherwise, kw handling code below has own extensive checks. if (n_kw == 0 && !self->has_def_kw_args) { if (n_args >= self->n_pos_args - self->n_def_args) { // given enough arguments, but may need to use some default arguments for (uint i = n_args; i < self->n_pos_args; i++) { code_state->state[n_state - 1 - i] = self->extra_args[i - (self->n_pos_args - self->n_def_args)]; } } else { fun_pos_args_mismatch(self, self->n_pos_args - self->n_def_args, n_args); } } } // copy positional args into state for (uint i = 0; i < n_args; i++) { code_state->state[n_state - 1 - i] = args[i]; } // check keyword arguments if (n_kw != 0 || self->has_def_kw_args) { DEBUG_printf("Initial args: "); dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args); mp_obj_t dict = MP_OBJ_NULL; if (self->takes_kw_args) { dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0? *var_pos_kw_args = dict; } for (uint i = 0; i < n_kw; i++) { qstr arg_name = MP_OBJ_QSTR_VALUE(kwargs[2 * i]); for (uint j = 0; j < self->n_pos_args + self->n_kwonly_args; j++) { if (arg_name == self->args[j]) { if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function got multiple values for argument '%s'", qstr_str(arg_name))); } code_state->state[n_state - 1 - j] = kwargs[2 * i + 1]; goto continue2; } } // Didn't find name match with positional args if (!self->takes_kw_args) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); } mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]); continue2:; } DEBUG_printf("Args with kws flattened: "); dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args); // fill in defaults for positional args mp_obj_t *d = &code_state->state[n_state - self->n_pos_args]; mp_obj_t *s = &self->extra_args[self->n_def_args - 1]; for (int i = self->n_def_args; i > 0; i--, d++, s--) { if (*d == MP_OBJ_NULL) { *d = *s; } } DEBUG_printf("Args after filling default positional: "); dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args); // Check that all mandatory positional args are specified while (d < &code_state->state[n_state]) { if (*d++ == MP_OBJ_NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function missing required positional argument #%d", &code_state->state[n_state] - d)); } } // Check that all mandatory keyword args are specified // Fill in default kw args if we have them for (uint i = 0; i < self->n_kwonly_args; i++) { if (code_state->state[n_state - 1 - self->n_pos_args - i] == MP_OBJ_NULL) { mp_map_elem_t *elem = NULL; if (self->has_def_kw_args) { elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[self->n_def_args])->map, MP_OBJ_NEW_QSTR(self->args[self->n_pos_args + i]), MP_MAP_LOOKUP); } if (elem != NULL) { code_state->state[n_state - 1 - self->n_pos_args - i] = elem->value; } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function missing required keyword argument '%s'", qstr_str(self->args[self->n_pos_args + i]))); } } } } else { // no keyword arguments given if (self->n_kwonly_args != 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function missing keyword-only argument")); } if (self->takes_kw_args) { *var_pos_kw_args = mp_obj_new_dict(0); } } // bytecode prelude: initialise closed over variables for (uint n_local = *ip++; n_local > 0; n_local--) { uint local_num = *ip++; code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]); } // now that we skipped over the prelude, set the ip for the VM code_state->ip = ip; DEBUG_printf("Calling: n_pos_args=%d, n_kwonly_args=%d\n", self->n_pos_args, self->n_kwonly_args); dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args); dump_args(code_state->state, n_state); // execute the byte code with the correct globals context mp_obj_dict_t *old_globals = mp_globals_get(); mp_globals_set(self->globals); mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode(code_state, MP_OBJ_NULL); mp_globals_set(old_globals); #if VM_DETECT_STACK_OVERFLOW if (vm_return_kind == MP_VM_RETURN_NORMAL) { if (code_state->sp < code_state->state) { printf("VM stack underflow: " INT_FMT "\n", code_state->sp - code_state->state); assert(0); } } // We can't check the case when an exception is returned in state[n_state - 1] // and there are no arguments, because in this case our detection slot may have // been overwritten by the returned exception (which is allowed). if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && self->n_pos_args + self->n_kwonly_args == 0)) { // Just check to see that we have at least 1 null object left in the state. bool overflow = true; for (uint i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) { if (code_state->state[i] == MP_OBJ_NULL) { overflow = false; break; } } if (overflow) { printf("VM stack overflow state=%p n_state+1=" UINT_FMT "\n", code_state->state, n_state); assert(0); } } #endif mp_obj_t result; switch (vm_return_kind) { case MP_VM_RETURN_NORMAL: // return value is in *sp result = *code_state->sp; break; case MP_VM_RETURN_EXCEPTION: // return value is in state[n_state - 1] result = code_state->state[n_state - 1]; break; case MP_VM_RETURN_YIELD: // byte-code shouldn't yield default: assert(0); result = mp_const_none; vm_return_kind = MP_VM_RETURN_NORMAL; break; } // free the state if it was allocated on the heap if (state_size > VM_MAX_STATE_ON_STACK) { m_del_var(mp_code_state, byte, state_size, code_state); } if (vm_return_kind == MP_VM_RETURN_NORMAL) { return result; } else { // MP_VM_RETURN_EXCEPTION nlr_raise(result); } }
http_status_t /* O - Status of document creation */ cupsStartDestDocument( http_t *http, /* I - Connection to destination */ cups_dest_t *dest, /* I - Destination */ cups_dinfo_t *info, /* I - Destination information */ int job_id, /* I - Job ID */ const char *docname, /* I - Document name */ const char *format, /* I - Document format */ int num_options, /* I - Number of document options */ cups_option_t *options, /* I - Document options */ int last_document) /* I - 1 if this is the last document */ { ipp_t *request; /* Send-Document request */ http_status_t status; /* HTTP status */ DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, options=%p, last_document=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id, docname, format, num_options, (void *)options, last_document)); /* * Range check input... */ if (!http || !dest || !info || job_id <= 0) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); DEBUG_puts("1cupsStartDestDocument: Bad arguments."); return (HTTP_STATUS_ERROR); } /* * Create a Send-Document request... */ if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0); DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document " "request."); return (HTTP_STATUS_ERROR); } ippSetVersion(request, info->version / 10, info->version % 10); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (docname) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", NULL, docname); if (format) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format); ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last_document); cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION); cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT); /* * Send and delete the request, then return the status... */ status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE); ippDelete(request); return (status); }
int /* O - Number of options */ cupsAddOption(const char *name, /* I - Name of option */ const char *value, /* I - Value of option */ int num_options,/* I - Number of options */ cups_option_t **options) /* IO - Pointer to options */ { cups_option_t *temp; /* Pointer to new option */ int insert, /* Insertion point */ diff; /* Result of search */ DEBUG_printf(("2cupsAddOption(name=\"%s\", value=\"%s\", num_options=%d, " "options=%p)", name, value, num_options, options)); if (!name || !name[0] || !value || !options || num_options < 0) { DEBUG_printf(("3cupsAddOption: Returning %d", num_options)); return (num_options); } /* * Look for an existing option with the same name... */ if (num_options == 0) { insert = 0; diff = 1; } else { insert = cups_find_option(name, num_options, *options, num_options - 1, &diff); if (diff > 0) insert ++; } if (diff) { /* * No matching option name... */ DEBUG_printf(("4cupsAddOption: New option inserted at index %d...", insert)); if (num_options == 0) temp = (cups_option_t *)malloc(sizeof(cups_option_t)); else temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) * (size_t)(num_options + 1)); if (!temp) { DEBUG_puts("3cupsAddOption: Unable to expand option array, returning 0"); return (0); } *options = temp; if (insert < num_options) { DEBUG_printf(("4cupsAddOption: Shifting %d options...", (int)(num_options - insert))); memmove(temp + insert + 1, temp + insert, (size_t)(num_options - insert) * sizeof(cups_option_t)); } temp += insert; temp->name = _cupsStrAlloc(name); num_options ++; } else { /* * Match found; free the old value... */ DEBUG_printf(("4cupsAddOption: Option already exists at index %d...", insert)); temp = *options + insert; _cupsStrFree(temp->value); } temp->value = _cupsStrAlloc(value); DEBUG_printf(("3cupsAddOption: Returning %d", num_options)); return (num_options); }
ipp_status_t /* O - IPP status code */ cupsCloseDestJob( http_t *http, /* I - Connection to destination */ cups_dest_t *dest, /* I - Destination */ cups_dinfo_t *info, /* I - Destination information */ int job_id) /* I - Job ID */ { int i; /* Looping var */ ipp_t *request = NULL;/* Close-Job/Send-Document request */ ipp_attribute_t *attr; /* operations-supported attribute */ DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id)); /* * Range check input... */ if (!http || !dest || !info || job_id <= 0) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); DEBUG_puts("1cupsCloseDestJob: Bad arguments."); return (IPP_STATUS_ERROR_INTERNAL); } /* * Build a Close-Job or empty Send-Document request... */ if ((attr = ippFindAttribute(info->attrs, "operations-supported", IPP_TAG_ENUM)) != NULL) { for (i = 0; i < attr->num_values; i ++) if (attr->values[i].integer == IPP_OP_CLOSE_JOB) { request = ippNewRequest(IPP_OP_CLOSE_JOB); break; } } if (!request) request = ippNewRequest(IPP_OP_SEND_DOCUMENT); if (!request) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0); DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document " "request."); return (IPP_STATUS_ERROR_INTERNAL); } ippSetVersion(request, info->version / 10, info->version % 10); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (ippGetOperation(request) == IPP_OP_SEND_DOCUMENT) ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1); /* * Send the request and return the status... */ ippDelete(cupsDoRequest(http, request, info->resource)); DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()), cupsLastErrorString())); return (cupsLastError()); }
/* * '_sspiRead()' - Read a buffer from an ssl socket */ int /* O - Bytes read or SOCKET_ERROR */ _sspiRead(_sspi_struct_t *conn, /* I - Client connection */ void *buf, /* I - Buffer */ size_t len) /* I - Buffer length */ { SecBufferDesc message; /* Array of SecBuffer struct */ SecBuffer buffers[4] = { 0 }; /* Security package buffer */ int num = 0; /* Return value */ if (!conn) { WSASetLastError(WSAEINVAL); num = SOCKET_ERROR; goto cleanup; } /* * If there are bytes that have already been * decrypted and have not yet been read, return * those */ if (buf && (conn->readBufferUsed > 0)) { int bytesToCopy = (int) min(conn->readBufferUsed, len); /* Amount of bytes to copy */ /* from read buffer */ memcpy(buf, conn->readBuffer, bytesToCopy); conn->readBufferUsed -= bytesToCopy; if (conn->readBufferUsed > 0) /* * If the caller didn't request all the bytes * we have in the buffer, then move the unread * bytes down */ memmove(conn->readBuffer, conn->readBuffer + bytesToCopy, conn->readBufferUsed); num = bytesToCopy; } else { PSecBuffer pDataBuffer; /* Data buffer */ PSecBuffer pExtraBuffer; /* Excess data buffer */ SECURITY_STATUS scRet; /* SSPI status */ int i; /* Loop control variable */ /* * Initialize security buffer structs */ message.ulVersion = SECBUFFER_VERSION; message.cBuffers = 4; message.pBuffers = buffers; do { /* * If there is not enough space in the * buffer, then increase it's size */ if (conn->decryptBufferLength <= conn->decryptBufferUsed) { conn->decryptBufferLength += 4096; conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer, conn->decryptBufferLength); if (!conn->decryptBuffer) { DEBUG_printf(("_sspiRead: unable to allocate %d byte buffer", conn->decryptBufferLength)); WSASetLastError(E_OUTOFMEMORY); num = SOCKET_ERROR; goto cleanup; } } buffers[0].pvBuffer = conn->decryptBuffer; buffers[0].cbBuffer = (unsigned long) conn->decryptBufferUsed; buffers[0].BufferType = SECBUFFER_DATA; buffers[1].BufferType = SECBUFFER_EMPTY; buffers[2].BufferType = SECBUFFER_EMPTY; buffers[3].BufferType = SECBUFFER_EMPTY; scRet = DecryptMessage(&conn->context, &message, 0, NULL); if (scRet == SEC_E_INCOMPLETE_MESSAGE) { if (buf) { num = recv(conn->sock, conn->decryptBuffer + conn->decryptBufferUsed, (int)(conn->decryptBufferLength - conn->decryptBufferUsed), 0); if (num == SOCKET_ERROR) { DEBUG_printf(("_sspiRead: recv failed: %d", WSAGetLastError())); goto cleanup; } else if (num == 0) { DEBUG_printf(("_sspiRead: server disconnected")); goto cleanup; } conn->decryptBufferUsed += num; } else { num = (int) conn->readBufferUsed; goto cleanup; } } } while (scRet == SEC_E_INCOMPLETE_MESSAGE); if (scRet == SEC_I_CONTEXT_EXPIRED) { DEBUG_printf(("_sspiRead: context expired")); WSASetLastError(WSAECONNRESET); num = SOCKET_ERROR; goto cleanup; } else if (scRet != SEC_E_OK) { DEBUG_printf(("_sspiRead: DecryptMessage failed: %lx", scRet)); WSASetLastError(WSASYSCALLFAILURE); num = SOCKET_ERROR; goto cleanup; } /* * The decryption worked. Now, locate data buffer. */ pDataBuffer = NULL; pExtraBuffer = NULL; for (i = 1; i < 4; i++) { if (buffers[i].BufferType == SECBUFFER_DATA) pDataBuffer = &buffers[i]; else if (!pExtraBuffer && (buffers[i].BufferType == SECBUFFER_EXTRA)) pExtraBuffer = &buffers[i]; } /* * If a data buffer is found, then copy * the decrypted bytes to the passed-in * buffer */ if (pDataBuffer) { int bytesToCopy = min(pDataBuffer->cbBuffer, (int) len); /* Number of bytes to copy into buf */ int bytesToSave = pDataBuffer->cbBuffer - bytesToCopy; /* Number of bytes to save in our read buffer */ if (bytesToCopy) memcpy(buf, pDataBuffer->pvBuffer, bytesToCopy); /* * If there are more decrypted bytes than can be * copied to the passed in buffer, then save them */ if (bytesToSave) { if ((int)(conn->readBufferLength - conn->readBufferUsed) < bytesToSave) { conn->readBufferLength = conn->readBufferUsed + bytesToSave; conn->readBuffer = realloc(conn->readBuffer, conn->readBufferLength); if (!conn->readBuffer) { DEBUG_printf(("_sspiRead: unable to allocate %d bytes", conn->readBufferLength)); WSASetLastError(E_OUTOFMEMORY); num = SOCKET_ERROR; goto cleanup; } } memcpy(((BYTE*) conn->readBuffer) + conn->readBufferUsed, ((BYTE*) pDataBuffer->pvBuffer) + bytesToCopy, bytesToSave); conn->readBufferUsed += bytesToSave; } num = (buf) ? bytesToCopy : (int) conn->readBufferUsed; } else { DEBUG_printf(("_sspiRead: unable to find data buffer")); WSASetLastError(WSASYSCALLFAILURE); num = SOCKET_ERROR; goto cleanup; } /* * If the decryption process left extra bytes, * then save those back in decryptBuffer. They will * be processed the next time through the loop. */ if (pExtraBuffer) { memmove(conn->decryptBuffer, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer); conn->decryptBufferUsed = pExtraBuffer->cbBuffer; } else { conn->decryptBufferUsed = 0; } } cleanup: return (num); }
http_status_t /* O - @code HTTP_STATUS_CONTINUE@ if OK or HTTP status on error */ cupsWriteRequestData( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ const char *buffer, /* I - Bytes to write */ size_t length) /* I - Number of bytes to write */ { int wused; /* Previous bytes in buffer */ /* * Get the default connection as needed... */ DEBUG_printf(("cupsWriteRequestData(http=%p, buffer=%p, " "length=" CUPS_LLFMT ")", http, buffer, CUPS_LLCAST length)); if (!http) { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ if ((http = cg->http) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No active connection"), 1); DEBUG_puts("1cupsWriteRequestData: Returning HTTP_STATUS_ERROR."); return (HTTP_STATUS_ERROR); } } /* * Then write to the HTTP connection... */ wused = http->wused; if (httpWrite2(http, buffer, length) < 0) { DEBUG_puts("1cupsWriteRequestData: Returning HTTP_STATUS_ERROR."); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(http->error), 0); return (HTTP_STATUS_ERROR); } /* * Finally, check if we have any pending data from the server... */ if (length >= HTTP_MAX_BUFFER || http->wused < wused || (wused > 0 && http->wused == length)) { /* * We've written something to the server, so check for response data... */ if (_httpWait(http, 0, 1)) { http_status_t status; /* Status from _httpUpdate */ _httpUpdate(http, &status); if (status >= HTTP_STATUS_MULTIPLE_CHOICES) { _cupsSetHTTPError(status); do { status = httpUpdate(http); } while (status != HTTP_STATUS_ERROR && http->state == HTTP_STATE_POST_RECV); httpFlush(http); } DEBUG_printf(("1cupsWriteRequestData: Returning %d.\n", status)); return (status); } } DEBUG_puts("1cupsWriteRequestData: Returning HTTP_STATUS_CONTINUE."); return (HTTP_STATUS_CONTINUE); }