/* Same as anp_dump(), but the header of the message is also dumped. */ int anp_msg_dump(struct anp_msg *self, kstr *dump_str) { int error = 0; kstr work_str; kstr_init(&work_str); kstr_reset(dump_str); kstr_sf(&work_str, "major> %u\n", self->major); kstr_append_kstr(dump_str, &work_str); kstr_sf(&work_str, "minor> %u\n", self->minor); kstr_append_kstr(dump_str, &work_str); kstr_sf(&work_str, "type> %u\n", self->minor); kstr_append_kstr(dump_str, &work_str); kstr_sf(&work_str, "id> "PRINTF_64"u\n", self->minor); kstr_append_kstr(dump_str, &work_str); if (anp_dump(&self->payload, &work_str)) { error = -1; } else { kstr_append_kstr(dump_str, &work_str); } kstr_clean(&work_str); return error; }
/* FIXME: In Blackjack this function should become generally available. */ void format_current_error_for_user(kstr *dest) { struct kerror *error_instance = kerror_get_current(); int i; kstr_reset(dest); if (error_instance->stack.size == 0) { kstr_assign_cstr(dest, "unknown error"); } else { for (i = error_instance->stack.size - 1; i >= 0; i--) { struct kerror_node *node = (struct kerror_node *) karray_get(&error_instance->stack, i); /* Level 1 error are meant to be readable. */ if (node->level >= 1) { if (i != error_instance->stack.size - 1) { kstr_append_cstr(dest, ": "); } kstr_append_kstr(dest, &node->text); } } } if (dest->slen == 0) kstr_assign_cstr(dest, "unknown error"); }
/* This function ensures that the string specified does not get too large. If * the internal memory associated to the string is bigger than the threshold * specified, the memory associated to the string is released and a new, small * buffer is allocated for the string. In all cases, the string is cleared. */ void kstr_shrink(kstr *self, int max_size) { if (self->slen > max_size) { kstr_clean(self); kstr_init(self); } kstr_reset(self); }
/* This function recomposes a directory path from its subcomponents. If the * directory path has no absolute part and no other components, the directory * path will be empty. Otherwise, the directory path will end with a delimiter. */ void kpath_recompose_dir(kstr *path, struct kpath_dir *dir, int format) { int i; kstr_reset(path); if (dir->abs_part.slen) kstr_assign_kstr(path, &dir->abs_part); for (i = 0; i < dir->components.size; i++) { kstr_append_kstr(path, (kstr *) dir->components.data[i]); kstr_append_char(path, kpath_delim(format)); } }
void kstr_sfv(kstr *self, const char *format, va_list arg) { kstr_reset(self); kstr_append_sfv(self, format, arg); }
/* This function splits the path into 3 components, directory (with trailing * delimiter), file name (without extension), and extension (without '.'). * * The path '/etc/ld.so.conf' will yield directory '/etc/', file name 'ld', and extension 'so.conf'. * The path '/etc/' will yield directory '/etc/', file name '', and extension ''. * The path '/etc' will yield directory '/', file name 'etc', and extension ''. * The path 'foo.' will yield directory './', file name 'foo.' and extension '', i.e. the extension must not be empty. * The path '.foo' will yield directory './', file name '.foo' and extension '', i.e. the file name must not be empty. * The path '.' will yield directory './', file name '', and extension ''. * The path '..' will yield directory '../', file name '', and extension ''. * The path '' will yield directory '', file name '', and extension ''. * Rule of thumb: If the extension is not empty, then <dir><filename>.<extension> is the path. * If the extension is empty, then <dir><filename> is the path. * Arguments: * String containing the path. * Directory string pointer, can be NULL. * File name string pointer, can be NULL. * Extension string pointer, can be NULL. */ void kpath_split(kstr *path, kstr *dir, kstr *name, kstr *ext, int format) { int i; int last_delim_pos = -1; int filename_start_pos = 0; int first_dot_pos = -1; /* Locate the last path delimiter, if any. */ for (i = path->slen - 1; i >= 0; i--) { if (kpath_is_delim(path->data[i], format)) { last_delim_pos = i; break; } } /* Check if the next characters after the last delimiter, or the first * characters if there is no last delimiter, are exactly and no more than * '.' or '..'. In that case, consider the whole path to be a directory * path. */ if (last_delim_pos != -1) filename_start_pos = last_delim_pos + 1; if (! strcmp(path->data + filename_start_pos, ".")) filename_start_pos += 1; else if (! strcmp(path->data + filename_start_pos, "..")) filename_start_pos += 2; /* Locate the first dot in the file name, if any. */ for (i = filename_start_pos; i < path->slen; i++) { /* We found a dot. */ if (path->data[i] == '.') { /* If there's nothing before or after the dot, consider there is no dot. */ if (i != filename_start_pos && i != path->slen - 1) first_dot_pos = i; break; } } /* Get the directory portion. */ if (dir) { /* Empty path. */ if (! path->slen) kstr_reset(dir); /* Relative path with no directory specified. */ else if (! filename_start_pos) kstr_sf(dir, ".%c", kpath_delim(format)); /* Directory present. Extract the directory and add a delimiter if * required. */ else { kstr_mid(path, dir, 0, filename_start_pos); if (! kpath_is_delim(dir->data[dir->slen - 1], format)) kstr_append_char(dir, kpath_delim(format)); } } /* Get the file name. */ if (name) { int filename_size; /* No extension case. */ if (first_dot_pos == -1) filename_size = path->slen - filename_start_pos; /* Extension case. */ else filename_size = first_dot_pos - filename_start_pos; kstr_mid(path, name, filename_start_pos, filename_size); } /* Get the extension. */ if (ext) { /* No extension case. */ if (first_dot_pos == -1) kstr_reset(ext); /* Extension case. */ else kstr_mid(path, ext, first_dot_pos + 1, path->slen - first_dot_pos - 1); } }
/* This function decomposes the directory path specified into an array of * subcomponents. If the path is absolute, the absolute part will be something * like 'C:\' on Windows and '/' on UNIX, otherwise it will be empty. The * remaining components will not contain delimiters. * * The path 'C:/toto/bar' will yield ('C:\', 'toto', 'bar') on Windows with alt * support. * The path '/toto/bar/' will yield ('/', 'toto', 'bar') on UNIX. * The path './../foo/' will yield ('.', '..', 'foo'). * The path '' will yield (). */ void kpath_decompose_dir(kstr *path, struct kpath_dir *dir, int format) { int scan_pos = 0; kstr cur_component; /* Get the platform format. */ int platform_format = kpath_get_platform_format(format); /* Determine if the path is absolute. */ int is_absolute = kpath_is_absolute(path, format); kstr_init(&cur_component); kpath_dir_reset(dir); /* If the path is absolute, obtain the absolute part. */ if (is_absolute) { if (platform_format == KPATH_FORMAT_UNIX) { kstr_append_char(&dir->abs_part, '/'); scan_pos = 1; } else { kstr_append_buf(&dir->abs_part, path->data, 2); kstr_append_char(&dir->abs_part, kpath_delim(format)); scan_pos = 3; } } /* Scan the rest of the path. */ while (scan_pos < path->slen) { /* We encountered a delimiter. */ if (kpath_is_delim(path->data[scan_pos], format)) { /* If the current component is empty, ignore it. Otherwise, add the * component in the component array. */ if (cur_component.slen) { kstr *s = kstr_new(); kstr_assign_kstr(s, &cur_component); karray_push(&dir->components, s); } /* Reset the current component. */ kstr_reset(&cur_component); } /* Append the current character. */ else kstr_append_char(&cur_component, path->data[scan_pos]); scan_pos++; } /* Add the last component, if any, in the component array. */ if (cur_component.slen) { kstr *s = kstr_new(); kstr_assign_kstr(s, &cur_component); karray_push(&dir->components, s); } kstr_clean(&cur_component); }
void kpath_dir_reset(struct kpath_dir *self) { int i = 0; kstr_reset(&self->abs_part); for (i = 0; i < self->components.size; i++) kstr_destroy((kstr *) self->components.data[i]); karray_reset(&self->components); }
/* This function dumps the content of a ANP message buffer in the string * specified. This function sets the KMOD error string when it encounters an * error in the buffer. It returns -1 on failure. */ int anp_dump(kbuffer *buf, kstr *dump_str) { int error = 0; kstr work_str; kstr data_str; kbuffer bin_buf; kstr_init(&work_str); kstr_init(&data_str); kbuffer_init(&bin_buf); kstr_reset(dump_str); while (! kbuffer_eof(buf)) { uint8_t type = buf->data[buf->pos]; if (type == ANP_UINT32) { uint32_t val; error = anp_read_uint32(buf, &val); if (error) break; kstr_sf(&work_str, "uint32> %u\n", val); kstr_append_kstr(dump_str, &work_str); } else if (type == ANP_UINT64) { uint64_t val; error = anp_read_uint64(buf, &val); if (error) break; kstr_sf(&work_str, "uint64> "PRINTF_64"u\n", val); kstr_append_kstr(dump_str, &work_str); } else if (type == ANP_STR) { error = anp_read_kstr(buf, &data_str); if (error) break; kstr_sf(&work_str, "string %u> ", data_str.slen); kstr_append_kstr(dump_str, &work_str); kstr_append_kstr(dump_str, &data_str); kstr_append_cstr(dump_str, "\n"); } else if (type == ANP_BIN) { error = anp_read_bin(buf, &bin_buf); if (error) break; kstr_sf(&work_str, "binary %u> ", bin_buf.len); kstr_append_kstr(dump_str, &work_str); kstr_append_cstr(dump_str, "\n"); } else { kmod_set_error("invalid ANP identifier (%u)\n", type); error = -1; break; } } kstr_clean(&work_str); kstr_clean(&data_str); kbuffer_clean(&bin_buf); /* Reset the buffer position to 0. */ buf->pos = 0; return error; }