/* vim: set sw=3 ts=3 sts=3 expandtab: */ #include "ecdb.h" int ecdb_source_init(Ecdb_Source *src); void ecdb_source_add_directory_recursive(Ecdb_Source *parent); Ecdb_Source * ecdb_source_new(void) { Ecdb_Source *src; src = calloc(1, sizeof(Ecdb_Source)); if (!src) { return NULL; } if (!ecdb_source_init(src)) { FREE(src); return NULL; } return src; } int ecdb_source_init(Ecdb_Source *src) { src->dir = FALSE; src->num_children = 0; src->size = 0; src->children = calloc(1, sizeof(Ecdb_Source)); if (!src->children) { return FALSE; } src->children[src->num_children] = NULL; return TRUE; } void ecdb_source_destroy(Ecdb_Source *src) { int i; Ecdb_Source *child; if (!src) return; /* free the non-recursive stuff */ if (src->dst) { eina_stringshare_del(src->dst); src->dst = NULL; } /* Not sure what to do here. The nodes should already be dealt with * in normal operation. Maybe have another function that specifically * deals with this in error cases. Anyways, commented out for now */ //if (src->node) iso_node_unref(src->node); if (src->children) { for (i = 0; src->children[i]; i++) { child = src->children[i]; ecdb_source_destroy(child); } FREE(src->children); } FREE(src); } void ecdb_source_data_set(Ecdb_Source *src, const char *dst) { if ((!src) || (!ecore_file_exists(dst))) { return; } src->dst = eina_stringshare_add(dst); src->size = ecore_file_size(dst); /* Add the files recursively here */ if (ecore_file_is_dir(src->dst)) { src->dir = !!TRUE; ecdb_source_add_directory_recursive(src); } } void ecdb_source_add_directory_recursive(Ecdb_Source *parent) { Eina_List *files; Ecdb_Source *child; char path[PATH_MAX]; char *src; files = ecore_file_ls(parent->dst); EINA_LIST_FREE(files, src) { child = ecdb_source_new(); snprintf(path, PATH_MAX, "%s/%s", parent->dst, src); ecdb_source_data_set(child, path); ecdb_source_child_append(parent, child); FREE(src); } files = eina_list_free(files); } void ecdb_source_child_append(Ecdb_Source *src, Ecdb_Source *child) { long long orig, diff; Ecdb_Source *p; if (src == child) { EINA_ERROR_PWARN("Trying to make a parent of itself!\n"); return; } orig = src->size; src->num_children++; /* This is really inefficient when adding directories with lots and lots * of child files. Its good enough not to be a hugely critical thing, * but before release I need to test against using a list, or before * adding a directory count the list and malloc the entire size. Also * need to worry about multi-file drag and drop. */ src->children = realloc(src->children, sizeof(Ecdb_Source) * (src->num_children + 1)); src->children[src->num_children - 1] = child; src->children[src->num_children] = NULL; src->size += child->size; child->parent = src; diff = src->size - orig; p = src; while (p->parent) { p = p->parent; p->size += diff; } } /* Basically here we can remove all occurences (who knows why we'd get * multiple, but whatever), or just the first. For now remove the first, and * see how that goes */ void ecdb_source_child_remove(Ecdb_Source *src, Ecdb_Source *child) { Ecdb_Source **temp; Ecdb_Source *s; int i, cidx, f; if (src == child) { EINA_ERROR_PWARN("Trying to remove oneself\n"); return; } temp = calloc(src->num_children, sizeof(Ecdb_Source)); temp[src->num_children - 1] = NULL; cidx = f = 0; for (i = 0; src->children[i]; i++) { if ((src->children[i] == child) && (!f)) { f++; continue; } temp[cidx] = src->children[i]; cidx++; } FREE(src->children); src->children = temp; src->num_children--; // Propogate the size changes back up to the root s = src; do { s->size -= child->size; if (s->parent) s = s->parent; else break; } while (1); child->parent = NULL; } void ecdb_source_add_children_rec(Ecdb_Source *parent, IsoImage *image) { IsoDir *cd = NULL; Ecdb_Source *cs; int i; if ((!parent) || (!image)) return; i = 0; while ((cs = parent->children[i])) { if (cs->dir) { iso_tree_add_new_dir(ISO_DIR(parent->node), ecore_file_file_get(cs->dst), &cd); cs->node = ISO_NODE(cd); /* If the source has children, find the node from above * (if applicable), and recursively add to it */ if (cs->num_children > 0) { ecdb_source_add_children_rec(cs, image); } } /* file */ else { iso_tree_add_node(image, ISO_DIR(parent->node), cs->dst, NULL); } i++; } } /* proj->files should only have children */ BurnSource * ecdb_image_project(Ecdb_Burn_Project *bp) { IsoImage *image; Ecdb_Source *c; IsoWriteOpts *opts; BurnSource *data_src, *fifo_src; Ecdb_Data_Project *proj; if ((!bp->files) || (!bp->files->num_children)) { return NULL; } /* To handle already-suplied image files */ if ((bp->files->num_children == 1) && (ECDB_PROJECT(bp)->type == ECDB_IMAGE_PROJECT)) { efreet_mime_init(); c = bp->files->children[0]; if ((!ecore_file_is_dir(c->dst)) && (!strcmp(efreet_mime_type_get(c->dst), "application/x-cd-image"))) { data_src = burn_file_source_new(c->dst, NULL); goto FIFO_CREATE; } else if (ECDB_PROJECT(bp)->type == ECDB_IMAGE_PROJECT) { EINA_ERROR_PWARN("Supplied file is not an image!\n"); efreet_mime_shutdown(); return NULL; } efreet_mime_shutdown(); } if (ECDB_PROJECT(bp)->type == ECDB_DATA_PROJECT) { proj = ECDB_DATA(bp); } else { EINA_ERROR_PWARN("Incorrect project type!\n"); return NULL; } /* Otherwise we have a bunch of files */ if (!iso_image_new(proj->volume_id, &image)) { EINA_ERROR_PWARN("Failed to create image!\n"); return NULL; } /* Set all ids */ if (proj->publisher_id) { iso_image_set_publisher_id(image, proj->publisher_id); } if (proj->data_preparer_id) { iso_image_set_data_preparer_id(image, proj->data_preparer_id); } if (proj->system_id) { iso_image_set_system_id(image, proj->system_id); } if (proj->application_id) { iso_image_set_application_id(image, proj->application_id); } if (proj->copywrite_id) { iso_image_set_copyright_file_id(image, proj->copywrite_id); } if (proj->abstract_id) { iso_image_set_abstract_file_id(image, proj->abstract_id); } if (proj->biblio_id) { iso_image_set_biblio_file_id(image, proj->biblio_id); } if (!iso_write_opts_new(&opts, 2)) { EINA_ERROR_PWARN("Failed to create writing options!\n"); iso_image_unref(image); return NULL; } /* And some write opts stuff */ iso_write_opts_set_iso_level(opts, proj->iso_level); iso_write_opts_set_joliet(opts, proj->use_joliet); iso_write_opts_set_rockridge(opts, proj->use_rockridge); iso_write_opts_set_iso1999(opts, proj->iso1990); iso_write_opts_set_appendable(opts, bp->multi); iso_tree_set_follow_symlinks(image, proj->follow_symlinks); iso_tree_set_ignore_hidden(image, proj->ignore_hidden); iso_tree_set_ignore_special(image, proj->ignore_special); /* actually fill image with some files now */ bp->files->node = ISO_NODE(iso_image_get_root(image)); ecdb_source_add_children_rec(bp->files, image); /* Make the burn source here */ iso_image_create_burn_source(image, opts, &data_src); iso_write_opts_free(opts); iso_image_unref(image); /* And, convert to fifo */ FIFO_CREATE: fifo_src = burn_fifo_source_new(data_src, bp->fifo_chunksize, bp->fifo_chunks, 0); burn_source_free(data_src); return fifo_src; }