Main Page   Modules   Data Structures   File List   Data Fields   Globals  

libdrc.c

Go to the documentation of this file.
00001 /*
00002  * libdrc.c
00003  * Created on 14 Mar 2005
00004  * Authors:
00005  *    Wesley Leggette <wleggette@kaylix.net>
00006  * 
00007  * 
00008  * 
00009  * libdarc
00010  * 
00011  * 
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025  * 
00026  * $Id: libdrc_8c-source.html 708 2005-03-21 12:30:37Z leggwes $
00027  */
00028 
00034 #include "libdrc.h"
00035 
00036 #if HAVE_ERRNO_H
00037 #include <errno.h>
00038 #endif
00039 
00040 #if HAVE_STDLIB_H
00041 #include <stdlib.h>
00042 #endif
00043 
00044 
00045 #include <libxml/parser.h>
00046 #include <libxml/tree.h>
00047 
00048 
00049 /* internal tool functions */
00050 
00051 static char* bool_to_string( bool val ); /* returns null on error */
00052 static bool string_to_bool( char* str, bool* val ); /* returns false on error */
00053 static char* allocate_copy_string( const char* source ); /* null indicates no mem */
00054 
00055 
00056 
00057 struct _dar_drc
00058 {
00059     enum { read_file, read_memory } read_mode;
00060     
00061     char* xml_buffer;
00062     char* xml_filename;
00063     
00064     int xml_buffer_size;
00065     
00066     char* dtd_filename;
00067     int dtd_version;
00068     
00069     xmlDocPtr doc;
00070     
00071     
00072     dar_sup_spec* spec;
00073     dar_sup_storage* storage;
00074     dar_sup_flags* flags;
00075     
00076     bool has_reference;
00077     
00078     dar_sup_spec* ref_spec;
00079     dar_sup_storage* ref_storage;
00080     dar_sup_flags* ref_flags;
00081     
00082     
00083 };
00084     
00085 
00086 
00087 
00088 
00089 
00090 /* internal process division functions */
00091 
00092 static char* get_dtd_location(const char* dtdfilepath, const char* version);
00093 static void validate_drc(dar_drc* ref, dar_sup_exception* exception);
00094 static void interpret_drc(dar_drc* ref, dar_sup_exception* exception);
00095 static bool dar_drc_prep(dar_drc* ref); /* null pointers and set defaults */
00096 static xmlNodePtr get_next_element_node(xmlNodePtr node);
00097 
00098 
00099 /* interpreters */
00100 
00101 static void interpret_drc_1_0(dar_drc* ref, dar_sup_exception* exception);
00102     
00103 
00104 /* library functions */
00105 
00106 char* dar_drc_get_passphrase( dar_drc* ref )
00107 {
00108     DEBUG("Function: dar_drc_get_passphrase: Retrieving passphrase.\n");
00109     if (ref->storage->crypto_pass == NULL)
00110         return NULL;
00111     char* ret = (char*)malloc(strlen(ref->storage->crypto_pass) + 1);
00112     if (ret == NULL) { return NULL; }
00113     strcpy( ret, ref->storage->crypto_pass );
00114     return ret;
00115 }
00116 
00117 bool dar_drc_set_passphrase( dar_drc* ref, char* passphrase )
00118 {
00119     DEBUG("Function: dar_drc_set_passphrase: Replacing passphrase.\n");
00120     char* tmp = ref->storage->crypto_pass;
00121     ref->storage->crypto_pass = (char*)malloc(strlen(passphrase) + 1);
00122     if (ref->storage->crypto_pass == NULL)
00123     {
00124         ref->storage->crypto_pass = tmp;
00125         return false;
00126     }
00127     strcpy( ref->storage->crypto_pass, passphrase );
00128     if (tmp != NULL)
00129         free(tmp);
00130     return true;
00131 }
00132 
00133 char* dar_drc_get_reference_passphrase( dar_drc* ref )
00134 {
00135     DEBUG("Function: dar_drc_get_reference_passphrase: Retrieving reference archive passphrase.\n");
00136     if (ref->ref_storage->crypto_pass == NULL)
00137         return NULL;
00138     char* ret = (char*)malloc(strlen(ref->ref_storage->crypto_pass) + 1);
00139     if (ret == NULL) { return NULL; }
00140     strcpy( ret, ref->ref_storage->crypto_pass );
00141     return ret;
00142 }
00143 
00144 bool dar_drc_set_reference_passphrase( dar_drc* ref, char* passphrase )
00145 {
00146     DEBUG("Function: dar_drc_set_reference_passphrase: Replacing reference archive passphrase.\n");
00147     char* tmp = ref->ref_storage->crypto_pass;
00148     ref->ref_storage->crypto_pass = (char*)malloc(strlen(passphrase) + 1);
00149     if (ref->ref_storage->crypto_pass == NULL)
00150     {
00151         ref->ref_storage->crypto_pass = tmp;
00152         return false;
00153     }
00154     strcpy( ref->ref_storage->crypto_pass, passphrase );
00155     if (tmp != NULL)
00156         free(tmp);
00157     return true;
00158 }
00159 
00160 bool dar_drc_has_reference(dar_drc* ref)
00161 {
00162     DEBUG("Function: dar_drc_has_reference: Querying if drc contains reference archive specs.\n");
00163     return ref->has_reference;
00164 }
00165 
00166 dar_archive* dar_drc_open_reference( dar_user_interaction_struct dialog,
00167                 dar_drc* ref, dar_sup_exception* exception )
00168 {
00169     DEBUG("Function: dar_drc_open_reference: Opening reference archive.\n");
00170 
00171     if (ref->has_reference)
00172     {
00173         DEBUG("Reference archive exists, opening.\n");
00174         dar_archive* ret = dar_op_archive_open( dialog, *(ref->ref_spec),
00175                                         *(ref->ref_storage), exception );
00176                                         
00177         if ( exception->type != LIBDAR_NOEXCEPT )
00178         {
00179             DEBUG("Exception caught, throwing.\n");
00180             return NULL;
00181         }
00182         return ret;
00183     } else {
00184         DEBUG("No reference archive exists, returning null.\n");
00185         return NULL;
00186     }
00187 }
00188 
00189 
00190 dar_sup_spec *dar_drc_get_spec( dar_drc* ref )
00191 {
00192     DEBUG("Function: dar_drc_get_spec: Retrieving archive spec struct.\n");
00193     return ref->spec;
00194 }
00195 
00196 dar_sup_storage *dar_drc_get_storage( dar_drc* ref )
00197 {
00198     DEBUG("Function: dar_drc_get_storage: Retrieving archive storage struct.\n");
00199     return ref->storage;
00200 }
00201 
00202 dar_sup_flags *dar_drc_get_flags( dar_drc* ref )
00203 {
00204     DEBUG("Function: dar_drc_get_flags: Retrieving archive flags struct.\n");
00205     return ref->flags;
00206 }
00207 
00208 void dar_drc_destroy( dar_drc *ref )
00209 {
00210     DEBUG("Function: dar_drc_destroy: Freeing drc context object.\n");
00211     if ( ref->doc != NULL )
00212         xmlFreeDoc(ref->doc);
00213     if ( ref->dtd_filename != NULL )
00214         free(ref->dtd_filename);
00215     if ( ref->xml_buffer != NULL )
00216     {
00217         free(ref->xml_buffer);
00218     }
00219     if ( ref->xml_filename != NULL )
00220     {
00221         free(ref->xml_filename);
00222     }
00223     if ( ref->flags != NULL )
00224     {
00225         free(ref->flags);
00226     }
00227     if ( ref->spec != NULL )
00228     {
00229         dar_sup_spec_destroy(ref->spec);
00230         free(ref->spec);
00231     }
00232     if ( ref->storage != NULL )
00233     {
00234         dar_sup_storage_destroy(ref->storage);
00235         free(ref->storage);
00236     }
00237     if ( ref->ref_spec != NULL )
00238     {
00239         dar_sup_spec_destroy(ref->ref_spec);
00240         free(ref->ref_spec);
00241     }
00242     if ( ref->ref_storage != NULL )
00243     {
00244         dar_sup_storage_destroy(ref->ref_storage);
00245         free(ref->ref_storage);
00246     }
00247     if ( ref->ref_flags != NULL )
00248     {
00249         free(ref->ref_flags);
00250     }
00251     
00252     free(ref);
00253     
00254     return;
00255 }
00256 
00257 dar_drc *dar_drc_create( dar_drc* reference,
00258                 dar_sup_spec* spec, dar_sup_storage* storage,
00259                 dar_sup_flags* flags )
00260 {
00261     DEBUG("Function: dar_drc_create: Creating drc from archive spec structures.\n");
00262     dar_drc* ret = (dar_drc*)malloc(sizeof(dar_drc));
00263     if (ret == NULL)
00264     {
00265         DEBUG("Memory exhausted, could not allocate drc context object.\n");
00266         return NULL;
00267     }
00268     
00269     DEBUG("Preping drc context.\n");
00270     
00271     if ( !dar_drc_prep(ret) )
00272     {
00273         DEBUG("Memory exhausted, could not allocate drc internal storage.\n");
00274         free(ret);
00275         return NULL;
00276     }
00277         
00278     DEBUG("Copying reference archive specification if applicable.\n");
00279     
00280     if (reference != NULL)
00281     {
00282         DEBUG("Copying reference archive elements: spec structure.\n");
00283         
00284         if (reference->spec->arc_path != NULL)
00285         {
00286             ret->ref_spec->arc_path = 
00287                     allocate_copy_string(reference->spec->arc_path);
00288             if ( ret->ref_spec->arc_path == NULL )
00289             {
00290                 DEBUG("Memory exhausted, could not allocate archive path copy.\n");
00291                 dar_drc_destroy(ret);
00292                 return NULL;
00293             }
00294         }
00295         
00296         if (reference->spec->arc_name != NULL)
00297         {
00298             ret->ref_spec->arc_name =
00299                     allocate_copy_string(reference->spec->arc_name);
00300             if ( ret->ref_spec->arc_name == NULL )
00301             {
00302                 DEBUG("Memory exhausted, could not allocate archive name copy.\n");
00303                 dar_drc_destroy(ret);
00304                 return NULL;
00305             }
00306         }
00307         
00308         if (reference->spec->arc_ext != NULL)
00309         {
00310             ret->ref_spec->arc_ext =
00311                     allocate_copy_string(reference->spec->arc_ext);
00312             if ( ret->ref_spec->arc_ext == NULL )
00313             {
00314                 DEBUG("Memory exhausted, could not allocate archive extension copy.\n");
00315                 dar_drc_destroy(ret);
00316                 return NULL;
00317             }
00318         }
00319         
00320         if (reference->spec->input_pipe != NULL)
00321         {
00322             ret->ref_spec->input_pipe =
00323                     allocate_copy_string(reference->spec->input_pipe);
00324             if ( ret->ref_spec->input_pipe == NULL )
00325             {
00326                 DEBUG("Memory exhausted, could not allocate input pipe name copy.\n");
00327                 dar_drc_destroy(ret);
00328                 return NULL;
00329             }
00330         }
00331         
00332         if (reference->spec->output_pipe != NULL)
00333         {
00334             ret->ref_spec->output_pipe =
00335                     allocate_copy_string(reference->spec->output_pipe);
00336             if ( ret->ref_spec->output_pipe == NULL )
00337             {
00338                 DEBUG("Memory exhausted, could not allocate output pipe name copy.\n");
00339                 dar_drc_destroy(ret);
00340                 return NULL;
00341             }
00342         }
00343         
00344         DEBUG("Copying reference archive elements: storage structure.\n");
00345         
00346         ret->ref_storage->crypto_algo =
00347                 reference->storage->crypto_algo;
00348                 
00349         ret->ref_storage->crypto_size =
00350                 reference->storage->crypto_size;
00351         
00352         if (reference->storage->crypto_pass != NULL)
00353         {
00354             ret->ref_storage->crypto_pass =
00355                     allocate_copy_string(reference->storage->crypto_pass);
00356             if ( ret->ref_storage->crypto_pass == NULL )
00357             {
00358                 DEBUG("Memory exhausted, could not allocate passphrase copy.\n");
00359                 dar_drc_destroy(ret);
00360                 return NULL;
00361             }
00362         }
00363         
00364         if (reference->storage->slice_execute != NULL)
00365         {
00366             ret->ref_storage->slice_execute =
00367                     allocate_copy_string(reference->storage->slice_execute);
00368             if ( ret->ref_storage->slice_execute == NULL )
00369             {
00370                 DEBUG("Memory exhausted, could not allocate interslice command copy.\n");
00371                 dar_drc_destroy(ret);
00372                 return NULL;
00373             }
00374         }
00375         
00376         DEBUG("Finished copying reference archive elements.\n");
00377     }
00378     
00379     DEBUG("Inserting archive specification structures.\n");
00380     
00381     ret->spec = spec;
00382     ret->storage = storage;
00383     ret->flags = flags;
00384     
00385     return ret; 
00386 }
00387 
00388 bool dar_drc_write_xml_file( const char* filename,
00389                 dar_sup_exception* exception )
00390 {
00391     DEBUG("Function: dar_drc_write_xml_file: Writing drc to file.\n");
00392     /* TODO: Implement this function */
00393     LIBDARC_EXCEPTION(exception, LIBDAR_ELIBCALL,
00394         "Library call not yet implemented.");
00395     return false;
00396     
00397 }
00398 
00399 char* dar_drc_write_xml_buffer( dar_sup_exception* exception )
00400 {
00401     DEBUG("Function: dar_drc_write_xml_buffer: Writing drc to memory.\n");
00402     /* TODO: Implement this function */
00403     LIBDARC_EXCEPTION(exception, LIBDAR_ELIBCALL,
00404         "Library call not yet implemented.");
00405     return NULL;
00406 }
00407 
00408 dar_drc *dar_drc_parse_xml_memory( const char* buffer, int size,
00409                 const char* dtdfilepath, dar_sup_exception* exception )
00410 {
00411     exception->type = LIBDAR_NOEXCEPT;
00412     
00413     DEBUG("Function: dar_drc_parse_xml_memory: Building drc from memory.\n");
00414     dar_drc* ret = (dar_drc*)malloc(sizeof(dar_drc));
00415     if (ret == NULL)
00416     {
00417         LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00418             "Memory exhausted, could not allocate drc context object.");
00419         return NULL;
00420     }
00421     
00422     DEBUG("Prepring drc content.\n");
00423     
00424     if ( !dar_drc_prep(ret) )
00425     {
00426         LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00427             "Memory exhausted, could not allocate drc internal storage.");
00428         free(ret);
00429         return NULL;
00430     }
00431     
00432     ret->read_mode = read_memory;
00433     ret->xml_buffer = (char*)malloc(size);
00434     if (ret->xml_buffer == NULL)
00435     {
00436         LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00437             "Memory exhausted, could not allocate xml buffer copy.");
00438         dar_drc_destroy(ret);
00439         return NULL;
00440     }
00441     memcpy( ret->xml_buffer, buffer, size );
00442     ret->xml_buffer_size = size;
00443     
00444     ret->doc = xmlReadMemory(ret->xml_buffer, size, NULL, NULL, 0);
00445     if (ret->doc == NULL)
00446     {
00447         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
00448             "Failed to parse xml file.");
00449         dar_drc_destroy(ret);
00450         return NULL;
00451     }
00452     
00453     if (dtdfilepath != NULL)
00454     {
00455         ret->dtd_filename = allocate_copy_string(dtdfilepath);
00456         if (ret->dtd_filename == NULL)
00457         {
00458             LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00459                 "Memory exhausted, could not allocate dtd filename copy.");
00460             dar_drc_destroy(ret);
00461             return NULL;
00462         }
00463     } else {
00464         ret->dtd_filename = NULL;
00465     }
00466     
00467     validate_drc(ret, exception);
00468     if (exception->type != LIBDAR_NOEXCEPT)
00469     {
00470         DEBUG("Exception caught, cleaning up and throwing.\n");
00471         dar_drc_destroy(ret);
00472         return NULL;
00473     }
00474     
00475     interpret_drc(ret, exception);
00476     if (exception->type != LIBDAR_NOEXCEPT)
00477     {
00478         DEBUG("Exception caught, cleaning up and throwing.\n");
00479         dar_drc_destroy(ret);
00480         return NULL;
00481     }
00482     
00483     DEBUG("File parsing complete, returning drc object.\n");
00484     return ret;
00485 }
00486 
00487 dar_drc *dar_drc_parse_xml_file( const char* filename, 
00488     const char* dtdfilepath, dar_sup_exception* exception)
00489 {
00490     exception->type = LIBDAR_NOEXCEPT;
00491     
00492     DEBUG("Function: dar_drc_parse_xml_file: Building drc from file.\n");
00493     dar_drc* ret = (dar_drc*)malloc(sizeof(dar_drc));
00494     if (ret == NULL)
00495     {
00496         LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00497             "Memory exhausted, could not allocate drc context object.");
00498         return NULL;
00499     }
00500     
00501     /* set defaults, prep for panic on caught exceptions, and allocate
00502      * internal storage
00503      */
00504      
00505     DEBUG("Preping drc content.\n");
00506      
00507     if ( !dar_drc_prep(ret) )
00508     {
00509         LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00510             "Memory exhausted, could not allocate drc internal storage.");
00511         free(ret);
00512         return NULL;
00513     }
00514     
00515     ret->read_mode = read_file;
00516     ret->xml_filename = allocate_copy_string(filename);
00517     if (ret->xml_filename == NULL)
00518     {
00519         LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00520             "Memory exhausted, could not allocate xml filename copy.");
00521         dar_drc_destroy(ret);
00522         return NULL;
00523     }
00524     ret->doc = xmlReadFile(filename, NULL, 0);
00525     if (ret->doc == NULL)
00526     {
00527         LIBDARC_EXCEPTION( exception, LIBDAR_X_EINPUTSPEC,
00528             "Failed to parse xml file.");
00529         dar_drc_destroy(ret);
00530         return NULL;
00531     }
00532     
00533     if (dtdfilepath != NULL)
00534     {
00535         ret->dtd_filename = allocate_copy_string(dtdfilepath);
00536         if (ret->dtd_filename == NULL)
00537         {
00538             LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00539                 "Memory exhausted, could not allocate dtd filename copy.");
00540             dar_drc_destroy(ret);
00541             return NULL;
00542         }
00543     } else {
00544         ret->dtd_filename = NULL;
00545     }
00546     
00547     
00548     validate_drc(ret, exception);
00549     if (exception->type != LIBDAR_NOEXCEPT)
00550     {
00551         DEBUG("Exception caught, cleaning up and throwing.\n");
00552         dar_drc_destroy(ret);
00553         return NULL;
00554     }
00555     
00556     interpret_drc(ret, exception);
00557     if (exception->type != LIBDAR_NOEXCEPT)
00558     {
00559         DEBUG("Exception caught, cleaning up and throwing.\n");
00560         dar_drc_destroy(ret);
00561         return NULL;
00562     }
00563     
00564     DEBUG("File parsing complete, returning drc object.\n");
00565     return ret;
00566 }
00567 
00568 static void validate_drc(dar_drc* ref, dar_sup_exception* exception)
00569 {
00570     DEBUG("Function: validate_drc: Validating drc file against dtd.\n");
00571     
00572     
00573     /* get xml file version */
00574     DEBUG("Determining xml file version.\n");
00575     
00576     xmlNodePtr root = xmlDocGetRootElement(ref->doc);
00577     
00578     if ( strcmp("JobSettings", root->name) != 0 )
00579     {
00580         DEBUG("Root node named %s.\n", root->name);
00581         LIBDARC_EXCEPTION( exception, LIBDAR_X_EINPUTSPEC,
00582             "Input file not valid, incorrect root node.");
00583         return;
00584     }
00585     
00586     if ( !xmlHasProp(root, "FileVersion") )
00587     {
00588         LIBDARC_EXCEPTION( exception, LIBDAR_X_EINPUTSPEC,
00589             "Input file not valid, file version not present.");
00590         return;
00591     }
00592     
00593     xmlChar* version = xmlGetProp(root, "FileVersion");
00594     if (version == NULL)
00595     {
00596         LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00597             "Memory exhausted, could not allocate version attribute copy.");
00598         return;
00599     }
00600     DEBUG("Input file version: %s\n", version);
00601     
00602     if ( strcmp( version, "1.0" ) == 0 )
00603     {
00604         ref->dtd_version = 10;
00605     } else {
00606         LIBDARC_EXCEPTION( exception, LIBDAR_X_EINPUTSPEC,
00607             "Input file version not supported.");
00608     }
00609     
00610     DEBUG("Loading dtd.\n");
00611     
00612     char* filename = ref->dtd_filename;
00613     ref->dtd_filename = get_dtd_location( filename, version );
00614     if (ref->dtd_filename == NULL)
00615     {
00616         LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00617             "Memory exhausted, could not allocate dtd path.");
00618         return;
00619     }
00620     if (filename != NULL)
00621         free(filename);
00622     xmlFree(version);
00623     
00624     DEBUG("Dtd file path: %s\n", ref->dtd_filename);
00625     
00626     xmlValidCtxtPtr ctxt = xmlNewValidCtxt();
00627     if (ctxt == NULL)
00628     {
00629         LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00630             "Memory exhausted, could not allocate xml validation context.");
00631         return;
00632     }
00633     
00634     xmlDtdPtr dtd = xmlParseDTD(NULL, ref->dtd_filename);
00635     if (dtd == NULL)
00636     {
00637         LIBDARC_EXCEPTION( exception, LIBDAR_EMEMORY,
00638             "Memory exhausted, could not allocate dtd object.");
00639         xmlFreeValidCtxt(ctxt);
00640         return;
00641     }
00642     
00643     if ( !xmlValidateDtd( ctxt, ref->doc, dtd ) )
00644     {
00645         LIBDARC_EXCEPTION( exception, LIBDAR_X_EINPUTSPEC,
00646             "Input file invalid, validation against DTD failed.");
00647         xmlFreeValidCtxt(ctxt);
00648         return;
00649     }
00650     xmlFreeValidCtxt(ctxt);
00651     
00652     DEBUG("Freeing dtd context.\n");
00653     xmlFreeDtd(dtd);
00654     
00655     return; 
00656 }
00657 
00658 static void interpret_drc(dar_drc* ref, dar_sup_exception* exception)
00659 {
00660     DEBUG("Function: interpret_drc: Translating drc xml tree to libdarc specs.\n");
00661     
00662     switch ( ref->dtd_version )
00663     {
00664         case 10: /* 1.0 */
00665             interpret_drc_1_0(ref, exception);
00666             DEBUG("Exit function: interpret_drc_1_0\n");
00667             DEBUG("Returned: %d\n", exception->type);
00668             break;
00669         default:
00670             LIBDARC_EXCEPTION(exception, LIBDAR_EBUG,
00671                 "Requested drc interpreter invalid.");
00672             break;
00673     }
00674     return;
00675 }
00676 
00677 
00678 
00679 
00680 /* interpreter definitions */
00681 
00682 /* pass MaskUnion or Mask element */
00683 static dar_mask *interpret_drc_1_0_recurse_mask(xmlNodePtr node,
00684             dar_drc* ref, dar_sup_exception* exception)
00685 {
00686     DEBUG("Function: interpret_drc_1_0_recurse_mask: Interpret mask elements.\n");
00687     
00688     xmlChar* type = xmlGetProp(node, "Type");
00689     if (type == NULL)
00690     {
00691         LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00692             "Memory exhausted, could not allocate attribute copy.");
00693     }
00694     DEBUG("Element type: %s\n", type);
00695     
00696     dar_mask* ret;
00697     
00698     /* process MaskUnion elements first, then Mask elements */
00699     if ( strcmp( node->name, "MaskUnion") == 0 )
00700     {
00701         enum { type_or, type_and, type_not } union_type;
00702         
00703         
00704         DEBUG("Interpreting MaskUnion type.\n");
00705         dar_mask* in = NULL;
00706         xmlNodePtr tmp = node->children;
00707         
00708         DEBUG("Building specific mask union container.\n");
00709         
00710         if ( strcmp(type, "and") == 0 )
00711         {
00712             DEBUG("And union found.\n");
00713             union_type = type_and;
00714             ret = dar_mask_create_and();
00715         } else if ( strcmp(type, "or") == 0 )
00716         {
00717             DEBUG("Or union found.\n");
00718             union_type = type_or;
00719             ret = dar_mask_create_or();
00720         } else if ( strcmp(type, "not") == 0 )
00721         { /* contains its own child seek loop, doesn't use shared loop below */
00722             DEBUG("Not union found.\n");
00723             union_type = type_not;
00724             
00725             dar_mask* in = NULL;
00726             xmlNodePtr tmp = node->children;
00727             
00728             DEBUG("Finding union element.\n"); /* only one element */
00729             
00730             do
00731             {
00732                 DEBUG("Element type: %d\n", tmp->type);
00733                 DEBUG("Element name: %s\n", tmp->name);
00734                 if ( tmp->type == XML_ELEMENT_NODE )
00735                 {
00736                     DEBUG("Element selected.\n");
00737                     in = interpret_drc_1_0_recurse_mask(tmp, ref, exception);
00738                     if ( exception->type != LIBDAR_NOEXCEPT)
00739                     {
00740                         xmlFree(type);
00741                         return NULL;
00742                     } 
00743                     break;
00744                 }
00745             } while ( (tmp = tmp->next) != tmp->last );
00746             
00747             if (in == NULL)
00748             {
00749                 LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
00750                     "Input file invalid, no child node for not mask.");
00751                 xmlFree(type);
00752                 return NULL;
00753             }
00754             
00755             ret = dar_mask_create_not(in);
00756             if (ret == NULL)
00757             {
00758                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00759                     "Memory exhausted, could not allocate mask object.");
00760             }
00761             xmlFree(type);
00762             dar_mask_destroy(in);
00763             return ret;
00764         } else {
00765             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
00766                 "Input file invalid, mask union type not valid.");
00767             xmlFree(type);
00768             return NULL;
00769         } /* end of type selection, and/or mask unions continue here */
00770         
00771         if (ret == NULL)
00772         {
00773             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00774                 "Memory exhausted, could not allocate mask object.");
00775             xmlFree(type);
00776             return NULL;
00777         }
00778         
00779         DEBUG("Finding union elements.\n");
00780         
00781         for (; tmp; tmp = tmp->next)
00782         {
00783             DEBUG("Next node: %s\n", tmp->name);
00784             
00785             if (tmp->type == XML_ELEMENT_NODE)
00786             {
00787                 DEBUG("Element selected.\n");
00788                 in = interpret_drc_1_0_recurse_mask(tmp, ref, exception);
00789                 if ( exception->type != LIBDAR_NOEXCEPT )
00790                 {
00791                     dar_mask_destroy(ret);
00792                     xmlFree(type);
00793                     return NULL;
00794                 } else {
00795                     switch(union_type)
00796                     {
00797                         case type_and:
00798                             dar_mask_and_add(ret, in);
00799                             break;
00800                         case type_or:
00801                             dar_mask_or_add(ret, in);
00802                             break;
00803                         default:
00804                             LIBDARC_EXCEPTION(exception, LIBDAR_EBUG,
00805                                 "Invalid mask union type selected.");
00806                             dar_mask_destroy(in);
00807                             dar_mask_destroy(ret);
00808                             xmlFree(type);
00809                             return NULL;
00810                     }
00811                 }
00812                 dar_mask_destroy(in);
00813             }
00814         }
00815         xmlFree(type);
00816         return ret;
00817         
00818     } else {
00819         DEBUG("Check for mask element properties.\n");
00820         
00821         bool case_sensit = true;
00822         if ( xmlHasProp(node, "CaseSensitive") )
00823         {
00824             xmlChar* cs_tmp = xmlGetProp(node, "CaseSensitive");
00825             if ( !string_to_bool( cs_tmp, &case_sensit ) )
00826             {
00827                 LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
00828                     "Input file invalid, could not parse case sensitive setting.");
00829                 xmlFree(cs_tmp);
00830                 xmlFree(type);
00831                 return NULL;
00832             }
00833             xmlFree(cs_tmp);
00834         }
00835         
00836         
00837         if ( strcmp(type, "samepath") == 0 )
00838         {
00839             DEBUG("Samepath node type found.\n");
00840             xmlChar* cont = xmlNodeGetContent(node);
00841             ret = dar_mask_create_same_path(cont, case_sensit);
00842             if (ret == NULL)
00843             {
00844                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00845                     "Memory exhausted, could not allocate mask object.");
00846             }
00847             xmlFree(type);
00848             xmlFree(cont);
00849             return ret;
00850         } else if ( strcmp(type, "boolean") == 0 )
00851         {
00852             DEBUG("Boolean node type found.\n");
00853             xmlChar* cont = xmlNodeGetContent(node);
00854             bool tmpb;
00855             if ( !string_to_bool( cont, &tmpb ) )
00856             {
00857                 LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
00858                     "Input file invalid, could not parse boolean mask setting.");
00859                 xmlFree(type);
00860                 xmlFree(cont);
00861                 return NULL;
00862             }
00863             ret = dar_mask_create_bool( tmpb );
00864             if (ret == NULL)
00865             {
00866                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00867                     "Memory exhausted, could not allocate mask object.");
00868             }
00869             xmlFree(type);
00870             xmlFree(cont);
00871             return ret;
00872         } else if ( strcmp(type, "excludedir") == 0 )
00873         {
00874             DEBUG("Exclude dir node type found.\n");
00875             xmlChar* cont = xmlNodeGetContent(node);
00876             ret = dar_mask_create_exclude_dir(cont, case_sensit);
00877             if (ret == NULL)
00878             {
00879                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00880                     "Memory exhausted, could not allocate mask object.");
00881             }
00882             xmlFree(type);
00883             xmlFree(cont);
00884             return ret;
00885         } else if ( strcmp(type, "regular") == 0 )
00886         {
00887             DEBUG("Regular node type found.\n");
00888             xmlChar* cont = xmlNodeGetContent(node);
00889             ret = dar_mask_create_regular(cont, case_sensit);
00890             if (ret == NULL)
00891             {
00892                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00893                     "Memory exhausted, could not allocate mask object.");
00894             }
00895             xmlFree(type);
00896             xmlFree(cont);
00897             return ret;
00898         } else if ( strcmp(type, "simple") == 0 )
00899         {
00900             DEBUG("Simple node type found.\n");
00901             xmlChar* cont = xmlNodeGetContent(node);
00902             ret = dar_mask_create_simple(cont, case_sensit);
00903             if (ret == NULL)
00904             {
00905                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00906                     "Memory exhausted, could not allocate mask object.");
00907             }
00908             xmlFree(type);
00909             xmlFree(cont);
00910             return ret;
00911         } else if ( strcmp(type, "simplepath") == 0 )
00912         {
00913             DEBUG("Simple path node type found.\n");
00914             xmlChar* cont = xmlNodeGetContent(node);
00915             ret = dar_mask_create_simple_path(cont, case_sensit);
00916             if (ret == NULL)
00917             {
00918                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
00919                     "Memory exhausted, could not allocate mask object.");
00920             }
00921             xmlFree(type);
00922             xmlFree(cont);
00923             return ret;
00924         } else {
00925             DEBUG("Invalid node type found: %s\n", type);
00926             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
00927                 "Input file invalid, mask type not supported.");
00928             xmlFree(type);
00929             return NULL;
00930         }
00931     }
00932 }
00933 
00934 /* TODO: The following function should be optimized at some point. */
00935 
00936 /* pass first child of Flags element. */
00937 static void interpret_drc_1_0_recurse_flags(xmlNodePtr node,
00938             dar_drc* ref, dar_sup_exception* exception)
00939 {
00940     DEBUG("Function: interpret_drc_1_0_recurse_flags: Interpret flag elements.\n");
00941     if ( node == NULL )
00942     {
00943         return;
00944     }
00945     
00946     /* switch across flag types */
00947     bool tmp;
00948     xmlChar* cont = xmlNodeGetContent(node);
00949     if (!string_to_bool(cont, &tmp))
00950     {
00951         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
00952             "Input file invalid, flag content not valid.");
00953         if (cont != NULL)
00954             xmlFree(cont);
00955         return;
00956     }
00957     xmlFree(cont);
00958     
00959     DEBUG("Element name: %s\n", node->name);
00960     DEBUG("Element value: %d\n", tmp);
00961     
00962     if ( strcmp(node->name, "AllowOverwrite") == 0 )
00963     {
00964         ref->flags->allow_overwrite = tmp;
00965     } else if ( strcmp(node->name, "WarnOverwrite") == 0 )
00966     {
00967         ref->flags->warn_overwrite = tmp;
00968     } else if ( strcmp(node->name, "SlicePause") == 0 )
00969     {
00970         ref->flags->slice_pause = tmp;
00971     } else if ( strcmp(node->name, "CreateEmptyStubs") == 0 )
00972     {
00973         ref->flags->create_empty_stubs = tmp;
00974     } else if ( strcmp(node->name, "EaSystem") == 0 )
00975     {
00976         ref->flags->ea_system = tmp;
00977     } else if ( strcmp(node->name, "EaUser") == 0 )
00978     {
00979         ref->flags->ea_user = tmp;
00980     } else if ( strcmp(node->name, "NoDump") == 0 )
00981     {
00982         ref->flags->no_dump = tmp;
00983     } else if ( strcmp(node->name, "IgnoreOwner") == 0 )
00984     {
00985         ref->flags->ignore_owner = tmp;
00986     } else if ( strcmp(node->name, "TestRun") == 0 )
00987     {
00988         ref->flags->test_run = tmp;
00989     } else if ( strcmp(node->name, "AlterAtime") == 0 )
00990     {
00991         ref->flags->alter_atime = tmp;
00992     } else if ( strcmp(node->name, "SameFs") == 0 )
00993     {
00994         ref->flags->same_fs = tmp;
00995     } else if ( strcmp(node->name, "DeleteMarked") == 0 )
00996     {
00997         ref->flags->delete_marked = tmp;
00998     } else if ( strcmp(node->name, "RestoreFlat") == 0 )
00999     {
01000         ref->flags->restore_flat = tmp;
01001     } else if ( strcmp(node->name, "WarnRemoveNoMatch") == 0 )
01002     {
01003         ref->flags->warn_remove_no_match = tmp;
01004     } else if ( strcmp(node->name, "OnlyMoreRecent") == 0 )
01005     {
01006         ref->flags->only_more_recent = tmp;
01007     } else if ( strcmp(node->name, "TarFormat") == 0 )
01008     {
01009         ref->flags->tar_format = tmp;
01010     } else if ( strcmp(node->name, "FilterUnsaved") == 0 )
01011     {
01012         ref->flags->filter_unsaved = tmp;
01013     } else
01014     {
01015         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01016             "Input file invalid, flag element unsupported.");
01017     }
01018     
01019     node = get_next_element_node(node->next);
01020     
01021     interpret_drc_1_0_recurse_flags(node, ref, exception);
01022     return;
01023 }
01024 
01025 /* pass Encryption element */   
01026 static void interpret_drc_1_0_encryption(xmlNodePtr node,
01027             dar_drc* ref, dar_sup_exception* exception)
01028 {
01029     DEBUG("Function: interpret_drc_1_0_encryption: Interpreting encryption element.\n");
01030     xmlChar* algo = xmlGetProp(node, "Algorithm");
01031     
01032     if (strcmp( algo, "none" ) == 0 )
01033     {
01034         ref->storage->crypto_algo = dar_crypto_none;
01035         xmlFree(algo);
01036         return;
01037     }   
01038     
01039     if ( strcmp( algo, "blowfish" ) == 0 )
01040     {
01041         ref->storage->crypto_algo = dar_crypto_blowfish;
01042     } else if ( strcmp( algo, "scrambling" ) == 0 )
01043     {
01044         ref->storage->crypto_algo = dar_crypto_scrambling;
01045     } else
01046     {
01047         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01048             "Input file invalid, encryption algorithm unsupported.");
01049         xmlFree(algo);
01050         return;
01051     }
01052     xmlFree(algo);
01053     
01054     xmlChar* block = xmlGetProp(node, "BlockSize");
01055     
01056     errno = 0;
01057     long s = strtol(block, NULL, 10);
01058     if ( errno != 0 || s >= U_32_MAX )
01059     {
01060         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01061             "Input file invalid, could not parse block size.");
01062         xmlFree(block);
01063         return;
01064     }
01065     xmlFree(block);
01066     
01067     ref->storage->crypto_size = (U_32)s;
01068     
01069     xmlChar* cont = xmlNodeGetContent(node);
01070     if ( cont == NULL || strcmp ( cont, "" ) == 0 )
01071     {
01072         return;
01073     } else {
01074         ref->storage->crypto_pass = allocate_copy_string(cont);
01075         if ( ref->storage->crypto_pass == NULL )
01076         {
01077             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01078                 "Memory exhausted, could not allocate passphrase copy.");
01079         }
01080     }
01081     
01082     if ( cont != NULL )
01083         xmlFree(cont);
01084     
01085     return;
01086 }
01087 
01088 /* pass Compression element */
01089 static void interpret_drc_1_0_compression(xmlNodePtr node,
01090             dar_drc* ref, dar_sup_exception* exception)
01091 {
01092     DEBUG("Function: interpret_drc_1_0_compression: Interpreting compression element.\n");
01093     xmlChar* algo = xmlGetProp(node, "Algorithm");
01094     
01095     if ( strcmp( algo, "none" ) == 0 )
01096     {
01097         ref->storage->compress_algo = dar_compression_none;
01098         xmlFree(algo);
01099         return;
01100     }
01101     
01102     if ( strcmp( algo, "zip" ) == 0 )
01103     {
01104         ref->storage->compress_algo = dar_compression_zip;
01105     } else if ( strcmp( algo, "gzip" ) == 0 )
01106     {
01107         ref->storage->compress_algo = dar_compression_gzip;
01108     } else if ( strcmp( algo, "bzip2" ) == 0 )
01109     {
01110         ref->storage->compress_algo = dar_compression_bzip2;
01111     } else 
01112     {
01113         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01114             "Input file invalid, compression algorithm unsupported.");
01115         xmlFree(algo);
01116         return;
01117     }
01118     xmlFree(algo);
01119     
01120     xmlChar* tn = xmlGetProp(node, "Level");
01121     
01122     errno = 0;
01123     long s = strtol(tn, NULL, 10);
01124     if ( errno != 0 || s > 9 )
01125     {
01126         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01127             "Input file invalid, compression level invalid.");
01128         xmlFree(tn);
01129         return;
01130     }
01131     xmlFree(tn);
01132     
01133     ref->storage->compress_level = (U_I)s;
01134     
01135     tn = xmlGetProp(node, "MinSize");
01136     
01137     dar_infinint* si = dar_infhs(tn);
01138     if ( si == NULL )
01139     {
01140         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01141             "Input file invalid, compression minimum size invalid.");
01142         xmlFree(tn);
01143         dar_infinint_destroy(si);
01144         return;
01145     }
01146     xmlFree(tn);
01147     
01148     ref->storage->compress_min_size = si;
01149     
01150     xmlNodePtr ch = node->children;
01151     
01152     if ( ch->type != XML_ELEMENT_NODE )
01153     {
01154         ch = get_next_element_node(ch);
01155     }
01156     
01157     ref->storage->compress_mask = 
01158             interpret_drc_1_0_recurse_mask(ch, ref, exception);
01159     if ( exception->type != LIBDAR_NOEXCEPT )
01160     {
01161         DEBUG("Exception caught, throwing.\n");
01162         return;
01163     }
01164     return;
01165 }
01166 
01167 /* pass SliceSize element */
01168 static void interpret_drc_1_0_slice_size(xmlNodePtr node,
01169             dar_drc* ref, dar_sup_exception* exception)
01170 {
01171     DEBUG("Function: interpret_drc_1_0_slice_size: Interpreting slice size element.\n");
01172     xmlChar* tmp = NULL;
01173     if ( xmlHasProp( node, "Initial" ) )
01174     {
01175         tmp = xmlGetProp(node, "Initial");
01176         if (tmp == NULL)
01177         {
01178             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01179                 "Memory exhausted, could not allocate copy of intial size.");
01180             return;
01181         }
01182         dar_infinint* ti = dar_tools_get_extended_size(tmp, 1024);
01183         if (ti == NULL)
01184         {
01185             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01186                 "Input file invalid, could not parse initial slice size.");
01187             xmlFree(tmp);
01188             return;
01189         }
01190         xmlFree(tmp);
01191         ref->storage->first_file_size = ti;
01192     }
01193     tmp = xmlNodeGetContent(node);
01194     if (tmp == NULL)
01195     {
01196         LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01197             "Memory exhausted, could not allocate copy of size element.");
01198         return;
01199     }
01200     dar_infinint* tib = dar_tools_get_extended_size(tmp, 1024);
01201     if (tib == NULL)
01202     {
01203         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01204             "Input file invalid, could not parse slice size.");
01205         xmlFree(tmp);
01206         return;
01207     }
01208     xmlFree(tmp);
01209     ref->storage->file_size = tib;
01210     
01211     return;
01212 }
01213 
01214 /* pass Archive element */
01215 static void interpret_drc_1_0_archive(xmlNodePtr node,
01216             dar_drc* ref, dar_sup_exception* exception)
01217 {
01218     DEBUG("Function: interpret_drc_1_0_archive: Interpreting archive element.\n");
01219     if ( !xmlHasProp(node, "Type") )
01220     {
01221         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01222             "Input file invalid, archive element does not have type attribute.");
01223         return;
01224     }
01225     
01226     xmlChar* type = xmlGetProp(node, "Type");
01227     if (type == NULL)
01228     {
01229         LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01230             "Memory exhausted, could not allocate copy of archive spec type.");
01231         return;
01232     }
01233     
01234     xmlChar* tmp = NULL;
01235     if ( strcmp(type, "pipeset") == 0 )
01236     {
01237         xmlFree(type);
01238         tmp = xmlNodeGetContent(node);
01239         if (tmp == NULL)
01240         {
01241             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01242                 "Input file invalid, pipe elements not listed in archive element.");
01243             return;
01244         }
01245         char* l = NULL;
01246         char* t = NULL;
01247         t = strtok_r(tmp, ";", &l);
01248         if (t == NULL)
01249         {
01250             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01251                 "Input file invalid, input pipe string not found.");
01252             xmlFree(tmp);
01253             return;
01254         }
01255         ref->spec->input_pipe = allocate_copy_string(t);
01256         if ( ref->spec->input_pipe == NULL )
01257         {
01258             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01259                 "Memory exhausted, could not allocate copy of input pipe.");
01260         }
01261         t = strtok_r(NULL, ";", &l);
01262         if (t == NULL)
01263         {
01264             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01265                 "Input file invalid, output pipe string not found.");
01266             xmlFree(tmp);
01267             return;
01268         }
01269         ref->spec->output_pipe = allocate_copy_string(t);
01270         if ( ref->spec->output_pipe == NULL )
01271         {
01272             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01273                 "Memory exhausted, could not allocate copy of output pipe.");
01274         }
01275         xmlFree(tmp);
01276         
01277         ref->spec->arc_path = allocate_copy_string("");
01278         if ( ref->spec->arc_path == NULL )
01279         {
01280             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01281                 "Memory exhausted, could not allocate empty archive path.");
01282         }
01283         
01284         ref->spec->arc_ext = allocate_copy_string("dar");
01285         if ( ref->spec->arc_ext == NULL )
01286         {
01287             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01288                 "Memory exhausted, could not allocate set archive extension.");
01289         }
01290         
01291         /* "-" activates pipeset in libdar library */
01292         ref->spec->arc_name = allocate_copy_string("-");
01293         if ( ref->spec->arc_name == NULL )
01294         {
01295             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01296                 "Memory exhausted, could not allocate set archive name.");
01297         }
01298         
01299     } else if ( strcmp(type, "file") == 0 )
01300     {
01301         xmlFree(type);
01302         
01303         if ( xmlHasProp(node, "Root") ) /* setting this optional, else default */
01304         {
01305             tmp = xmlGetProp(node, "Root");
01306             ref->spec->arc_path = allocate_copy_string(tmp);
01307             if ( ref->spec->arc_path == NULL )
01308             {
01309                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01310                     "Memory exhausted, could not allocate copy of archive path.");
01311                 xmlFree(tmp);
01312                 return;
01313             }
01314             xmlFree(tmp);
01315         } else
01316         {
01317             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01318                 "Input file invalid, archive path not indicated.");
01319             return;
01320         }
01321         
01322         if ( xmlHasProp(node, "Extension") ) /* also optional */
01323         {
01324             tmp = xmlGetProp(node, "Extension");
01325             ref->spec->arc_ext = allocate_copy_string(tmp);
01326             if ( ref->spec->arc_ext == NULL )
01327             {
01328                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01329                     "Memory exhausted, could not allocate copy of archive extension.");
01330                 xmlFree(tmp);
01331                 return;
01332             }
01333             xmlFree(tmp);
01334         } else
01335         {
01336             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01337                 "Input file invalid, archive extension not indicated.");
01338             return;
01339         }
01340         
01341         tmp = xmlNodeGetContent(node);
01342         if (tmp == NULL)
01343         {
01344             LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01345                 "Input file invalid, archive name not found.");
01346             xmlFree(tmp);
01347             return;
01348         }
01349         
01350         ref->spec->arc_name = allocate_copy_string(tmp);
01351         if ( ref->spec->arc_name == NULL )
01352         {
01353             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01354                 "Memory exhausted, could not allocate copy of archive name.");
01355             xmlFree(tmp);
01356             return;
01357         }
01358         xmlFree(tmp);
01359         
01360         ref->spec->input_pipe = allocate_copy_string("");
01361         if ( ref->spec->input_pipe == NULL )
01362         {
01363             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01364                 "Memory exhausted, could not allocate set input pipe name.");
01365         }
01366         
01367         ref->spec->output_pipe = allocate_copy_string("");
01368         if ( ref->spec->output_pipe == NULL )
01369         {
01370             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01371                 "Memory exhausted, could not allocate set output pipe name.");
01372         }
01373         
01374     } else
01375     {
01376         xmlFree(type);
01377         
01378         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01379             "Input file invalid, archive type invalid.");
01380         return;
01381     }
01382     return;
01383 }
01384 
01385 
01386 
01387 
01388 
01389 static void interpret_drc_1_0(dar_drc* ref, dar_sup_exception* exception)
01390 {
01391     DEBUG("Function: interpret_drc_1_0: Interpreting drc version 1.0.\n");
01392     
01393     xmlNodePtr root = xmlDocGetRootElement(ref->doc);
01394     xmlNodePtr ch = root->children;
01395     xmlNodePtr ch2 = NULL;
01396     xmlNodePtr ch3 = NULL;
01397     xmlNodePtr ch4 = NULL;
01398     xmlChar* xctmp = NULL;
01399     
01400     DEBUG("Root node name: %s\n", root->name);
01401     DEBUG("First child node name: %s\n", ch->name);
01402     
01403     DEBUG("Seeking Specification(1) element.\n");
01404     
01405     if ( ch->type != XML_ELEMENT_NODE )
01406     {
01407         DEBUG("Finding next element node.\n");
01408         ch = get_next_element_node(ch);
01409     }
01410     
01411     if ( ch == NULL || strcmp(ch->name, "Specification") != 0 )
01412     {
01413         LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01414             "Input file invalid, could not find archive specification.");
01415         return;
01416     }
01417     
01418     DEBUG("Found, translating specification element.\n");
01419     
01420     /* Filesystem */
01421     ch2 = ch->children;
01422     DEBUG("Seeking Filesystem(2) element.\n");
01423     
01424     if ( ch2->type != XML_ELEMENT_NODE )
01425     {
01426         ch2 = get_next_element_node(ch2);
01427     }
01428     
01429     if ( xmlHasProp(ch2, "Root") )
01430     {
01431         xctmp = xmlGetProp(ch2, "Root");
01432         ref->spec->root_path = allocate_copy_string(xctmp);
01433         if ( ref->spec->root_path == NULL )
01434         {
01435             LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01436                 "Memory exhausted, could not allocate copy of root path.");
01437             xmlFree(xctmp);
01438             return;
01439         }
01440         xmlFree(xctmp);
01441     }
01442     
01443     /* Selection */
01444     ch3 = ch2->children;
01445     DEBUG("Seeking Selection(3) element.\n");
01446     
01447     if ( ch3 != NULL && ch3->type != XML_ELEMENT_NODE )
01448     {
01449         ch3 = get_next_element_node(ch3);
01450     }
01451     
01452     if ( ch3 != NULL && strcmp(ch3->name, "Selection") == 0 )
01453     {
01454         /* Mask */
01455         ch4 = ch3->children;
01456         DEBUG("Seeking Mask(4) element.\n");
01457         
01458         if ( ch4->type != XML_ELEMENT_NODE )
01459         {
01460             ch4 = get_next_element_node(ch4);
01461         }
01462         
01463         dar_mask* tmpmask = 
01464             interpret_drc_1_0_recurse_mask(ch4, ref, exception);
01465         
01466         if ( exception->type != LIBDAR_NOEXCEPT )
01467         {
01468             DEBUG("Exception caught, throwing.\n");
01469             return;
01470         }
01471         
01472         ref->spec->selection = tmpmask;
01473         
01474         /* Subtree */
01475         DEBUG("Seeking Subtree(3) element.\n");
01476         ch3 = get_next_element_node(ch3->next);
01477     }
01478 
01479     if ( ch3 != NULL && strcmp(ch3->name, "Subtree") == 0 )
01480     {
01481         /* Mask */
01482         DEBUG("Seeking Mask(4) element.\n");
01483         ch4 = ch3->children;
01484         
01485         
01486         if ( ch4->type != XML_ELEMENT_NODE )
01487         {
01488             ch4 = get_next_element_node(ch4);
01489         }
01490         
01491         dar_mask* tmpmask =
01492             interpret_drc_1_0_recurse_mask(ch4, ref, exception);
01493         
01494         if ( exception->type != LIBDAR_NOEXCEPT )
01495         {
01496             DEBUG("Exception caught, throwing.\n");
01497             return;
01498         }
01499         
01500         ref->spec->subtree = tmpmask;
01501     }
01502     
01503     /* Archive */
01504     DEBUG("Seeking Archive(2) element.\n");
01505     ch2 = get_next_element_node(ch2->next);
01506     
01507     
01508     interpret_drc_1_0_archive(ch2, ref, exception);
01509     
01510     if ( exception->type != LIBDAR_NOEXCEPT )
01511     {
01512         DEBUG("Exception caught, throwing.\n");
01513         return;
01514     }
01515     
01516     DEBUG("Finding reference element, continuing if not found.\n");
01517     
01518     /* Reference */
01519     DEBUG("Seeking Reference(1) element.\n");
01520     ch = get_next_element_node(ch->next);
01521     
01522     
01523     if ( ch != NULL && strcmp(ch->name, "Reference") == 0 )
01524     {
01525         DEBUG("Reference element found, processing.\n");
01526         
01527         /* dar_drc object needs to be copied because spec, etc, objects
01528          * are modified directly by processing functions. Therefore, ref_spec,
01529          * etc, objects need to be placed in those slots during processing
01530          * of the reference element.
01531          */
01532          
01533         ref->has_reference = true;
01534         
01535         dar_drc temp_ref;
01536         
01537         temp_ref.spec = ref->ref_spec;
01538         temp_ref.storage = ref->ref_storage;
01539         temp_ref.flags = ref->ref_flags;
01540         
01541         /* Archive */
01542         ch2 = ch->children;
01543         DEBUG("Seeking Archive(2) element.\n");
01544         
01545         if ( ch2->type != XML_ELEMENT_NODE )
01546         {
01547             ch2 = get_next_element_node(ch2);
01548         }
01549         
01550         interpret_drc_1_0_archive(ch2, &temp_ref, exception);
01551         
01552         if ( exception->type != LIBDAR_NOEXCEPT )
01553         {
01554             DEBUG("Exception caught, throwing.\n");
01555             return;
01556         }
01557         
01558         /* Encryption */
01559         DEBUG("Seeking Encryption(2) element.\n");
01560         ch2 = get_next_element_node(ch2->next);
01561         
01562         if ( ch2 != NULL && strcmp(ch2->name, "Encryption") == 0 )
01563         {
01564             interpret_drc_1_0_encryption(ch2, &temp_ref, exception);
01565             
01566             if ( exception->type != LIBDAR_NOEXCEPT )
01567             {
01568                 DEBUG("Exception caught, throwing.\n");
01569                 return;
01570             }
01571             
01572             /* Script */
01573             DEBUG("Seeking Script(2) element.\n");
01574             ch2 = get_next_element_node(ch2->next);
01575         }
01576         
01577         if ( ch2 != NULL && strcmp(ch2->name, "Script") == 0 )
01578         {
01579         
01580             xctmp = xmlNodeGetContent(ch2);
01581             temp_ref.storage->slice_execute = allocate_copy_string(xctmp);
01582             
01583             if ( temp_ref.storage->slice_execute == NULL && xctmp != NULL )
01584             {
01585                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01586                     "Memory exhausted, could not allocate copy of inter-slice command.");
01587                 xmlFree(xctmp);
01588                 return;
01589             }
01590             xmlFree(xctmp);
01591         }
01592         
01593         /* temp_ref variables were just pointers to ref objects,
01594          * we don't need to copy pointers over before temp_ref deallocation,
01595          * which happens here.
01596          */
01597          
01598          /* moving to next element */
01599          ch = get_next_element_node(ch->next);
01600     }
01601     
01602     DEBUG("Finding storage element, continuing if not found.\n");
01603     
01604     /* Storage */
01605     
01606     if ( ch != NULL && strcmp(ch->name, "Storage") == 0 )
01607     {
01608         DEBUG("Storage element found, processing.\n");
01609         
01610         /* Compression */
01611         ch2 = ch->children;
01612         DEBUG("Seeking Compression(2) element.\n");
01613         
01614         if ( ch2->type != XML_ELEMENT_NODE )
01615         {
01616             ch2 = get_next_element_node(ch2);
01617         }
01618         
01619         if ( ch2 != NULL && strcmp(ch2->name, "Compression") == 0 )
01620         {
01621             interpret_drc_1_0_compression(ch2, ref, exception);
01622             
01623             if ( exception->type != LIBDAR_NOEXCEPT )
01624             {
01625                 DEBUG("Exception caught, throwing.\n");
01626                 return;
01627             }
01628             
01629             /* Encryption */
01630             DEBUG("Seeking Encryption(2) element.\n");
01631             ch2 = get_next_element_node(ch2->next);
01632         }
01633         
01634         if ( ch2 != NULL && strcmp(ch2->name, "Encryption") == 0 )
01635         {
01636             interpret_drc_1_0_encryption(ch2, ref, exception);
01637             
01638             if ( exception->type != LIBDAR_NOEXCEPT )
01639             {
01640                 DEBUG("Exception caught, throwing.\n");
01641                 return;
01642             }
01643             
01644             /* SliceSize */
01645             DEBUG("Seeking SliceSize(2) element.\n");
01646             ch2 = get_next_element_node(ch2->next);
01647         }
01648         
01649         if ( ch2 != NULL && strcmp(ch2->name, "SliceSize") == 0 )
01650         {
01651             interpret_drc_1_0_slice_size(ch2, ref, exception);
01652             
01653             if ( exception->type != LIBDAR_NOEXCEPT )
01654             {
01655                 DEBUG("Exception caught, throwing.\n");
01656                 return;
01657             }
01658             
01659             /* Script */
01660             DEBUG("Seeking Script(2) element.\n");
01661             ch2 = get_next_element_node(ch2->next);
01662         }
01663         
01664         if ( ch2 != NULL && strcmp(ch2->name, "Script") == 0 )
01665         {
01666             xctmp = xmlNodeGetContent(ch2);
01667             ref->storage->slice_execute = allocate_copy_string(xctmp);
01668             
01669             if ( ref->storage->slice_execute == NULL && xctmp != NULL )
01670             {
01671                 LIBDARC_EXCEPTION(exception, LIBDAR_EMEMORY,
01672                     "Memory exhausted, could not allocate copy of inter-slice command.");
01673                 xmlFree(xctmp);
01674                 return;
01675             }
01676             xmlFree(xctmp);
01677             
01678             /* Hourshift */
01679             DEBUG("Seeking Hourshift(2) element.\n");
01680             ch2 = get_next_element_node(ch2->next);
01681         }
01682         
01683         if ( ch2 != NULL && strcmp(ch2->name, "Hourshift") == 0 )
01684         {
01685             xctmp = xmlNodeGetContent(ch2);
01686             ref->storage->hourshift = dar_infds(xctmp);
01687             
01688             if ( ref->storage->hourshift == NULL )
01689             {
01690                 LIBDARC_EXCEPTION(exception, LIBDAR_X_EINPUTSPEC,
01691                     "Input file invalid, could not parse hourshift value.");
01692                 xmlFree(xctmp);
01693                 return;
01694             }
01695             xmlFree(xctmp);
01696         }
01697         
01698          /* moving to next element */
01699          ch = get_next_element_node(ch->next);
01700     }
01701     
01702     DEBUG("Finding flags element, continuing if not found.\n");
01703     
01704     if ( ch != NULL && strcmp(ch->name, "Flags") == 0 )
01705     {
01706         DEBUG("Flags element found, processing.\n");
01707         
01708         /* first flag element */
01709         ch2 = ch->children;
01710     
01711         if ( ch2->type != XML_ELEMENT_NODE )
01712         {
01713             ch2 = get_next_element_node(ch2);
01714         }
01715         
01716         interpret_drc_1_0_recurse_flags(ch2, ref, exception);
01717         
01718         if ( exception->type != LIBDAR_NOEXCEPT )
01719         {
01720             DEBUG("Exception caught, throwing.\n");
01721             return;
01722         }
01723         
01724          /* moving to next element */
01725          ch = get_next_element_node(ch->next);
01726     }
01727     
01728     return;
01729 }
01730 
01731 
01732 
01733 
01734 
01735 /* internal functions definitions */
01736 
01737 static char* bool_to_string( bool val )
01738 {
01739     DEBUG("Function: bool_to_string: Converting boolean to string.\n");
01740     char* ret;
01741     if (val)
01742     {
01743         ret = (char*)malloc(5);
01744         if (ret == NULL) { return NULL; }
01745         strcpy(ret, "true");
01746     } else {
01747         ret = (char*)malloc(6);
01748         if (ret == NULL) { return NULL; }
01749         strcpy(ret, "false");
01750     }
01751     return ret;
01752 }
01753 
01754 static bool string_to_bool( char* str, bool* val )
01755 {
01756     DEBUG("Function: string_to_bool: Converting string to boolean.\n");
01757     
01758     if (val == NULL)
01759     {
01760         DEBUG("Source error: Input parameter is null.\n");
01761         return false;
01762     }
01763     
01764     if (str == NULL)
01765     {
01766         DEBUG("Argument error: No input string.\n");
01767         return false;
01768     }
01769     
01770     if ( strcmp( str, "true" ) == 0 )
01771     {
01772         *val = true;
01773         return true;
01774     } else if ( strcmp( str, "false" ) == 0 )
01775     {
01776         *val = false;
01777         return true;
01778     } else {
01779         DEBUG("Argument error: Improper input data format.\n");
01780         return false;
01781     }
01782 }
01783 
01784 static char* allocate_copy_string( const char* source )
01785 {
01786     DEBUG("Function: allocate_copy_string: Copying string into newly allocated space.\n");
01787     if (source == NULL) { return NULL; }
01788     char* ret = (char*)malloc(strlen(source) + 1);
01789     if (ret == NULL) { return NULL; }
01790     strcpy( ret, source );
01791     return ret;
01792 }
01793 
01794 /* DRC_DTD_FILE_PREFIX and DRC_DTD_FILE_LOCATION defined in Makefile.am */
01795 
01796 static char* get_dtd_location(const char* dtdfilepath, const char* version)
01797 {
01798     DEBUG("Function: get_dtd_location: Determining dtd file location.\n");
01799     const char* prefix = DRC_DTD_FILE_PREFIX;
01800     const char* path = DRC_DTD_FILE_LOCATION;
01801     
01802     char* ret;
01803     
01804     if ( dtdfilepath != NULL )
01805     {
01806         DEBUG("dtdfilepath = %s\n", dtdfilepath);
01807         ret = (char*)malloc(strlen(dtdfilepath));
01808         if (ret == NULL) { return NULL; }
01809         strcpy( ret, dtdfilepath );
01810         return ret;
01811     }
01812     
01813 #if WIN32_PLATFORM
01814     /* "..\\share\\libdarc\\" + PREFIX + "-" + VERSION + ".dtd" + "\0" -> 23 */
01815     ret = (char*)malloc( strlen(prefix) + strlen(version) + 23 );
01816     if (ret == NULL) { return NULL; }
01817     *ret = 0;
01818     strcat(ret, "..\\share\\libdarc\\");
01819     strcat(ret, prefix);
01820     strcat(ret, "-");
01821     strcat(ret, version);
01822     strcat(ret, ".dtd");
01823 #else
01824     /* PATH + DIR_SEPERATOR_STR + PREFIX + "-" + VERSION + ".dtd" + "\0" -> 7 */
01825     ret = (char*)malloc( strlen(path) + strlen(prefix) + strlen(version) + 7 );
01826     if (ret == NULL) { return NULL; }
01827     *ret = 0;
01828     strcat(ret, path);
01829     strcat(ret, DIR_SEPARATOR_STR);
01830     strcat(ret, prefix);
01831     strcat(ret, "-");
01832     strcat(ret, version);
01833     strcat(ret, ".dtd");
01834 #endif
01835     
01836     return ret;
01837 }
01838 
01839 /* returns false if allocation fails */
01840 static bool dar_drc_prep(dar_drc* ref)
01841 {
01842     DEBUG("Function: dar_drc_prep: Zeroing out drc context.\n");
01843     /* set pointers to NULL to prep for dar_drc_destroy on panic */
01844     ref->xml_buffer = NULL;
01845     ref->xml_filename = NULL;
01846     ref->dtd_filename = NULL;
01847     ref->doc = NULL;
01848     
01849     ref->xml_buffer_size = 0;
01850     
01851     ref->has_reference = false;
01852     
01853     ref->spec = (dar_sup_spec*)malloc(sizeof(dar_sup_spec));
01854     ref->storage = (dar_sup_storage*)malloc(sizeof(dar_sup_storage));
01855     ref->flags = (dar_sup_flags*)malloc(sizeof(dar_sup_flags));
01856     
01857     ref->ref_spec = (dar_sup_spec*)malloc(sizeof(dar_sup_spec));
01858     ref->ref_storage = (dar_sup_storage*)malloc(sizeof(dar_sup_storage));
01859     ref->ref_flags = (dar_sup_flags*)malloc(sizeof(dar_sup_flags));
01860     
01861     if (    ref->spec == NULL ||
01862             ref->storage == NULL ||
01863             ref->flags == NULL ||
01864             ref->ref_spec == NULL ||
01865             ref->ref_storage == NULL ||
01866             ref->ref_flags == NULL )
01867     {
01868         DEBUG("Memory exhausted, allocation failed in dar_drc_prep.\n");
01869         if (ref->spec != NULL)
01870             free(ref->spec);
01871         if (ref->storage != NULL)
01872             free(ref->storage);
01873         if (ref->flags != NULL)
01874             free(ref->flags);
01875         if (ref->ref_spec != NULL)
01876             free(ref->ref_spec);
01877         if (ref->ref_storage != NULL)
01878             free(ref->ref_storage);
01879         if (ref->ref_flags != NULL);
01880             free(ref->ref_flags);
01881             
01882         ref->spec = NULL;
01883         ref->storage = NULL;
01884         ref->flags = NULL;
01885         ref->ref_spec = NULL;
01886         ref->ref_storage = NULL;
01887         ref->ref_flags = NULL;
01888         
01889         return false;
01890     }
01891     
01892     
01893     
01894     /* set defaults for support structures */
01895     dar_sup_spec_defaults(ref->spec);
01896     dar_sup_storage_defaults(ref->storage);
01897     dar_sup_flags_defaults(ref->flags);
01898     
01899     dar_sup_spec_defaults(ref->ref_spec);
01900     dar_sup_storage_defaults(ref->ref_storage);
01901     dar_sup_flags_defaults(ref->ref_flags);
01902     return true;
01903 }
01904 
01905 static xmlNodePtr get_next_element_node(xmlNodePtr node)
01906 {
01907     DEBUG("Function: get_next_element_node: Scanning to next element node.\n");
01908     DEBUG("Node passed in: %s\n", node->name);
01909     xmlNodePtr n;
01910     
01911     for (n = node; n; n = n->next)
01912     {
01913         DEBUG("Next node: %s\n", n->name);
01914         if (n->type == XML_ELEMENT_NODE)
01915         {
01916             DEBUG("Found element node.\n");
01917             return n;
01918         }
01919     }
01920     return NULL;
01921 }
01922         
01923 
01924