401 lines
8.7 KiB
C
401 lines
8.7 KiB
C
/* 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)
|
|
{
|
|
EINA_ERROR_PWARN("srs NULL!\n");
|
|
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;
|
|
|
|
if (!parent)
|
|
{
|
|
EINA_ERROR_PWARN("parent NULL!\n");
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
void
|
|
ecdb_source_child_append(Ecdb_Source *src, Ecdb_Source *child)
|
|
{
|
|
long long orig, diff;
|
|
Ecdb_Source *p;
|
|
|
|
if (!src)
|
|
{
|
|
EINA_ERROR_PWARN("src NULL!\n");
|
|
return;
|
|
}
|
|
|
|
if (!child)
|
|
{
|
|
EINA_ERROR_PWARN("child NULL!\n");
|
|
return;
|
|
}
|
|
|
|
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)
|
|
{
|
|
EINA_ERROR_PWARN("src NULL!\n");
|
|
return;
|
|
}
|
|
|
|
if (!child)
|
|
{
|
|
EINA_ERROR_PWARN("child NULL!\n");
|
|
return;
|
|
}
|
|
|
|
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 = 0;
|
|
|
|
if (!parent)
|
|
{
|
|
EINA_ERROR_PWARN("parent NULL!\n");
|
|
return;
|
|
}
|
|
|
|
if (!image)
|
|
{
|
|
EINA_ERROR_PWARN("image NULL!\n");
|
|
return;
|
|
}
|
|
|
|
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)
|
|
{
|
|
EINA_ERROR_PWARN("bp NULL!\n");
|
|
return NULL;
|
|
}
|
|
|
|
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
|
|
{
|
|
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;
|
|
}
|
|
|