static bool get_script(const char *path, xmlNodePtr ptr) { if (gl_script_program) { RARCH_ERR("Script already imported.\n"); return false; } char script_class[64]; xml_get_prop(script_class, sizeof(script_class), ptr, "class"); if (*script_class) strlcpy(gl_tracker_script_class, script_class, sizeof(gl_tracker_script_class)); char language[64]; xml_get_prop(language, sizeof(language), ptr, "language"); if (strcmp(language, "python") != 0) { RARCH_ERR("Script language is not Python.\n"); return false; } char *script = xml_get_content(ptr); if (!script) return false; gl_script_program = xml_replace_if_file(script, path, ptr, "src"); if (!gl_script_program) { RARCH_ERR("Cannot find Python script.\n"); return false; } return true; }
xml_conf_xpath_result_for_each(xmldisk_set, xmldisk, i) { const char *path_prop; const char *node_name; char path[EXA_MAXSIZE_DEVPATH + 1]; struct adm_disk *disk; struct adm_node *node; node_name = xml_get_prop(xmldisk, "node"); node = adm_cluster_get_node_by_name(node_name); if (!node) { set_error(err_desc, -ADMIND_ERR_UNKNOWN_NODENAME, "Node '%s' is not part of the cluster.", node_name); xml_conf_xpath_free(xmldisk_set); return; } path_prop = xml_get_prop(xmldisk, "path"); os_disk_normalize_path(path_prop, path, sizeof(path)); exalog_debug("Checking rdev '%s:%s' is not already used", node_name, path); if (info->nb_disks >= NBMAX_DISKS_PER_GROUP) { set_error(err_desc, -ADMIND_ERR_TOO_MANY_DISKS_IN_GROUP, "too many disks in group (> %d)", NBMAX_DISKS_PER_GROUP); xml_conf_xpath_free(xmldisk_set); return; } disk = adm_cluster_get_disk_by_path(node_name, path); if (!disk) { set_error(err_desc, -ADMIND_ERR_UNKNOWN_DISK, "disk '%s:%s' is unknown", node_name, path); xml_conf_xpath_free(xmldisk_set); return; } uuid_copy(&info->disks[info->nb_disks], &disk->uuid); info->nb_disks++; }
/** * Extracts an unsigned int value from a XML node */ static int xml_get_uint_prop(const xmlNodePtr xml_node, const char *prop_name, uint32_t *prop_val, cl_error_desc_t *err_desc) { const char *val_str = xml_get_prop(xml_node, prop_name); if (sscanf(val_str, "%u", prop_val) != 1) { set_error(err_desc, -EXA_ERR_XML_GET, "Inappropriate value '%s' for parameter '%s'", val_str, prop_name); return -1; } return 0; }
int main(int argc, char *argv[]) { xmlDocPtr doc = NULL; xmlChar *result = NULL; if (argc != 2) { fprintf(stderr, "Usage: %s <xmlfile>\n", argv[0]); return -1; } doc = xml_get_doc(argv[1]); if (doc == NULL) { xmlCleanupParser(); return -1; } result = xml_get_value(doc, "//Format/meta/good"); if (result == NULL) fprintf(stderr, "Not found\n"); else { fprintf(stdout, "result = %s\n", result); xmlFree(result); } result = xml_get_prop(doc, "//Format", "FmtName"); if (result == NULL) fprintf(stderr, "Not found\n"); else { fprintf(stdout, "prop result: %s\n", result); xmlFree(result); } result = xml_doc_to_string(doc); if (result == NULL) fprintf(stderr, "Not fount\n"); else { fprintf(stdout, "result = %s\n", result); xmlFree(result); } xmlFreeDoc(doc); xmlCleanupParser(); return 0; }
static char *xml_replace_if_file(char *content, const char *path, xmlNodePtr node, const char *src_prop) { char prop[64]; if (!xml_get_prop(prop, sizeof(prop), node, src_prop)) return content; free(content); content = NULL; char shader_path[PATH_MAX]; fill_pathname_resolve_relative(shader_path, path, (const char*)prop, sizeof(shader_path)); RARCH_LOG("Loading external source from \"%s\".\n", shader_path); if (read_file(shader_path, (void**)&content) >= 0) return content; else return NULL; }
static unsigned get_xml_shaders(const char *path, struct shader_program *prog, size_t size) { LIBXML_TEST_VERSION; xmlParserCtxtPtr ctx = xmlNewParserCtxt(); if (!ctx) { RARCH_ERR("Failed to load libxml2 context.\n"); return false; } RARCH_LOG("Loading XML shader: %s\n", path); xmlDocPtr doc = xmlCtxtReadFile(ctx, path, NULL, 0); xmlNodePtr head = NULL; xmlNodePtr cur = NULL; unsigned num = 0; if (!doc) { RARCH_ERR("Failed to parse XML file: %s\n", path); goto error; } #ifdef HAVE_LIBXML2 if (ctx->valid == 0) { RARCH_ERR("Cannot validate XML shader: %s\n", path); goto error; } #endif head = xmlDocGetRootElement(doc); for (cur = head; cur; cur = cur->next) { if (cur->type != XML_ELEMENT_NODE) continue; if (strcmp((const char*)cur->name, "shader") != 0) continue; char attr[64]; xml_get_prop(attr, sizeof(attr), cur, "language"); if (strcmp(attr, "GLSL") != 0) continue; xml_get_prop(attr, sizeof(attr), cur, "style"); glsl_modern = strcmp(attr, "GLES2") == 0; if (glsl_modern) RARCH_LOG("[GL]: Shader reports a GLES2 style shader.\n"); break; } if (!cur) // We couldn't find any GLSL shader :( goto error; memset(prog, 0, sizeof(struct shader_program) * size); // Iterate to check if we find fragment and/or vertex shaders. for (cur = cur->children; cur && num < size; cur = cur->next) { if (cur->type != XML_ELEMENT_NODE) continue; char *content = xml_get_content(cur); if (!content) continue; if (strcmp((const char*)cur->name, "vertex") == 0) { if (prog[num].vertex) { RARCH_ERR("Cannot have more than one vertex shader in a program.\n"); free(content); goto error; } content = xml_replace_if_file(content, path, cur, "src"); if (!content) { RARCH_ERR("Shader source file was provided, but failed to read.\n"); goto error; } prog[num].vertex = content; } else if (strcmp((const char*)cur->name, "fragment") == 0) { if (glsl_modern && !prog[num].vertex) { RARCH_ERR("Modern GLSL was chosen and vertex shader was not provided. This is an error.\n"); free(content); goto error; } content = xml_replace_if_file(content, path, cur, "src"); if (!content) { RARCH_ERR("Shader source file was provided, but failed to read.\n"); goto error; } prog[num].fragment = content; if (!get_xml_attrs(&prog[num], cur)) { RARCH_ERR("XML shader attributes do not comply with specifications.\n"); goto error; } num++; } else if (strcmp((const char*)cur->name, "texture") == 0) { free(content); if (!get_texture_image(path, cur)) { RARCH_ERR("Texture image failed to load.\n"); goto error; } } else if (strcmp((const char*)cur->name, "import") == 0) { free(content); if (!get_import_value(cur)) { RARCH_ERR("Import value is invalid.\n"); goto error; } } #ifdef HAVE_PYTHON else if (strcmp((const char*)cur->name, "script") == 0) { free(content); if (!get_script(path, cur)) { RARCH_ERR("Script is invalid.\n"); goto error; } } #endif } if (num == 0) { RARCH_ERR("Couldn't find vertex shader nor fragment shader in XML file.\n"); goto error; } xmlFreeDoc(doc); xmlFreeParserCtxt(ctx); return num; error: RARCH_ERR("Failed to load XML shader ...\n"); if (doc) xmlFreeDoc(doc); xmlFreeParserCtxt(ctx); return 0; }
static bool get_import_value(xmlNodePtr ptr) { if (gl_tracker_info_cnt >= MAX_VARIABLES) { RARCH_ERR("Too many import variables ...\n"); return false; } char id[64], semantic[64], wram[64], input[64], bitmask[64], bitequal[64]; xml_get_prop(id, sizeof(id), ptr, "id"); xml_get_prop(semantic, sizeof(semantic), ptr, "semantic"); xml_get_prop(wram, sizeof(wram), ptr, "wram"); xml_get_prop(input, sizeof(input), ptr, "input_slot"); xml_get_prop(bitmask, sizeof(bitmask), ptr, "mask"); xml_get_prop(bitequal, sizeof(bitequal), ptr, "equal"); unsigned memtype; enum state_tracker_type tracker_type; enum state_ram_type ram_type = RARCH_STATE_NONE; uint32_t addr = 0; unsigned mask_value = 0; unsigned mask_equal = 0; if (!*semantic || !*id) { RARCH_ERR("No semantic or ID for import value.\n"); return false; } if (strcmp(semantic, "capture") == 0) tracker_type = RARCH_STATE_CAPTURE; else if (strcmp(semantic, "capture_previous") == 0) tracker_type = RARCH_STATE_CAPTURE_PREV; else if (strcmp(semantic, "transition") == 0) tracker_type = RARCH_STATE_TRANSITION; else if (strcmp(semantic, "transition_count") == 0) tracker_type = RARCH_STATE_TRANSITION_COUNT; else if (strcmp(semantic, "transition_previous") == 0) tracker_type = RARCH_STATE_TRANSITION_PREV; #ifdef HAVE_PYTHON else if (strcmp(semantic, "python") == 0) tracker_type = RARCH_STATE_PYTHON; #endif else { RARCH_ERR("Invalid semantic for import value.\n"); return false; } #ifdef HAVE_PYTHON if (tracker_type != RARCH_STATE_PYTHON) #endif { if (*input) { unsigned slot = strtoul(input, NULL, 0); switch (slot) { case 1: ram_type = RARCH_STATE_INPUT_SLOT1; break; case 2: ram_type = RARCH_STATE_INPUT_SLOT2; break; default: RARCH_ERR("Invalid input slot for import.\n"); return false; } } else if (*wram) { addr = strtoul(wram, NULL, 16); ram_type = RARCH_STATE_WRAM; } else { RARCH_ERR("No RAM address specificed for import value.\n"); return false; } } switch (ram_type) { case RARCH_STATE_WRAM: memtype = RETRO_MEMORY_SYSTEM_RAM; break; default: memtype = -1u; } if ((memtype != -1u) && (addr >= pretro_get_memory_size(memtype))) { RARCH_ERR("Address out of bounds.\n"); return false; } if (*bitmask) mask_value = strtoul(bitmask, NULL, 16); if (*bitequal) mask_equal = strtoul(bitequal, NULL, 16); strlcpy(gl_tracker_info[gl_tracker_info_cnt].id, id, sizeof(gl_tracker_info[0].id)); gl_tracker_info[gl_tracker_info_cnt].addr = addr; gl_tracker_info[gl_tracker_info_cnt].type = tracker_type; gl_tracker_info[gl_tracker_info_cnt].ram_type = ram_type; gl_tracker_info[gl_tracker_info_cnt].mask = mask_value; gl_tracker_info[gl_tracker_info_cnt].equal = mask_equal; gl_tracker_info_cnt++; return true; }
static bool get_texture_image(const char *shader_path, xmlNodePtr ptr) { if (gl_teximage_cnt >= MAX_TEXTURES) { RARCH_WARN("Too many texture images. Ignoring ...\n"); return true; } bool linear = true; char filename[PATH_MAX]; char filter[64]; char id[64]; xml_get_prop(filename, sizeof(filename), ptr, "file"); xml_get_prop(filter, sizeof(filter), ptr, "filter"); xml_get_prop(id, sizeof(id), ptr, "id"); struct texture_image img; if (!*id) { RARCH_ERR("Could not find ID in texture.\n"); return false; } if (!*filename) { RARCH_ERR("Could not find filename in texture.\n"); return false; } if (strcmp(filter, "nearest") == 0) linear = false; char tex_path[PATH_MAX]; fill_pathname_resolve_relative(tex_path, shader_path, (const char*)filename, sizeof(tex_path)); RARCH_LOG("Loading texture image from: \"%s\" ...\n", tex_path); if (!texture_image_load(tex_path, &img)) { RARCH_ERR("Failed to load texture image from: \"%s\"\n", tex_path); return false; } strlcpy(gl_teximage_uniforms[gl_teximage_cnt], (const char*)id, sizeof(gl_teximage_uniforms[0])); glGenTextures(1, &gl_teximage[gl_teximage_cnt]); pglActiveTexture(GL_TEXTURE0 + gl_teximage_cnt + 1); glBindTexture(GL_TEXTURE_2D, gl_teximage[gl_teximage_cnt]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(GL_TEXTURE_2D, 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_INTERNAL_FORMAT32, img.width, img.height, 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, img.pixels); pglActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); free(img.pixels); gl_teximage_cnt++; return true; }
static bool get_xml_attrs(struct shader_program *prog, xmlNodePtr ptr) { prog->scale_x = 1.0; prog->scale_y = 1.0; prog->type_x = prog->type_y = RARCH_SCALE_INPUT; prog->valid_scale = false; // Check if shader forces a certain texture filtering. char attr[64]; if (xml_get_prop(attr, sizeof(attr), ptr, "filter")) { if (strcmp(attr, "nearest") == 0) { prog->filter = RARCH_GL_NEAREST; RARCH_LOG("XML: Shader forces GL_NEAREST.\n"); } else if (strcmp(attr, "linear") == 0) { prog->filter = RARCH_GL_LINEAR; RARCH_LOG("XML: Shader forces GL_LINEAR.\n"); } else RARCH_WARN("XML: Invalid property for filter.\n"); } else prog->filter = RARCH_GL_NOFORCE; // Check for scaling attributes *lots of code <_<* char attr_scale[64], attr_scale_x[64], attr_scale_y[64]; char attr_size[64], attr_size_x[64], attr_size_y[64]; char attr_outscale[64], attr_outscale_x[64], attr_outscale_y[64]; xml_get_prop(attr_scale, sizeof(attr_scale), ptr, "scale"); xml_get_prop(attr_scale_x, sizeof(attr_scale_x), ptr, "scale_x"); xml_get_prop(attr_scale_y, sizeof(attr_scale_y), ptr, "scale_y"); xml_get_prop(attr_size, sizeof(attr_size), ptr, "size"); xml_get_prop(attr_size_x, sizeof(attr_size_x), ptr, "size_x"); xml_get_prop(attr_size_y, sizeof(attr_size_y), ptr, "size_y"); xml_get_prop(attr_outscale, sizeof(attr_outscale), ptr, "outscale"); xml_get_prop(attr_outscale_x, sizeof(attr_outscale_x), ptr, "outscale_x"); xml_get_prop(attr_outscale_y, sizeof(attr_outscale_y), ptr, "outscale_y"); unsigned x_attr_cnt = 0, y_attr_cnt = 0; if (*attr_scale) { float scale = strtod(attr_scale, NULL); prog->scale_x = scale; prog->scale_y = scale; prog->valid_scale = true; prog->type_x = prog->type_y = RARCH_SCALE_INPUT; RARCH_LOG("Got scale attr: %.1f\n", scale); x_attr_cnt++; y_attr_cnt++; } if (*attr_scale_x) { float scale = strtod(attr_scale_x, NULL); prog->scale_x = scale; prog->valid_scale = true; prog->type_x = RARCH_SCALE_INPUT; RARCH_LOG("Got scale_x attr: %.1f\n", scale); x_attr_cnt++; } if (*attr_scale_y) { float scale = strtod(attr_scale_y, NULL); prog->scale_y = scale; prog->valid_scale = true; prog->type_y = RARCH_SCALE_INPUT; RARCH_LOG("Got scale_y attr: %.1f\n", scale); y_attr_cnt++; } if (*attr_size) { prog->abs_x = prog->abs_y = strtoul(attr_size, NULL, 0); prog->valid_scale = true; prog->type_x = prog->type_y = RARCH_SCALE_ABSOLUTE; RARCH_LOG("Got size attr: %u\n", prog->abs_x); x_attr_cnt++; y_attr_cnt++; } if (*attr_size_x) { prog->abs_x = strtoul(attr_size_x, NULL, 0); prog->valid_scale = true; prog->type_x = RARCH_SCALE_ABSOLUTE; RARCH_LOG("Got size_x attr: %u\n", prog->abs_x); x_attr_cnt++; } if (*attr_size_y) { prog->abs_y = strtoul(attr_size_y, NULL, 0); prog->valid_scale = true; prog->type_y = RARCH_SCALE_ABSOLUTE; RARCH_LOG("Got size_y attr: %u\n", prog->abs_y); y_attr_cnt++; } if (*attr_outscale) { float scale = strtod(attr_outscale, NULL); prog->scale_x = scale; prog->scale_y = scale; prog->valid_scale = true; prog->type_x = prog->type_y = RARCH_SCALE_VIEWPORT; RARCH_LOG("Got outscale attr: %.1f\n", scale); x_attr_cnt++; y_attr_cnt++; } if (*attr_outscale_x) { float scale = strtod(attr_outscale_x, NULL); prog->scale_x = scale; prog->valid_scale = true; prog->type_x = RARCH_SCALE_VIEWPORT; RARCH_LOG("Got outscale_x attr: %.1f\n", scale); x_attr_cnt++; } if (*attr_outscale_y) { float scale = strtod(attr_outscale_y, NULL); prog->scale_y = scale; prog->valid_scale = true; prog->type_y = RARCH_SCALE_VIEWPORT; RARCH_LOG("Got outscale_y attr: %.1f\n", scale); y_attr_cnt++; } if (x_attr_cnt > 1) return false; if (y_attr_cnt > 1) return false; return true; }
gint rc_extract_packages_from_undump_buffer (const guint8 *data, int len, RCChannelAndSubdFn channel_callback, RCPackageFn package_callback, RCPackageMatchFn lock_callback, gpointer user_data) { xmlDoc *doc; xmlNode *dump_node; RCChannel *system_channel = NULL; RCChannel *current_channel = NULL; xmlNode *channel_node; int count = 0; doc = rc_parse_xml_from_buffer (data, len); if (doc == NULL) return -1; dump_node = xmlDocGetRootElement (doc); if (dump_node == NULL) return -1; if (g_strcasecmp (dump_node->name, "world")) { rc_debug (RC_DEBUG_LEVEL_WARNING, "Unrecognized top-level node for undump: '%s'", dump_node->name); return -1; } channel_node = dump_node->xmlChildrenNode; while (channel_node != NULL) { if (! g_strcasecmp (channel_node->name, "locks")) { xmlNode *lock_node = channel_node->xmlChildrenNode; while (lock_node) { RCPackageMatch *lock; lock = rc_package_match_from_xml_node (lock_node); if (lock_callback) lock_callback (lock, user_data); lock_node = lock_node->next; } } else if (! g_strcasecmp (channel_node->name, "system_packages")) { int subcount; if (!system_channel) { system_channel = rc_channel_new ("@system", "System Packages", "@system", "System Packages"); rc_channel_set_system (system_channel); rc_channel_set_hidden (system_channel); } if (channel_callback) channel_callback (system_channel, FALSE, user_data); subcount = rc_extract_packages_from_xml_node (channel_node, system_channel, package_callback, user_data); if (subcount < 0) { /* Do something clever */ g_assert_not_reached (); } count += subcount; } else if (! g_strcasecmp (channel_node->name, "channel")) { char *name; char *alias; char *id_str; static guint32 dummy_id = 0xdeadbeef; char *subd_str; int subd; char *priority_str; char *priority_unsubd_str; name = xml_get_prop (channel_node, "name"); alias = xml_get_prop (channel_node, "alias"); id_str = xml_get_prop (channel_node, "id"); if (id_str == NULL) { id_str = g_strdup_printf ("dummy:%d", dummy_id); ++dummy_id; } subd_str = xml_get_prop (channel_node, "subscribed"); subd = subd_str ? atoi (subd_str) : 0; priority_str = xml_get_prop (channel_node, "priority_base"); priority_unsubd_str = xml_get_prop (channel_node, "priority_unsubd"); current_channel = rc_channel_new (id_str, name, alias, NULL); if (current_channel) { int subd_priority, unsubd_priority; subd_priority = priority_str ? atoi (priority_str) : 0; unsubd_priority = priority_unsubd_str ? atoi (priority_unsubd_str) : 0; rc_channel_set_priorities (current_channel, subd_priority, unsubd_priority); if (channel_callback) channel_callback (current_channel, subd, user_data); if (package_callback) { int subcount; subcount = rc_extract_packages_from_xml_node (channel_node, current_channel, package_callback, user_data); if (subcount < 0) { /* FIXME: do something clever */ g_assert_not_reached (); } count += subcount; } } g_free (name); g_free (alias); g_free (id_str); g_free (subd_str); g_free (priority_str); g_free (priority_unsubd_str); } channel_node = channel_node->next; } xmlFreeDoc (doc); return count; }
static void get_info_from_params(const struct dgcreate_params *params, struct dgcreate_info *info, cl_error_desc_t *err_desc) { xmlDocPtr config; xmlNodePtr diskgroup_ptr; xmlAttrPtr attr; int i; EXA_ASSERT(params); EXA_ASSERT(info); EXA_ASSERT(err_desc); config = params->config; memset(info, 0, sizeof(*info)); diskgroup_ptr = xml_conf_xpath_singleton(config, "/Exanodes/diskgroup"); uuid_generate(&info->uuid); /* 0 means that the slot width will be automagically computed */ info->slot_width = 0; info->chunk_size = adm_cluster_get_param_int("default_chunk_size"); info->su_size = adm_cluster_get_param_int("default_su_size"); info->dirty_zone_size = adm_cluster_get_param_int("default_dirty_zone_size"); info->blended_stripes = false; info->nb_disks = 0; info->nb_spare = VRT_DEFAULT_NB_SPARES; info->layout[0] = '\0'; for (attr = diskgroup_ptr->properties; attr != NULL; attr = attr->next) { if (xmlStrEqual(attr->name, BAD_CAST("name"))) strlcpy(info->name, xml_get_prop(diskgroup_ptr, "name"), EXA_MAXSIZE_GROUPNAME + 1); else if (xmlStrEqual(attr->name, BAD_CAST("layout"))) strlcpy(info->layout, xml_get_prop(diskgroup_ptr, "layout"), EXA_MAXSIZE_LAYOUTNAME + 1); else if (xmlStrEqual(attr->name, BAD_CAST("slot_width"))) { if (xml_get_uint_prop(diskgroup_ptr, "slot_width", &info->slot_width, err_desc) != 0) return; /* NOTE User can not give a zero value * If slot_width is not provided, we pass zero * to vrt so that it can calculate the proper slot_width */ if (info->slot_width == 0) { set_error(err_desc, -EXA_ERR_XML_GET, "slot_width must be greater than zero"); return; } } else if (xmlStrEqual(attr->name, BAD_CAST("chunk_size"))) { if (xml_get_uint_prop(diskgroup_ptr, "chunk_size", &info->chunk_size, err_desc) != 0) return; } else if (xmlStrEqual(attr->name, BAD_CAST("su_size"))) { if (xml_get_uint_prop(diskgroup_ptr, "su_size", &info->su_size, err_desc) != 0) return; } else if (xmlStrEqual(attr->name, BAD_CAST("dirty_zone_size"))) { if (xml_get_uint_prop(diskgroup_ptr, "dirty_zone_size", &info->dirty_zone_size, err_desc) != 0) return; } else if (xmlStrEqual(attr->name, BAD_CAST("blended_stripes"))) { if (xml_get_uint_prop(diskgroup_ptr, "blended_stripes", &info->blended_stripes, err_desc) != 0) return; } else if (xmlStrEqual(attr->name, BAD_CAST("nb_spare"))) { if (xml_get_uint_prop(diskgroup_ptr, "nb_spare", &info->nb_spare, err_desc) != 0) return; } else if (!xmlStrEqual(attr->name, BAD_CAST("cluster"))) { set_error(err_desc, -EXA_ERR_XML_GET, "Unknown group property '%s'", (char *)attr->name); return; } } /* Check the group name */ if (info->name == NULL || info->name[0] == '\0') { set_error(err_desc, -EXA_ERR_INVALID_PARAM, NULL); return; } /* Check if a group with that name already exist */ if (adm_group_get_group_by_name(info->name) != NULL) { set_error(err_desc, -VRT_ERR_GROUPNAME_USED, NULL); return; } if (info->layout[0] == '\0') { set_error(err_desc, -EXA_ERR_XML_GET, NULL); return; } if (params->alldisks) { struct adm_node *node; adm_cluster_for_each_node(node) { struct adm_disk *disk; adm_node_for_each_disk(node, disk) { if (uuid_is_zero(&disk->group_uuid)) { if (disk->path[0] == '\0') { set_error(err_desc, -ADMIND_ERR_UNKNOWN_DISK, "disk " UUID_FMT " is unknown", UUID_VAL(&disk->uuid)); return; } if (info->nb_disks >= NBMAX_DISKS_PER_GROUP) { set_error(err_desc, -ADMIND_ERR_TOO_MANY_DISKS_IN_GROUP, "too many disks in group (> %d)", NBMAX_DISKS_PER_GROUP); return; } uuid_copy(&info->disks[info->nb_disks], &disk->uuid); info->nb_disks++; } } } } else {