static errno_t sbus_introspect_args(FILE *file, enum sbus_arg_type type, const struct sbus_argument *args) { errno_t ret; int i; if (args == NULL) { return EOK; } for (i = 0; args[i].name != NULL; i++) { switch (type) { case SBUS_ARG_SIGNAL: WRITE_OR_FAIL(file, ret, done, FMT_SIGNAL_ARG, args[i].type, args[i].name); break; case SBUS_ARG_IN: WRITE_OR_FAIL(file, ret, done, FMT_METHOD_ARG, args[i].type, args[i].name, "in"); break; case SBUS_ARG_OUT: WRITE_OR_FAIL(file, ret, done, FMT_METHOD_ARG, args[i].type, args[i].name, "out"); break; } } ret = EOK; done: return ret; }
static char * sbus_introspect(TALLOC_CTX *mem_ctx, const char *node, const char **nodes, struct sbus_interface_list *list) { struct sbus_interface_list *item; char *introspection = NULL; FILE *memstream; char *buffer; size_t size; errno_t ret; memstream = open_memstream(&buffer, &size); if (memstream == NULL) { goto done; } WRITE_OR_FAIL(memstream, ret, done, FMT_DOCTYPE); WRITE_OR_FAIL(memstream, ret, done, FMT_NODE, node); DLIST_FOR_EACH(item, list) { ret = sbus_introspect_iface(memstream, item->interface); if (ret != EOK) { goto done; } }
static int sbus_introspect_iface(FILE *file, struct sbus_interface *iface) { errno_t ret; WRITE_OR_FAIL(file, ret, done, FMT_IFACE, iface->name); ret = sbus_introspect_annotations(file, false, iface->annotations); if (ret != EOK) { goto done; } ret = sbus_introspect_methods(file, iface->methods); if (ret != EOK) { goto done; } ret = sbus_introspect_signals(file, iface->signals); if (ret != EOK) { goto done; } ret = sbus_introspect_properties(file, iface->properties); if (ret != EOK) { goto done; } WRITE_OR_FAIL(file, ret, done, FMT_IFACE_CLOSE); ret = EOK; done: return ret; }
static errno_t sbus_introspect_properties(FILE *file, const struct sbus_property *properties) { struct sbus_introspect_property *props; const char *mode; errno_t ret; int len; int i; if (properties == NULL) { return EOK; } for (len = 0; properties[len].name != NULL ; len++); props = talloc_zero_array(NULL, struct sbus_introspect_property, len + 1); if (props == NULL) { return ENOMEM; } for (i = 0; properties[i].name != NULL; i++) { sbus_introspect_property_set(props, &properties[i]); } for (i = 0; props[i].name != NULL; i++) { mode = sbus_introspect_property_mode(&props[i]); if (EMPTY(props[i].annotations)) { WRITE_OR_FAIL(file, ret, done, FMT_PROPERTY_EMPTY, props[i].name, props[i].type, mode); continue; } WRITE_OR_FAIL(file, ret, done, FMT_PROPERTY_OPEN, props[i].name, props[i].type, mode); ret = sbus_introspect_annotations(file, true, props[i].annotations); if (ret != EOK) { goto done; } WRITE_OR_FAIL(file, ret, done, FMT_PROPERTY_CLOSE); } ret = EOK; done: talloc_free(props); return ret; }
static errno_t sbus_introspect_methods(FILE *file, const struct sbus_method *methods) { errno_t ret; int i; if (methods == NULL) { return EOK; } for (i = 0; methods[i].name != NULL; i++) { if (EMPTY(methods[i].annotations) && EMPTY(methods[i].arguments->input) && EMPTY(methods[i].arguments->output)) { WRITE_OR_FAIL(file, ret, done, FMT_METHOD_EMPTY, methods[i].name); continue; } WRITE_OR_FAIL(file, ret, done, FMT_METHOD_OPEN, methods[i].name); ret = sbus_introspect_annotations(file, true, methods[i].annotations); if (ret != EOK) { goto done; } ret = sbus_introspect_args(file, SBUS_ARG_IN, methods[i].arguments->input); if (ret != EOK) { goto done; } ret = sbus_introspect_args(file, SBUS_ARG_OUT, methods[i].arguments->output); if (ret != EOK) { goto done; } WRITE_OR_FAIL(file, ret, done, FMT_METHOD_CLOSE); } ret = EOK; done: return ret; }
static errno_t sbus_introspect_signals(FILE *file, const struct sbus_signal *signals) { errno_t ret; int i; if (signals == NULL) { return EOK; } for (i = 0; signals[i].name != NULL; i++) { if (EMPTY(signals[i].annotations) && EMPTY(signals[i].arguments)) { WRITE_OR_FAIL(file, ret, done, FMT_SIGNAL_EMPTY, signals[i].name); continue; } WRITE_OR_FAIL(file, ret, done, FMT_SIGNAL_OPEN, signals[i].name); ret = sbus_introspect_annotations(file, true, signals[i].annotations); if (ret != EOK) { goto done; } ret = sbus_introspect_args(file, SBUS_ARG_SIGNAL, signals[i].arguments); if (ret != EOK) { goto done; } WRITE_OR_FAIL(file, ret, done, FMT_SIGNAL_CLOSE); } ret = EOK; done: return ret; }
ssize_t write_crnl(int to_fd, char *buffer, ssize_t len) { char *newline; ssize_t r, retval = 0; ssize_t count, offset = 0; for(offset = 0; offset < len; offset += count) { // Set the number of characters to write to the number // of characters remaining in the buffer. count = len - offset; newline = memchr(buffer + offset, '\n', count); // Ensure that we write no further than any newline characters. if (newline) { // Use how far the newline lies beyond the current offset // in the buffer, plus one to include the nl. count = newline - buffer - offset + 1; } // Macro to automate performing a safe write, deciding whether to return // based on the return value, and finally increasing the count. #define WRITE_OR_FAIL(f, b, l) { \ r = safe_write(f, b, l); \ if (r == -1) return r; \ else retval += r; \ } WRITE_OR_FAIL(to_fd, buffer + offset, count); if (newline) WRITE_OR_FAIL(to_fd, "\r", 1); #undef WRITE_OR_FAIL } return retval; }
static int sbus_introspect_nodes(FILE *file, const char **nodes) { errno_t ret; int i; if (nodes == NULL) { return EOK; } for (i = 0; nodes[i] != NULL; i++) { WRITE_OR_FAIL(file, ret, done, FMT_CHILD_NODE, nodes[i]); } ret = EOK; done: return ret; }
static errno_t sbus_introspect_annotations(FILE *file, bool inside, const struct sbus_annotation *annotations) { errno_t ret; const char *indent = inside ? " " : ""; int i; if (annotations == NULL) { return EOK; } for (i = 0; annotations[i].name != NULL; i++) { WRITE_OR_FAIL(file, ret, done, FMT_ANNOTATION, indent, annotations[i].name, annotations[i].value); } ret = EOK; done: return ret; }
int fiasco_unpack(struct fiasco * fiasco, const char * dir) { int fd = -1; char * name = NULL; char * layout_name = NULL; struct image * image; struct image_list * image_list; uint32_t size; char cwd[256]; unsigned char buf[4096]; if ( dir ) { memset(cwd, 0, sizeof(cwd)); if ( ! getcwd(cwd, sizeof(cwd)) ) { ERROR_INFO("Cannot store current directory"); return -1; } if ( chdir(dir) < 0 ) { ERROR_INFO("Cannot change current directory to %s", dir); return -1; } } fiasco_print_info(fiasco); image_list = fiasco->first; while ( image_list ) { image = image_list->image; name = image_name_alloc_from_values(image); if ( ! name ) return -1; printf("\n"); printf("Unpacking image...\n"); image_print_info(image); if ( image->layout ) { layout_name = calloc(1, strlen(name) + strlen(".layout") + 1); if ( ! layout_name ) ALLOC_ERROR_RETURN(-1); sprintf(layout_name, "%s.layout", name); printf(" Layout file: %s\n", layout_name); } printf(" Output file: %s\n", name); if ( ! simulate ) { fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644); if ( fd < 0 ) { ERROR_INFO("Cannot create output file %s", name); return -1; } } free(name); image_seek(image, 0); while ( 1 ) { size = image_read(image, buf, sizeof(buf)); if ( size == 0 ) break; WRITE_OR_FAIL(name, fd, buf, size); } close(fd); if ( image->layout ) { if ( ! simulate ) { fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644); if ( fd < 0 ) { ERROR_INFO("Cannot create layout file %s", layout_name); return -1; } } free(layout_name); WRITE_OR_FAIL(layout_name, fd, image->layout, (int)strlen(image->layout)); close(fd); } image_list = image_list->next; } if ( dir ) { if ( chdir(cwd) < 0 ) { ERROR_INFO("Cannot change current directory back to %s", cwd); return -1; } } printf("\nDone\n\n"); return 0; }
int fiasco_write_to_file(struct fiasco * fiasco, const char * file) { int fd = -1; int i; int device_count; uint32_t size; uint32_t length; uint16_t hash; uint8_t length8; char ** device_hwrevs_bufs; const char * str; const char * type; struct image_list * image_list; struct image * image; unsigned char buf[4096]; if ( ! fiasco ) return -1; printf("Generating Fiasco image %s...\n", file); if ( ! fiasco->first ) FIASCO_WRITE_ERROR(file, fd, "Nothing to write"); if ( fiasco->name && strlen(fiasco->name)+1 > UINT8_MAX ) FIASCO_WRITE_ERROR(file, fd, "Fiasco name string is too long"); if ( fiasco->swver && strlen(fiasco->swver)+1 > UINT8_MAX ) FIASCO_WRITE_ERROR(file, fd, "SW version string is too long"); if ( ! simulate ) { fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0644); if ( fd < 0 ) { ERROR_INFO("Cannot create file"); return -1; } } printf("Writing Fiasco header...\n"); WRITE_OR_FAIL(file, fd, "\xb4", 1); /* signature */ if ( fiasco->name[0] ) str = fiasco->name; else str = "OSSO UART+USB"; length = 4 + strlen(str) + 3; if ( fiasco->swver[0] ) length += strlen(fiasco->swver) + 3; length = htonl(length); WRITE_OR_FAIL(file, fd, &length, 4); /* FW header length */ if ( fiasco->swver[0] ) length = htonl(2); else length = htonl(1); WRITE_OR_FAIL(file, fd, &length, 4); /* FW header blocks count */ /* Fiasco name */ length8 = strlen(str)+1; WRITE_OR_FAIL(file, fd, "\xe8", 1); WRITE_OR_FAIL(file, fd, &length8, 1); WRITE_OR_FAIL(file, fd, str, length8); /* SW version */ if ( fiasco->swver[0] ) { printf("Writing SW version: %s\n", fiasco->swver); length8 = strlen(fiasco->swver)+1; WRITE_OR_FAIL(file, fd, "\x31", 1); WRITE_OR_FAIL(file, fd, &length8, 1); WRITE_OR_FAIL(file, fd, fiasco->swver, length8); }; printf("\n"); image_list = fiasco->first; while ( image_list ) { image = image_list->image; if ( ! image ) FIASCO_WRITE_ERROR(file, fd, "Empty image"); printf("Writing image...\n"); image_print_info(image); type = image_type_to_string(image->type); device_hwrevs_bufs = device_list_alloc_to_bufs(image->devices); device_count = 0; if ( device_hwrevs_bufs && device_hwrevs_bufs[0] ) for ( ; device_hwrevs_bufs[device_count]; ++device_count ); if ( ! type ) FIASCO_WRITE_ERROR(file, fd, "Unknown image type"); if ( image->version && strlen(image->version) > UINT8_MAX ) FIASCO_WRITE_ERROR(file, fd, "Image version string is too long"); if ( image->layout && strlen(image->layout) > UINT8_MAX ) FIASCO_WRITE_ERROR(file, fd, "Image layout is too long"); printf("Writing image header...\n"); /* signature */ WRITE_OR_FAIL(file, fd, "T", 1); /* number of subsections */ length8 = device_count+1; if ( image->version ) ++length8; if ( image->layout ) ++length8; WRITE_OR_FAIL(file, fd, &length8, 1); /* unknown */ WRITE_OR_FAIL(file, fd, "\x2e\x19\x01\x01\x00", 5); /* checksum */ hash = htons(image->hash); WRITE_OR_FAIL(file, fd, &hash, 2); /* image type name */ memset(buf, 0, 12); strncpy((char *)buf, type, 12); WRITE_OR_FAIL(file, fd, buf, 12); /* image size */ size = htonl(image->size); WRITE_OR_FAIL(file, fd, &size, 4); /* unknown */ WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4); /* append version subsection */ if ( image->version ) { WRITE_OR_FAIL(file, fd, "1", 1); /* 1 - version */ length8 = strlen(image->version)+1; WRITE_OR_FAIL(file, fd, &length8, 1); WRITE_OR_FAIL(file, fd, image->version, length8); } /* append device & hwrevs subsection */ for ( i = 0; i < device_count; ++i ) { WRITE_OR_FAIL(file, fd, "2", 1); /* 2 - device & hwrevs */ WRITE_OR_FAIL(file, fd, &device_hwrevs_bufs[i][0], 1); WRITE_OR_FAIL(file, fd, device_hwrevs_bufs[i]+1, ((uint8_t *)(device_hwrevs_bufs[i]))[0]); } free(device_hwrevs_bufs); /* append layout subsection */ if ( image->layout ) { length8 = strlen(image->layout); WRITE_OR_FAIL(file, fd, "3", 1); /* 3 - layout */ WRITE_OR_FAIL(file, fd, &length8, 1); WRITE_OR_FAIL(file, fd, image->layout, length8); } /* dummy byte - end of all subsections */ WRITE_OR_FAIL(file, fd, "\x00", 1); printf("Writing image data...\n"); image_seek(image, 0); while ( 1 ) { size = image_read(image, buf, sizeof(buf)); if ( size == 0 ) break; WRITE_OR_FAIL(file, fd, buf, size); } image_list = image_list->next; if ( image_list ) printf("\n"); } close(fd); printf("\nDone\n\n"); return 0; }