"Fossies" - the Fresh Open Source Software Archive

Member "libisofs-1.5.4/libisofs/filesrc.c" (8 Jul 2020, 21867 Bytes) of package /linux/misc/libisofs-1.5.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "filesrc.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2007 Vreixo Formoso
    3  *               2010 - 2012 Thomas Schmitt
    4  *
    5  * This file is part of the libisofs project; you can redistribute it and/or
    6  * modify it under the terms of the GNU General Public License version 2 
    7  * or later as published by the Free Software Foundation. 
    8  * See COPYING file for details.
    9  */
   10 
   11 #ifdef HAVE_CONFIG_H
   12 #include "../config.h"
   13 #endif
   14 
   15 #include "libisofs.h"
   16 #include "filesrc.h"
   17 #include "node.h"
   18 #include "util.h"
   19 #include "writer.h"
   20 #include "messages.h"
   21 #include "image.h"
   22 #include "stream.h"
   23 #include "md5.h"
   24 
   25 #include <stdlib.h>
   26 #include <string.h>
   27 #include <limits.h>
   28 
   29 /* <<< */
   30 #include <stdio.h>
   31 
   32 #ifdef Xorriso_standalonE
   33 
   34 #ifdef Xorriso_with_libjtE
   35 #include "../libjte/libjte.h"
   36 #endif
   37 
   38 #else
   39 
   40 #ifdef Libisofs_with_libjtE
   41 #include <libjte/libjte.h>
   42 #endif
   43 
   44 #endif /* ! Xorriso_standalonE */
   45 
   46 
   47 #ifndef PATH_MAX
   48 #define PATH_MAX Libisofs_default_path_maX
   49 #endif
   50 
   51 
   52 int iso_file_src_cmp(const void *n1, const void *n2)
   53 {
   54     int ret;
   55     const IsoFileSrc *f1, *f2;
   56 
   57     if (n1 == n2) {
   58         return 0; /* Normally just a shortcut.
   59                      But important if Libisofs_file_src_cmp_non_zerO */
   60     }
   61 
   62     f1 = (const IsoFileSrc *)n1;
   63     f2 = (const IsoFileSrc *)n2;
   64 
   65     ret = iso_stream_cmp_ino(f1->stream, f2->stream, 0);
   66     return ret;
   67 }
   68 
   69 int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
   70 {
   71     int ret, i;
   72     IsoFileSrc *fsrc;
   73     unsigned int fs_id;
   74     dev_t dev_id;
   75     ino_t ino_id;
   76     int cret, no_md5= 0;
   77     void *xipt = NULL;
   78 
   79     if (img == NULL || file == NULL || src == NULL) {
   80         return ISO_NULL_POINTER;
   81     }
   82 
   83     iso_stream_get_id(file->stream, &fs_id, &dev_id, &ino_id);
   84 
   85     fsrc = calloc(1, sizeof(IsoFileSrc));
   86     if (fsrc == NULL) {
   87         return ISO_OUT_OF_MEM;
   88     }
   89 
   90     /* fill key and other atts */
   91     fsrc->no_write = (file->from_old_session && img->opts->appendable);
   92     if (file->from_old_session && img->opts->appendable) {
   93         /*
   94          * On multisession discs we keep file sections from old image.
   95          */
   96         int ret = iso_file_get_old_image_sections(file, &(fsrc->nsections),
   97                                                   &(fsrc->sections), 0);
   98         if (ret < 0) {
   99             free(fsrc);
  100             return ISO_OUT_OF_MEM;
  101         }
  102     } else {
  103 
  104         /*
  105          * For new files, or for image copy, we compute our own file sections.
  106          * Block and size of each section will be filled later.
  107          */
  108         off_t section_size = iso_stream_get_size(file->stream);
  109         if (section_size > (off_t) MAX_ISO_FILE_SECTION_SIZE) {
  110             fsrc->nsections = DIV_UP(section_size - (off_t) MAX_ISO_FILE_SECTION_SIZE,
  111                                      (off_t)ISO_EXTENT_SIZE) + 1;
  112         } else {
  113             fsrc->nsections = 1;
  114         }
  115         fsrc->sections = calloc(fsrc->nsections,
  116                                 sizeof(struct iso_file_section));
  117         if (fsrc->sections == NULL) {
  118             free(fsrc);
  119             return ISO_OUT_OF_MEM;
  120         }
  121         for (i = 0; i < fsrc->nsections; i++)
  122             fsrc->sections[i].block = 0;
  123     }
  124     fsrc->sort_weight = file->sort_weight;
  125     fsrc->stream = file->stream;
  126 
  127     /* insert the filesrc in the tree */
  128     ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
  129     if (ret <= 0) {
  130         if (ret == 0 && (*src)->checksum_index > 0 &&
  131             !img->opts->will_cancel) {
  132             /* Duplicate file source was mapped to previously registered source
  133             */
  134             cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
  135             if (cret < 0)
  136                 ret = cret;
  137         }
  138         free(fsrc->sections);
  139         free(fsrc);
  140         return ret;
  141     }
  142     iso_stream_ref(fsrc->stream);
  143 
  144     if ((img->opts->md5_file_checksums & 1) &&
  145         file->from_old_session && img->opts->appendable) {
  146         ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func,
  147                                   &xipt);
  148         if (ret <= 0)
  149             ret = iso_node_get_xinfo((IsoNode *) file, checksum_cx_xinfo_func,
  150                                       &xipt);
  151         if (ret <= 0)
  152             /* Omit MD5 indexing with old image nodes which have no MD5 */
  153             no_md5 = 1;
  154     }
  155 
  156     if ((img->opts->md5_file_checksums & 1) &&
  157         !(no_md5 || img->opts->will_cancel)) {
  158         img->checksum_idx_counter++;
  159         if (img->checksum_idx_counter < 0x7fffffff) {
  160             fsrc->checksum_index = img->checksum_idx_counter;
  161         } else {
  162             fsrc->checksum_index= 0;
  163             img->checksum_idx_counter= 0x7ffffffe; /* keep from rolling over */
  164         }
  165         cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
  166         if (cret < 0)
  167             return cret;
  168     }
  169 
  170     return ISO_SUCCESS;
  171 }
  172 
  173 /**
  174  * Add a given IsoFileSrc to the given image target.
  175  *
  176  * The IsoFileSrc will be cached in a tree to prevent the same file for
  177  * being written several times to image. If you call again this function
  178  * with a node that refers to the same source file, the previously
  179  * created one will be returned.
  180  *
  181  * @param img
  182  *      The image where this file is to be written
  183  * @param new
  184  *      The IsoFileSrc to add
  185  * @param src
  186  *      Will be filled with a pointer to the IsoFileSrc really present in
  187  *      the tree. It could be different than new if the same file already
  188  *      exists in the tree.
  189  * @return
  190  *      1 on success, 0 if file already exists on tree, < 0 error
  191  */
  192 int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src)
  193 {
  194     int ret;
  195 
  196     if (img == NULL || new == NULL || src == NULL) {
  197         return ISO_NULL_POINTER;
  198     }
  199 
  200     /* insert the filesrc in the tree */
  201     ret = iso_rbtree_insert(img->files, new, (void**)src);
  202     return ret;
  203 }
  204 
  205 void iso_file_src_free(void *node)
  206 {
  207     iso_stream_unref(((IsoFileSrc*)node)->stream);
  208     free(((IsoFileSrc*)node)->sections);
  209     free(node);
  210 }
  211 
  212 off_t iso_file_src_get_size(IsoFileSrc *file)
  213 {
  214     return iso_stream_get_size(file->stream);
  215 }
  216 
  217 static int cmp_by_weight(const void *f1, const void *f2)
  218 {
  219     IsoFileSrc *f = *((IsoFileSrc**)f1);
  220     IsoFileSrc *g = *((IsoFileSrc**)f2);
  221     /* higher weighted first */
  222     return g->sort_weight - f->sort_weight;
  223 }
  224 
  225 static
  226 int shall_be_written(void *arg)
  227 {
  228     IsoFileSrc *f = (IsoFileSrc *)arg;
  229     return f->no_write ? 0 : 1;
  230 }
  231 
  232 static
  233 int shall_be_written_if_not_taken(void *arg)
  234 {
  235     IsoFileSrc *f = (IsoFileSrc *)arg;
  236     return f->no_write || f->taken ? 0 : 1;
  237 }
  238 
  239 int filesrc_writer_pre_compute(IsoImageWriter *writer)
  240 {
  241     size_t i, size, is_external;
  242     Ecma119Image *t;
  243     IsoFileSrc **filelist;
  244     int (*inc_item)(void *);
  245     size_t omitted_count;
  246     IsoFileSrc **iso_ecma119_to_filesrc_array(Ecma119Image *t,
  247                                               int (*include_item)(void *),
  248                                               size_t *size);
  249 
  250     if (writer == NULL) {
  251         return ISO_ASSERT_FAILURE;
  252     }
  253 
  254     t = writer->target;
  255     t->filesrc_blocks = 0;
  256 
  257     /* Normally reserve a single zeroed block for all files which have
  258        no block address: symbolic links, device files, empty data files.
  259     */
  260     if (! t->opts->old_empty)
  261         t->filesrc_blocks++;
  262 
  263     /* on appendable images, ms files shouldn't be included */
  264     if (t->opts->appendable) {
  265         inc_item = shall_be_written;
  266     } else {
  267         inc_item = NULL;
  268     }
  269 
  270     /* store the filesrcs in a array */
  271     filelist = (IsoFileSrc**) iso_ecma119_to_filesrc_array(t, inc_item, &size);
  272     omitted_count = iso_rbtree_count_array(t->files, (size_t) 0,
  273                                            shall_be_written_if_not_taken);
  274     if (omitted_count > 0) {
  275         iso_msg_submit(t->image->id, ISO_NOT_REPRODUCIBLE, 0,
  276             "Cannot arrange content of data files in surely reproducible way");
  277         LIBISO_FREE_MEM(filelist);
  278         filelist = (IsoFileSrc**)iso_rbtree_to_array(
  279                                                     t->files, inc_item, &size);
  280     }
  281     if (filelist == NULL) {
  282         return ISO_OUT_OF_MEM;
  283     }
  284 
  285     /* sort files by weight, if needed */
  286     if (t->opts->sort_files) {
  287         qsort(filelist, size, sizeof(void*), cmp_by_weight);
  288     }
  289 
  290     /* fill block value */
  291     for (i = 0; i < size; ++i) {
  292         int extent = 0;
  293         IsoFileSrc *file = filelist[i];
  294         off_t section_size;
  295 
  296         /* 0xfffffffe in emerging image means that this is an external
  297            partition. Only assess extent sizes but do not count as part
  298            of filesrc_writer output.
  299         */
  300         is_external = (file->no_write == 0 &&
  301                        file->sections[0].block == 0xfffffffe);
  302 
  303         section_size = iso_stream_get_size(file->stream);
  304         for (extent = 0; extent < file->nsections - 1; ++extent) {
  305             file->sections[extent].block = t->filesrc_blocks + extent *
  306                         (ISO_EXTENT_SIZE / BLOCK_SIZE);
  307             file->sections[extent].size = ISO_EXTENT_SIZE;
  308             section_size -= (off_t) ISO_EXTENT_SIZE;
  309         }
  310 
  311         /*
  312          * final section
  313          */
  314         if (section_size <= 0) {
  315             /* Will become t->empty_file_block
  316                in filesrc_writer_compute_data_blocks()
  317                Special use of 0xffffffe0 to 0xffffffff is covered by
  318                mspad_writer which enforces a minimum start of filesrc at
  319                block 0x00000020.
  320             */
  321             file->sections[extent].block = 0xffffffff;
  322         } else {
  323             file->sections[extent].block =
  324                    t->filesrc_blocks + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE);
  325         }
  326         file->sections[extent].size = (uint32_t)section_size;
  327 
  328         /* 0xfffffffe in emerging image means that this is an external
  329            partition. Others will take care of the content data.
  330         */
  331         if (is_external) {
  332             file->sections[0].block = 0xfffffffe;
  333             file->no_write = 1; /* Ban for filesrc_writer */
  334     continue;
  335         }
  336 
  337         t->filesrc_blocks += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
  338     }
  339 
  340     /* the list is only needed by this writer, store locally */
  341     writer->data = filelist;
  342     return ISO_SUCCESS;
  343 }
  344 
  345 static
  346 int filesrc_writer_compute_data_blocks(IsoImageWriter *writer)
  347 {
  348     Ecma119Image *t;
  349     int extent = 0;
  350     size_t  i;
  351     IsoFileSrc *file;
  352     IsoFileSrc **filelist;
  353 
  354     if (writer == NULL) {
  355         return ISO_ASSERT_FAILURE;
  356     }
  357     t = writer->target;
  358     filelist = (IsoFileSrc **) writer->data;
  359 
  360     /* >>> HFS: need to align to allocation block size */;
  361     /* >>> HFS: ??? how to handle multi-extent files ? */;
  362 
  363     t->filesrc_start = t->curblock;
  364 
  365     /* Give all extent addresses their final absolute value */
  366     i = 0;
  367     while ((file = filelist[i++]) != NULL) {
  368 
  369        /* Skip external partitions */ 
  370        if (file->no_write)
  371     continue;
  372 
  373        for (extent = 0; extent < file->nsections; ++extent) {
  374             if (file->sections[extent].block == 0xffffffff)
  375                 file->sections[extent].block = t->empty_file_block;
  376             else
  377                 file->sections[extent].block += t->curblock;
  378        }
  379     }
  380 
  381     t->curblock += t->filesrc_blocks;
  382     return ISO_SUCCESS;
  383 }
  384 
  385 static
  386 int filesrc_writer_write_vol_desc(IsoImageWriter *writer)
  387 {
  388     /* nothing needed */
  389     return ISO_SUCCESS;
  390 }
  391 
  392 /* open a file, i.e., its Stream */
  393 static inline
  394 int filesrc_open(IsoFileSrc *file)
  395 {
  396     return iso_stream_open(file->stream);
  397 }
  398 
  399 static inline
  400 int filesrc_close(IsoFileSrc *file)
  401 {
  402     return iso_stream_close(file->stream);
  403 }
  404 
  405 /**
  406  * @return
  407  *     1 ok, 0 EOF, < 0 error
  408  */
  409 static
  410 int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
  411 {
  412     size_t got;
  413 
  414     return iso_stream_read_buffer(file->stream, buf, count, &got);
  415 }
  416 
  417 /* @return 1=ok, md5 is valid,
  418            0= not ok, go on,
  419           <0 fatal error, abort 
  420 */  
  421 static
  422 int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
  423 {
  424     return iso_stream_make_md5(file->stream, md5, 0);
  425 }
  426 
  427 /* name must be NULL or offer at least PATH_MAX characters.
  428    buffer must be NULL or offer at least BLOCK_SIZE characters.
  429 */
  430 int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file,
  431                            char *name, char *buffer, int flag)
  432 {
  433     int res, ret, was_error;
  434     char *name_data = NULL;
  435     char *buffer_data = NULL;
  436     size_t b;
  437     off_t file_size;
  438     uint32_t nblocks;
  439     void *ctx= NULL;
  440     char md5[16], pre_md5[16];
  441     int pre_md5_valid = 0;
  442     IsoStream *stream, *inp;
  443 
  444 #ifdef Libisofs_with_libjtE
  445     int jte_begun = 0;
  446 #endif
  447 
  448     if (name == NULL) {
  449         LIBISO_ALLOC_MEM(name_data, char, PATH_MAX);
  450         name = name_data;
  451     }
  452     if (buffer == NULL) {
  453         LIBISO_ALLOC_MEM(buffer_data, char, BLOCK_SIZE);
  454         buffer = buffer_data;
  455     }
  456 
  457     was_error = 0;
  458     file_size = iso_file_src_get_size(file);
  459     nblocks = DIV_UP(file_size, BLOCK_SIZE);
  460     pre_md5_valid = 0; 
  461     if (file->checksum_index > 0 && (t->opts->md5_file_checksums & 2)) {
  462         /* Obtain an MD5 of content by a first read pass */
  463         pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
  464     }
  465     res = filesrc_open(file);
  466 
  467     /* Get file name from end of filter chain */
  468     for (stream = file->stream; ; stream = inp) {
  469         inp = iso_stream_get_input_stream(stream, 0);
  470         if (inp == NULL)
  471     break;
  472     }
  473     iso_stream_get_file_name(stream, name);
  474     if (res < 0) {
  475         /*
  476          * UPS, very ugly error, the best we can do is just to write
  477          * 0's to image
  478          */
  479         iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
  480         was_error = 1;
  481         res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
  482                   "File \"%s\" can't be opened. Filling with 0s.", name);
  483         if (res < 0) {
  484             ret = res; /* aborted due to error severity */
  485             goto ex;
  486         }
  487         memset(buffer, 0, BLOCK_SIZE);
  488         for (b = 0; b < nblocks; ++b) {
  489             res = iso_write(t, buffer, BLOCK_SIZE);
  490             if (res < 0) {
  491                 /* ko, writer error, we need to go out! */
  492                 ret = res;
  493                 goto ex;
  494             }
  495         }
  496         ret = ISO_SUCCESS;
  497         goto ex;
  498     } else if (res > 1) {
  499         iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
  500         was_error = 1;
  501         res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
  502                   "Size of file \"%s\" has changed. It will be %s", name,
  503                   (res == 2 ? "truncated" : "padded with 0's"));
  504         if (res < 0) {
  505             filesrc_close(file);
  506             ret = res; /* aborted due to error severity */
  507             goto ex;
  508         }
  509     }
  510 #ifdef LIBISOFS_VERBOSE_DEBUG
  511     else {
  512         iso_msg_debug(t->image->id, "Writing file %s", name);
  513     }
  514 #endif
  515 
  516     /* >>> HFS: need to align to allocation block size */;
  517 
  518 #ifdef Libisofs_with_libjtE
  519     if (t->opts->libjte_handle != NULL) {
  520         res = libjte_begin_data_file(t->opts->libjte_handle, name,
  521                                      BLOCK_SIZE, file_size);
  522         if (res <= 0) {
  523             res = iso_libjte_forward_msgs(t->opts->libjte_handle, t->image->id,
  524                                     ISO_LIBJTE_FILE_FAILED, 0);
  525             if (res < 0) {
  526                 filesrc_close(file);
  527                 ret = ISO_LIBJTE_FILE_FAILED;
  528                 goto ex;
  529             }
  530         }
  531         jte_begun = 1;
  532     }
  533 #endif /* Libisofs_with_libjtE */
  534 
  535     if (file->checksum_index > 0) {
  536         /* initialize file checksum */
  537         res = iso_md5_start(&ctx);
  538         if (res <= 0)
  539             file->checksum_index = 0;
  540     }
  541     /* write file contents to image */
  542     for (b = 0; b < nblocks; ++b) {
  543         int wres;
  544         res = filesrc_read(file, buffer, BLOCK_SIZE);
  545         if (res < 0) {
  546             /* read error */
  547             break;
  548         }
  549         wres = iso_write(t, buffer, BLOCK_SIZE);
  550         if (wres < 0) {
  551             /* ko, writer error, we need to go out! */
  552             filesrc_close(file);
  553             ret = wres;
  554             goto ex;
  555         }
  556         if (file->checksum_index > 0) {
  557             /* Add to file checksum */
  558             if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
  559                 res = BLOCK_SIZE;
  560             else
  561                 res = file_size - b * BLOCK_SIZE;
  562             res = iso_md5_compute(ctx, buffer, res);
  563             if (res <= 0)
  564                 file->checksum_index = 0;
  565         }
  566     }
  567 
  568     filesrc_close(file);
  569 
  570     if (b < nblocks) {
  571         /* premature end of file, due to error or eof */
  572         iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
  573         was_error = 1;
  574         if (res < 0) {
  575             /* error */
  576             res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
  577                            "Read error in file %s.", name);
  578         } else {
  579             /* eof */
  580             res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
  581                           "Premature end of file %s.", name);
  582         }
  583 
  584         if (res < 0) {
  585             ret = res; /* aborted due error severity */
  586             goto ex;
  587         }
  588 
  589         /* fill with 0s */
  590         iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
  591                        "Filling with 0");
  592         memset(buffer, 0, BLOCK_SIZE);
  593         while (b++ < nblocks) {
  594             res = iso_write(t, buffer, BLOCK_SIZE);
  595             if (res < 0) {
  596                 /* ko, writer error, we need to go out! */
  597                 ret = res;
  598                 goto ex;
  599             }
  600             if (file->checksum_index > 0) {
  601                 /* Add to file checksum */
  602                 if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
  603                     res = BLOCK_SIZE;
  604                 else
  605                     res = file_size - b * BLOCK_SIZE;
  606                 res = iso_md5_compute(ctx, buffer, res);
  607                 if (res <= 0)
  608                     file->checksum_index = 0;
  609             }
  610         }
  611     }
  612     if (file->checksum_index > 0 &&
  613         file->checksum_index <= t->checksum_idx_counter) {
  614         /* Obtain checksum and dispose checksum context */
  615         res = iso_md5_end(&ctx, md5);
  616         if (res <= 0)
  617             file->checksum_index = 0;
  618         if ((t->opts->md5_file_checksums & 2) && pre_md5_valid > 0 &&
  619             !was_error) {
  620             if (! iso_md5_match(md5, pre_md5)) {
  621                 /* Issue MISHAP event */
  622                 iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
  623                 was_error = 1;
  624                 res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
  625        "Content of file '%s' changed while it was written into the image.",
  626                                      name);
  627                 if (res < 0) {
  628                     ret = res; /* aborted due to error severity */
  629                     goto ex;
  630                 }
  631             }
  632         }
  633         /* Write md5 into checksum buffer at file->checksum_index */
  634         memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
  635     }
  636 
  637     ret = ISO_SUCCESS;
  638 ex:;
  639     if (ctx != NULL) /* avoid any memory leak */
  640         iso_md5_end(&ctx, md5);
  641 
  642 #ifdef Libisofs_with_libjtE
  643     if (jte_begun) {
  644         res = libjte_end_data_file(t->opts->libjte_handle);
  645         iso_libjte_forward_msgs(t->opts->libjte_handle, t->image->id,
  646                                 ISO_LIBJTE_END_FAILED, 0);
  647         if (res <= 0 && ret >= 0)
  648             ret = ISO_LIBJTE_FILE_FAILED;
  649     }
  650 #endif /* Libisofs_with_libjtE */
  651 
  652     LIBISO_FREE_MEM(buffer_data);
  653     LIBISO_FREE_MEM(name_data);
  654     return ret;
  655 }
  656 
  657 static
  658 int filesrc_writer_write_data(IsoImageWriter *writer)
  659 {
  660     int ret;
  661     size_t i;
  662     Ecma119Image *t = NULL;
  663     IsoFileSrc *file;
  664     IsoFileSrc **filelist;
  665     char *name = NULL;
  666     char *buffer = NULL;
  667 
  668     if (writer == NULL) {
  669         ret = ISO_ASSERT_FAILURE; goto ex;
  670     }
  671 
  672     LIBISO_ALLOC_MEM(name, char, PATH_MAX);
  673     LIBISO_ALLOC_MEM(buffer, char, BLOCK_SIZE);
  674     t = writer->target;
  675     filelist = writer->data;
  676 
  677     iso_msg_debug(t->image->id, "Writing Files...");
  678 
  679     /* Normally write a single zeroed block as block address target for all
  680        files which have no block address:
  681        symbolic links, device files, empty data files.
  682     */
  683     if (! t->opts->old_empty) {
  684         ret = iso_write(t, buffer, BLOCK_SIZE);
  685         if (ret < 0)
  686             goto ex;
  687     }
  688 
  689     i = 0;
  690     while ((file = filelist[i++]) != NULL) {
  691         if (file->no_write) {
  692             /* Do not write external partitions */
  693             iso_msg_debug(t->image->id,
  694                           "filesrc_writer: Skipping no_write-src [%.f , %.f]",
  695                           (double) file->sections[0].block, 
  696                           (double) (file->sections[0].block - 1 +
  697                                 (file->sections[0].size + 2047) / BLOCK_SIZE));
  698     continue;
  699         }
  700         ret = iso_filesrc_write_data(t, file, name, buffer, 0);
  701         if (ret < 0)
  702             goto ex;
  703     }
  704 
  705     ret = ISO_SUCCESS;
  706 ex:;
  707     LIBISO_FREE_MEM(buffer);
  708     LIBISO_FREE_MEM(name);
  709     return ret;
  710 }
  711 
  712 
  713 static
  714 int filesrc_writer_free_data(IsoImageWriter *writer)
  715 {
  716     /* free the list of files (contents are free together with the tree) */
  717     free(writer->data);
  718     return ISO_SUCCESS;
  719 }
  720 
  721 int iso_file_src_writer_create(Ecma119Image *target)
  722 {
  723     IsoImageWriter *writer;
  724 
  725     writer = calloc(1, sizeof(IsoImageWriter));
  726     if (writer == NULL) {
  727         return ISO_OUT_OF_MEM;
  728     }
  729 
  730     writer->compute_data_blocks = filesrc_writer_compute_data_blocks;
  731     writer->write_vol_desc = filesrc_writer_write_vol_desc;
  732     writer->write_data = filesrc_writer_write_data;
  733     writer->free_data = filesrc_writer_free_data;
  734     writer->data = NULL;
  735     writer->target = target;
  736 
  737     /* add this writer to image */
  738     target->writers[target->nwriters++] = writer;
  739 
  740     return ISO_SUCCESS;
  741 }