1 /*
2  * Copyright (c) 2007 Vreixo Formoso
3  * Copyright (c) 2009 - 2016 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 <stdlib.h>
16 #include <sys/types.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdarg.h>
20 
21 #ifdef Xorriso_standalonE
22 
23 #ifdef Xorriso_with_libjtE
24 #include "../libjte/libjte.h"
25 #endif
26 
27 #else
28 
29 #ifdef Libisofs_with_libjtE
30 #include <libjte/libjte.h>
31 #endif
32 
33 #endif /* ! Xorriso_standalonE */
34 
35 #include "libiso_msgs.h"
36 #include "libisofs.h"
37 #include "messages.h"
38 
39 #include "util.h"
40 #include "node.h"
41 #include "stream.h"
42 
43 
44 /*
45  * error codes are 32 bit numbers, that follow the following conventions:
46  *
47  * bit  31 (MSB) -> 1 (to make the value always negative)
48  * bits 30-24 -> Encoded severity (Use ISO_ERR_SEV to translate an error code
49  *               to a LIBISO_MSGS_SEV_* constant)
50  *        = 0x10 -> DEBUG
51  *        = 0x20 -> UPDATE
52  *        = 0x30 -> NOTE
53  *        = 0x40 -> HINT
54  *        = 0x50 -> WARNING
55  *        = 0x60 -> SORRY
56  *        = 0x64 -> MISHAP
57  *        = 0x68 -> FAILURE
58  *        = 0x70 -> FATAL
59  *        = 0x71 -> ABORT
60  * bits 23-20 -> Encoded priority (Use ISO_ERR_PRIO to translate an error code
61  *               to a LIBISO_MSGS_PRIO_* constant)
62  *        = 0x0 -> ZERO
63  *        = 0x1 -> LOW
64  *        = 0x2 -> MEDIUM
65  *        = 0x3 -> HIGH
66  * bits 19-16 -> Reserved for future usage (maybe message ranges)
67  * bits 15-0  -> Error code
68  */
69 #define ISO_ERR_SEV(e)      (e & 0x7F000000)
70 #define ISO_ERR_PRIO(e)     ((e & 0x00700000) << 8)
71 #define ISO_ERR_CODE(e)     ((e & 0x0000FFFF) | 0x00030000)
72 
73 int iso_message_id = LIBISO_MSGS_ORIGIN_IMAGE_BASE;
74 
75 /**
76  * Threshold for aborting.
77  */
78 int abort_threshold = LIBISO_MSGS_SEV_FAILURE;
79 
80 #define MAX_MSG_LEN     4096
81 
82 struct libiso_msgs *libiso_msgr = NULL;
83 
84 
85 /* ------------- List of xinfo clone functions ----------- */
86 
87 struct iso_xinfo_cloner_assoc {
88     iso_node_xinfo_func proc;
89     iso_node_xinfo_cloner cloner;
90     struct iso_xinfo_cloner_assoc *next;
91 };
92 
93 struct iso_xinfo_cloner_assoc *iso_xinfo_cloner_list = NULL;
94 
95 /* API */
iso_node_xinfo_make_clonable(iso_node_xinfo_func proc,iso_node_xinfo_cloner cloner,int flag)96 int iso_node_xinfo_make_clonable(iso_node_xinfo_func proc,
97                                  iso_node_xinfo_cloner cloner, int flag)
98 {
99     struct iso_xinfo_cloner_assoc *assoc;
100 
101     /* Look for existing assoc of proc */
102     for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next)
103         if (assoc->proc == proc)
104     break;
105 
106     if (assoc == NULL) {
107         assoc = calloc(1, sizeof(struct iso_xinfo_cloner_assoc));
108         if (assoc == NULL)
109             return ISO_OUT_OF_MEM;
110         assoc->proc = proc;
111         assoc->next = iso_xinfo_cloner_list;
112         iso_xinfo_cloner_list = assoc;
113     }
114     assoc->cloner = cloner;
115     return ISO_SUCCESS;
116 }
117 
118 /* API */
iso_node_xinfo_get_cloner(iso_node_xinfo_func proc,iso_node_xinfo_cloner * cloner,int flag)119 int iso_node_xinfo_get_cloner(iso_node_xinfo_func proc,
120                               iso_node_xinfo_cloner *cloner, int flag)
121 {
122     struct iso_xinfo_cloner_assoc *assoc;
123 
124     *cloner = NULL;
125     for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = assoc->next) {
126         if (assoc->proc != proc)
127     continue;
128         *cloner = assoc->cloner;
129         return 1;
130     }
131     return 0;
132 }
133 
134 static
iso_node_xinfo_dispose_cloners(int flag)135 int iso_node_xinfo_dispose_cloners(int flag)
136 {
137     struct iso_xinfo_cloner_assoc *assoc, *next;
138 
139     for (assoc = iso_xinfo_cloner_list; assoc != NULL; assoc = next) {
140         next = assoc->next;
141         free((char *) assoc);
142     }
143     iso_xinfo_cloner_list= NULL;
144     return(1);
145 }
146 
147 /* ------------- End of xinfo clone functions list ----------- */
148 
149 
150 /*
151   @param flag  bit0= do not set up locale by LC_* environment variables
152 */
iso_init_with_flag(int flag)153 int iso_init_with_flag(int flag)
154 {
155     int ret;
156 
157 #ifdef Libisofs_with_libjtE
158 
159  /* Ugly compile time check for header version compatibility.
160     If everything matches, then it produces no C code. In case of mismatch,
161     intentionally faulty C code will be inserted.
162  */
163  /* The indentation is an advise of man gcc to help old compilers ignoring */
164  #if iso_libjte_req_major > LIBJTE_VERSION_MAJOR
165  #define Libisofs_libjte_dot_h_too_olD 1
166  #endif
167  #if iso_libjte_req_major == LIBJTE_VERSION_MAJOR && iso_libjte_req_minor > LIBJTE_VERSION_MINOR
168  #define Libisofs_libjte_dot_h_too_olD 1
169  #endif
170  #if iso_libjte_req_minor == LIBJTE_VERSION_MINOR && iso_libjte_req_micro > LIBJTE_VERSION_MICRO
171  #define Libisofs_libjte_dot_h_too_olD 1
172  #endif
173 
174 #ifdef Libisofs_libjte_dot_h_too_olD
175 LIBJTE_MISCONFIGURATION = 0;
176 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libjte_dot_h_TOO_OLD__SEE_libisofs_dot_h_AND_messages_c = 0;
177 LIBJTE_MISCONFIGURATION_ = 0;
178 #endif
179 
180     if (! libjte__is_compatible(LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
181                                 LIBJTE_VERSION_MICRO, 0)) {
182         fprintf(stderr,
183               "\nlibisofs: libjte TOO OLD ! Need at least libjte-%d.%d.%d\n\n",
184               LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
185               LIBJTE_VERSION_MICRO);
186         return ISO_FATAL_ERROR;
187     }
188 
189 #endif /* Libisofs_with_libjtE */
190 
191     if (! (flag & 1)) {
192         iso_init_locale(0);
193     }
194     if (libiso_msgr == NULL) {
195         if (libiso_msgs_new(&libiso_msgr, 0) <= 0)
196             return ISO_FATAL_ERROR;
197     }
198     libiso_msgs_set_severities(libiso_msgr, LIBISO_MSGS_SEV_NEVER,
199                    LIBISO_MSGS_SEV_FATAL, "libisofs: ", 0);
200 
201     ret = iso_node_xinfo_make_clonable(aaip_xinfo_func, aaip_xinfo_cloner, 0);
202     if (ret < 0)
203         return ret;
204     ret = iso_node_xinfo_make_clonable(checksum_cx_xinfo_func,
205                                        checksum_cx_xinfo_cloner, 0);
206     if (ret < 0)
207         return ret;
208     ret = iso_node_xinfo_make_clonable(checksum_md5_xinfo_func,
209                                        checksum_md5_xinfo_cloner, 0);
210     if (ret < 0)
211         return ret;
212     ret = iso_node_xinfo_make_clonable(zisofs_zf_xinfo_func,
213                                        zisofs_zf_xinfo_cloner, 0);
214     if (ret < 0)
215         return ret;
216     ret = iso_node_xinfo_make_clonable(iso_px_ino_xinfo_func,
217                                        iso_px_ino_xinfo_cloner, 0);
218     if (ret < 0)
219         return ret;
220     ret = iso_node_xinfo_make_clonable(iso_hfsplus_xinfo_func,
221                                        iso_hfsplus_xinfo_cloner, 0);
222     if (ret < 0)
223         return ret;
224     return 1;
225 }
226 
iso_init()227 int iso_init()
228 {
229     return iso_init_with_flag(0);
230 }
231 
iso_finish()232 void iso_finish()
233 {
234     libiso_msgs_destroy(&libiso_msgr, 0);
235     iso_node_xinfo_dispose_cloners(0);
236     iso_stream_destroy_cmpranks(0);
237 }
238 
iso_set_abort_severity(char * severity)239 int iso_set_abort_severity(char *severity)
240 {
241     int ret, sevno;
242 
243     ret = libiso_msgs__text_to_sev(severity, &sevno, 0);
244     if (ret <= 0)
245         return ISO_WRONG_ARG_VALUE;
246     if (sevno > LIBISO_MSGS_SEV_FAILURE || sevno < LIBISO_MSGS_SEV_NOTE)
247         return ISO_WRONG_ARG_VALUE;
248     ret = abort_threshold;
249     abort_threshold = sevno;
250     return ret;
251 }
252 
iso_msg_debug(int imgid,const char * fmt,...)253 void iso_msg_debug(int imgid, const char *fmt, ...)
254 {
255     char *msg = NULL;
256     va_list ap;
257 
258     LIBISO_ALLOC_MEM_VOID(msg, char, MAX_MSG_LEN);
259     va_start(ap, fmt);
260     vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
261     va_end(ap);
262 
263     libiso_msgs_submit(libiso_msgr, imgid, 0x00000002, LIBISO_MSGS_SEV_DEBUG,
264                        LIBISO_MSGS_PRIO_ZERO, msg, 0, 0);
265 ex:;
266     LIBISO_FREE_MEM(msg);
267 }
268 
iso_error_to_msg(int errcode)269 const char *iso_error_to_msg(int errcode)
270 {
271     switch(errcode) {
272     case ISO_CANCELED:
273         return "Operation canceled";
274     case ISO_FATAL_ERROR:
275         return "Unknown or unexpected fatal error";
276     case ISO_ERROR:
277         return "Unknown or unexpected error";
278     case ISO_ASSERT_FAILURE:
279         return "Internal programming error. Please report this bug";
280     case ISO_NULL_POINTER:
281         return "NULL pointer as value for an arg. that does not allow NULL";
282     case ISO_OUT_OF_MEM:
283         return "Memory allocation error";
284     case ISO_INTERRUPTED:
285         return "Interrupted by a signal";
286     case ISO_WRONG_ARG_VALUE:
287         return "Invalid parameter value";
288     case ISO_THREAD_ERROR:
289         return "Cannot create a needed thread";
290     case ISO_WRITE_ERROR:
291         return "Write error";
292     case ISO_BUF_READ_ERROR:
293         return "Buffer read error";
294     case ISO_NODE_ALREADY_ADDED:
295         return "Trying to add to a dir a node already added to a dir";
296     case ISO_NODE_NAME_NOT_UNIQUE:
297         return "Node with same name already exists";
298     case ISO_NODE_NOT_ADDED_TO_DIR:
299         return "Trying to remove a node that was not added to dir";
300     case ISO_NODE_DOESNT_EXIST:
301         return "A requested node does not exist";
302     case ISO_IMAGE_ALREADY_BOOTABLE:
303         return "Try to set the boot image of an already bootable image";
304     case ISO_BOOT_IMAGE_NOT_VALID:
305         return "Trying to use an invalid file as boot image";
306     case ISO_BOOT_IMAGE_OVERFLOW:
307         return "Too many boot images added";
308     case ISO_FILE_ERROR:
309         return "Error on file operation";
310     case ISO_FILE_ALREADY_OPENED:
311         return "Trying to open an already opened file";
312     case ISO_FILE_ACCESS_DENIED:
313         return "Access to file is not allowed";
314     case ISO_FILE_BAD_PATH:
315         return "Incorrect path to file";
316     case ISO_FILE_DOESNT_EXIST:
317         return "The file does not exist in the filesystem";
318     case ISO_FILE_NOT_OPENED:
319         return "Trying to read or close a file not opened";
320     case ISO_FILE_IS_DIR:
321         return "Directory used where no dir is expected";
322     case ISO_FILE_READ_ERROR:
323         return "Read error";
324     case ISO_FILE_IS_NOT_DIR:
325         return "Not dir used where a dir is expected";
326     case ISO_FILE_IS_NOT_SYMLINK:
327         return "Not symlink used where a symlink is expected";
328     case ISO_FILE_SEEK_ERROR:
329         return "Cannot seek to specified location";
330     case ISO_FILE_IGNORED:
331         return "File not supported in ECMA-119 tree and thus ignored";
332     case ISO_FILE_TOO_BIG:
333         return "A file is bigger than supported by used standard";
334     case ISO_FILE_CANT_WRITE:
335         return "File read error during image creation";
336     case ISO_FILENAME_WRONG_CHARSET:
337     case ISO_FILENAME_WRONG_CHARSET_OLD:
338         return "Cannot convert filename to requested charset";
339     case ISO_FILE_CANT_ADD:
340         return "File cannot be added to the tree";
341     case ISO_FILE_IMGPATH_WRONG:
342         return "File path break specification constraints and will be ignored";
343     case ISO_CHARSET_CONV_ERROR:
344         return "Charset conversion error";
345     case ISO_MANGLE_TOO_MUCH_FILES:
346         return "Too much files to mangle, cannot guarantee unique file names";
347     case ISO_WRONG_PVD:
348         return "Wrong or damaged Primary Volume Descriptor";
349     case ISO_WRONG_RR:
350         return "Wrong or damaged Rock Ridge entry";
351     case ISO_UNSUPPORTED_RR:
352         return "Unsupported Rock Ridge feature";
353     case ISO_WRONG_ECMA119:
354         return "Wrong or damaged ECMA-119";
355     case ISO_UNSUPPORTED_ECMA119:
356         return "Unsupported ECMA-119 feature";
357     case ISO_WRONG_EL_TORITO:
358         return "Wrong or damaged El-Torito catalog";
359     case ISO_UNSUPPORTED_EL_TORITO:
360         return "Unsupported El-Torito feature";
361     case ISO_ISOLINUX_CANT_PATCH:
362         return "Cannot patch isolinux boot image";
363     case ISO_UNSUPPORTED_SUSP:
364         return "Unsupported SUSP feature";
365     case ISO_WRONG_RR_WARN:
366         return "Error on a Rock Ridge entry that can be ignored";
367     case ISO_SUSP_UNHANDLED:
368         return "Unhandled SUSP entry";
369     case ISO_SUSP_MULTIPLE_ER:
370         return "Multiple ER SUSP entries found";
371     case ISO_UNSUPPORTED_VD:
372         return "Unsupported volume descriptor found";
373     case ISO_EL_TORITO_WARN:
374         return "El-Torito related warning";
375     case ISO_IMAGE_WRITE_CANCELED:
376         return "Image write cancelled";
377     case ISO_EL_TORITO_HIDDEN:
378         return "El-Torito image is hidden";
379     case ISO_DATA_SOURCE_SORRY:
380     case ISO_DATA_SOURCE_MISHAP:
381     case ISO_DATA_SOURCE_FAILURE:
382     case ISO_DATA_SOURCE_FATAL:
383         return "Read error occurred with IsoDataSource";
384     case ISO_AAIP_IGNORED:
385         return "AAIP info with ACL or xattr in ISO image will be ignored";
386     case ISO_AAIP_BAD_ACL:
387         return "Error with decoding ACL from AAIP info";
388     case ISO_AAIP_BAD_ACL_TEXT:
389         return "Error with encoding ACL for AAIP";
390     case ISO_AAIP_NOT_ENABLED:
391         return "AAIP processing for ACL or xattr not enabled at compile time";
392     case ISO_AAIP_BAD_AASTRING:
393         return "Error with decoding AAIP info for ACL or xattr";
394     case ISO_AAIP_NO_GET_LOCAL:
395         return "Error with reading ACL or xattr from local file";
396     case ISO_AAIP_NO_SET_LOCAL:
397         return "Error with attaching ACL or xattr to local file";
398     case ISO_AAIP_NON_USER_NAME:
399         return "Unallowed attempt to set an xattr with non-userspace name";
400     case ISO_EXTF_TOO_OFTEN:
401         return "Too many references on a single external filter command";
402     case ISO_ZLIB_NOT_ENABLED:
403         return "Use of zlib was not enabled at compile time";
404     case ISO_ZISOFS_TOO_LARGE:
405         return "File too large. Cannot apply zisofs filter.";
406     case ISO_FILTER_WRONG_INPUT:
407         return "Filter input differs from previous run";
408     case ISO_ZLIB_COMPR_ERR:
409         return "zlib compression/decompression error";
410     case ISO_ZISOFS_WRONG_INPUT:
411         return "Input stream is not in a supported zisofs format";
412     case ISO_ZISOFS_PARAM_LOCK:
413         return "Cannot set global zisofs parameters while filters exist";
414     case ISO_ZLIB_EARLY_EOF:
415         return "Premature EOF of zlib input stream";
416     case ISO_MD5_AREA_CORRUPTED:
417         return "Checksum area or checksum tag appear corrupted";
418     case ISO_MD5_TAG_MISMATCH:
419         return "Checksum mismatch between checksum tag and data blocks";
420     case ISO_SB_TREE_CORRUPTED:
421         return "Checksum mismatch in System Area, Volume Descriptors, or directory tree";
422     case ISO_MD5_TAG_UNEXPECTED:
423         return "Unexpected checksum tag type encountered";
424     case ISO_MD5_TAG_MISPLACED:
425         return "Misplaced checksum tag type encountered";
426     case ISO_MD5_TAG_OTHER_RANGE:
427         return "Checksum tag with unexpected address range encountered";
428     case ISO_MD5_STREAM_CHANGE:
429         return "Detected file content changes while it was written into the image";
430     case ISO_SCDBACKUP_TAG_NOT_0:
431         return "Session does not start at LBA 0. scdbackup checksum tag not written.";
432     case ISO_BOOT_NO_CATALOG:
433         return "No boot catalog created yet";
434     case ISO_OVWRT_MS_TOO_SMALL:
435         return "Multi-session offset too small for overwrite buffer";
436     case ISO_PART_OFFST_TOO_SMALL:
437         return "Partition offset too small for first tree root.";
438     case ISO_OVWRT_FIFO_TOO_SMALL:
439         return "The ring buffer is too small for overwrite buffer";
440     case ISO_LIBJTE_NOT_ENABLED:
441         return "Use of libjte was not enabled at compile time";
442     case ISO_LIBJTE_START_FAILED:
443         return "Failed to start up Jigdo Template Extraction";
444     case ISO_LIBJTE_END_FAILED:
445         return "Failed to finish Jigdo Template Extraction";
446     case ISO_LIBJTE_FILE_FAILED:
447         return "Failed to process file for Jigdo Template Extraction";
448     case ISO_BOOT_TOO_MANY_MIPS:
449         return "Too many MIPS Big Endian boot files given (max. 15)";
450     case ISO_BOOT_FILE_MISSING:
451         return "Boot file missing in image";
452     case ISO_BAD_PARTITION_NO:
453         return "Partition number out of range";
454     case ISO_BAD_PARTITION_FILE:
455         return "Cannot open data file for appended partition";
456     case ISO_NON_MBR_SYS_AREA:
457         return "May not combine MBR partition with non-MBR system area";
458     case ISO_DISPLACE_ROLLOVER:
459         return "Displacement offset leads outside 32 bit range";
460     case ISO_NAME_NEEDS_TRANSL:
461         return "File name cannot be written into ECMA-119 untranslated";
462     case ISO_STREAM_NO_CLONE:
463         return "Data file input stream object offers no cloning method";
464     case ISO_XINFO_NO_CLONE:
465         return "Extended information class offers no cloning method";
466     case ISO_MD5_TAG_COPIED:
467         return "Found copied superblock checksum tag";
468     case ISO_RR_NAME_TOO_LONG:
469         return "Rock Ridge leaf name too long";
470     case ISO_RR_NAME_RESERVED:
471         return "Reserved Rock Ridge leaf name";
472     case ISO_RR_PATH_TOO_LONG:
473         return "Rock Ridge path too long";
474     case ISO_AAIP_BAD_ATTR_NAME:
475         return "Attribute name cannot be represented";
476     case ISO_AAIP_ACL_MULT_OBJ:
477         return "ACL text contains multiple entries of user::, group::, other::";
478     case ISO_SECT_SCATTERED:
479         return "File sections do not form consecutive array of blocks";
480     case ISO_BOOT_TOO_MANY_APM:
481         return "Too many Apple Partition Map entries requested";
482     case ISO_BOOT_APM_OVERLAP:
483         return "Overlapping Apple Partition Map entries requested";
484     case ISO_BOOT_TOO_MANY_GPT:
485         return "Too many GPT entries requested";
486     case ISO_BOOT_GPT_OVERLAP:
487         return "Overlapping GPT entries requested";
488     case ISO_BOOT_TOO_MANY_MBR:
489         return "Too many MBR partition entries requested";
490     case ISO_BOOT_MBR_OVERLAP:
491         return "Overlapping MBR partition entries requested";
492     case ISO_BOOT_MBR_COLLISION:
493         return "Attempt to use an MBR partition entry twice";
494     case ISO_BOOT_NO_EFI_ELTO:
495         return "No suitable El Torito EFI boot image for exposure as GPT partition";
496     case ISO_BOOT_HFSP_BAD_BSIZE:
497         return "Not a supported HFS+ or APM block size";
498     case ISO_BOOT_APM_GPT_BSIZE:
499         return "APM block size prevents coexistence with GPT";
500     case ISO_HFSP_NO_MANGLE:
501         return "Name collision in HFS+, mangling not possible";
502     case ISO_DEAD_SYMLINK:
503         return "Symbolic link cannot be resolved";
504     case ISO_DEEP_SYMLINK:
505         return "Too many chained symbolic links";
506     case ISO_BAD_ISO_FILETYPE:
507         return "Unrecognized file type in ISO image";
508     case ISO_NAME_NOT_UCS2:
509         return "Filename not suitable for character set UCS-2";
510     case ISO_IMPORT_COLLISION:
511         return "File name collision during ISO image import";
512     case ISO_HPPA_PALO_INCOMPL:
513         return "Incomplete HP-PA PALO boot parameters";
514     case ISO_HPPA_PALO_OFLOW:
515         return "HP-PA PALO boot address exceeds 2 GB";
516     case ISO_HPPA_PALO_NOTREG:
517         return "HP-PA PALO file is not a data file";
518     case ISO_HPPA_PALO_CMDLEN:
519         return "HP-PA PALO command line too long";
520     case ISO_SYSAREA_PROBLEMS:
521         return "Problems encountered during inspection of System Area";
522     case ISO_INQ_SYSAREA_PROP:
523         return "Unrecognized inquiry for system area property";
524     case ISO_ALPHA_BOOT_NOTREG:
525         return "DEC Alpha Boot Loader file is not a data file";
526     case ISO_NO_KEPT_DATA_SRC:
527         return "No data source of imported ISO image available";
528     case ISO_MALFORMED_READ_INTVL:
529         return "Malformed description string for interval reader";
530     case ISO_INTVL_READ_PROBLEM:
531         return "Unreadable file, premature EOF, or failure to seek for interval reader";
532     case ISO_NOT_REPRODUCIBLE:
533         return "Cannot arrange content of data files in surely reproducible way";
534     case ISO_PATCH_FILTERED_BOOT:
535         return "May not write boot info into filtered stream of boot image";
536     case ISO_PATCH_OVERSIZED_BOOT:
537         return "Boot image to large to buffer for writing boot info";
538     case ISO_RR_NAME_TRUNCATED:
539         return "File name had to be truncated and MD5 marked";
540     case ISO_TRUNCATE_ISOFSNT:
541         return "File name truncation length changed by loaded image info";
542     case ISO_GENERAL_NOTE:
543         return "A general note message was issued";
544     case ISO_BAD_FSRC_FILETYPE:
545         return "Unrecognized file type of IsoFileSrc object";
546     case ISO_GPT_NO_VOL_UUID:
547         return "Cannot derive GPT GUID from undefined pseudo-UUID volume timestamp";
548     case ISO_BAD_GPT_GUID_MODE:
549         return "Unrecognized GPT disk GUID setup mode";
550     case ISO_NO_ROOT_DIR:
551         return "Unable to obtain root directory";
552     case ISO_SUSP_WRONG_CE_SIZE:
553         return "Zero sized, oversized, or mislocated SUSP CE area found";
554     case ISO_MULTI_OVER_IMPORTED:
555         return "Multi-session would overwrite imported_iso interval";
556     case ISO_ELTO_EFI_HIDDEN:
557         return "El-Torito EFI image is hidden";
558     case ISO_HFSPLUS_TOO_MANY_FILES:
559         return "Too many files in HFS+ directory tree";
560     case ISO_ZISOFS_TOO_MANY_PTR:
561         return "Too many zisofs block pointers needed overall";
562     case ISO_ZISOFS_BPT_UNDERRUN:
563         return "Prevented zisofs block pointer counter underrun";
564     case ISO_ZISOFS_UNKNOWN_SIZE:
565         return "Cannot obtain size of zisofs compressed stream";
566     default:
567         return "Unknown error";
568     }
569 }
570 
iso_msg_is_abort(int errcode)571 int iso_msg_is_abort(int errcode)
572 {
573     if (ISO_ERR_SEV(errcode) >= abort_threshold)
574         return 1;
575     return 0;
576 }
577 
578 
iso_msg_submit(int imgid,int errcode,int causedby,const char * fmt,...)579 int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
580 {
581     char msg[MAX_MSG_LEN];
582     va_list ap;
583 
584     /* when called with ISO_CANCELED, we don't need to submit any message */
585     if (errcode == (int) ISO_CANCELED && fmt == NULL) {
586         return ISO_CANCELED;
587     }
588 
589     if (fmt) {
590         va_start(ap, fmt);
591         vsnprintf(msg, MAX_MSG_LEN, fmt, ap);
592         va_end(ap);
593     } else {
594         strncpy(msg, iso_error_to_msg(errcode), MAX_MSG_LEN - 1);
595         msg[MAX_MSG_LEN - 1] = 0;
596     }
597 
598     libiso_msgs_submit(libiso_msgr, imgid, ISO_ERR_CODE(errcode),
599                        ISO_ERR_SEV(errcode), ISO_ERR_PRIO(errcode), msg, 0, 0);
600     if (causedby != 0) {
601         snprintf(msg, MAX_MSG_LEN, " > Caused by: %s",
602                  iso_error_to_msg(causedby));
603         libiso_msgs_submit(libiso_msgr, imgid, ISO_ERR_CODE(causedby),
604                  LIBISO_MSGS_SEV_NOTE, LIBISO_MSGS_PRIO_LOW, msg, 0, 0);
605         if (ISO_ERR_SEV(causedby) == LIBISO_MSGS_SEV_FATAL) {
606             return ISO_CANCELED;
607         }
608     }
609 
610     if (iso_msg_is_abort(errcode)) {
611         return ISO_CANCELED;
612     } else {
613         return 0;
614     }
615 }
616 
617 /**
618  * Control queueing and stderr printing of messages from libisofs.
619  * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
620  * "NOTE", "UPDATE", "DEBUG", "ALL".
621  *
622  * @param queue_severity Gives the minimum limit for messages to be queued.
623  *                       Default: "NEVER". If you queue messages then you
624  *                       must consume them by iso_msgs_obtain().
625  * @param print_severity Does the same for messages to be printed directly
626  *                       to stderr.
627  * @param print_id       A text prefix to be printed before the message.
628  * @return               >0 for success, <=0 for error
629  */
iso_set_msgs_severities(char * queue_severity,char * print_severity,char * print_id)630 int iso_set_msgs_severities(char *queue_severity, char *print_severity,
631                             char *print_id)
632 {
633     int ret, queue_sevno, print_sevno;
634 
635     ret = libiso_msgs__text_to_sev(queue_severity, &queue_sevno, 0);
636     if (ret <= 0)
637         return 0;
638     ret = libiso_msgs__text_to_sev(print_severity, &print_sevno, 0);
639     if (ret <= 0)
640         return 0;
641     ret = libiso_msgs_set_severities(libiso_msgr, queue_sevno, print_sevno,
642                                      print_id, 0);
643     if (ret <= 0)
644         return 0;
645     return 1;
646 }
647 
648 /**
649  * Obtain the oldest pending libisofs message from the queue which has at
650  * least the given minimum_severity. This message and any older message of
651  * lower severity will get discarded from the queue and is then lost forever.
652  *
653  * Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
654  * "NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
655  * will discard the whole queue.
656  *
657  * @param error_code Will become a unique error code as listed in messages.h
658  * @param imgid      Id of the image that was issued the message.
659  * @param msg_text   Must provide at least ISO_MSGS_MESSAGE_LEN bytes.
660  * @param severity   Will become the severity related to the message and
661  *                   should provide at least 80 bytes.
662  * @return 1 if a matching item was found, 0 if not, <0 for severe errors
663  */
iso_obtain_msgs(char * minimum_severity,int * error_code,int * imgid,char msg_text[],char severity[])664 int iso_obtain_msgs(char *minimum_severity, int *error_code, int *imgid,
665                     char msg_text[], char severity[])
666 {
667     int ret, minimum_sevno, sevno, priority, os_errno;
668     double timestamp;
669     pid_t pid;
670     char *textpt, *sev_name;
671     struct libiso_msgs_item *item= NULL;
672 
673     ret = libiso_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
674     if (ret <= 0)
675         return 0;
676     ret = libiso_msgs_obtain(libiso_msgr, &item, minimum_sevno,
677                              LIBISO_MSGS_PRIO_ZERO, 0);
678     if (ret <= 0)
679         goto ex;
680     ret = libiso_msgs_item_get_msg(item, error_code, &textpt, &os_errno, 0);
681     if (ret <= 0)
682         goto ex;
683     strncpy(msg_text, textpt, ISO_MSGS_MESSAGE_LEN-1);
684     if (strlen(textpt) >= ISO_MSGS_MESSAGE_LEN)
685         msg_text[ISO_MSGS_MESSAGE_LEN-1] = 0;
686 
687     ret = libiso_msgs_item_get_origin(item, &timestamp, &pid, imgid, 0);
688     if (ret <= 0)
689         goto ex;
690 
691     severity[0]= 0;
692     ret = libiso_msgs_item_get_rank(item, &sevno, &priority, 0);
693     if (ret <= 0)
694         goto ex;
695     ret = libiso_msgs__sev_to_text(sevno, &sev_name, 0);
696     if (ret <= 0)
697         goto ex;
698     strcpy(severity, sev_name);
699 
700     ret = 1;
701     ex: ;
702     libiso_msgs_destroy_item(libiso_msgr, &item, 0);
703     return ret;
704 }
705 
706 
iso_msgs_submit(int error_code,char msg_text[],int os_errno,char severity[],int origin)707 int iso_msgs_submit(int error_code, char msg_text[], int os_errno,
708 			char severity[], int origin)
709 {
710     int ret, sevno;
711 
712     ret = libiso_msgs__text_to_sev(severity, &sevno, 0);
713     if (ret <= 0)
714     	sevno = LIBISO_MSGS_SEV_ALL;
715     if (error_code <= 0) {
716     	switch(sevno) {
717     	       case LIBISO_MSGS_SEV_ABORT:   error_code = 0x00040000;
718     	break; case LIBISO_MSGS_SEV_FATAL:   error_code = 0x00040001;
719     	break; case LIBISO_MSGS_SEV_SORRY:   error_code = 0x00040002;
720     	break; case LIBISO_MSGS_SEV_WARNING: error_code = 0x00040003;
721     	break; case LIBISO_MSGS_SEV_HINT:    error_code = 0x00040004;
722     	break; case LIBISO_MSGS_SEV_NOTE:    error_code = 0x00040005;
723     	break; case LIBISO_MSGS_SEV_UPDATE:  error_code = 0x00040006;
724     	break; case LIBISO_MSGS_SEV_DEBUG:   error_code = 0x00040007;
725     	break; default:                      error_code = 0x00040008;
726     	}
727     }
728     ret = libiso_msgs_submit(libiso_msgr, origin, error_code,
729         	          sevno, LIBISO_MSGS_PRIO_HIGH, msg_text, os_errno, 0);
730     return ret;
731 }
732 
733 
iso_text_to_sev(char * severity_name,int * sevno)734 int iso_text_to_sev(char *severity_name, int *sevno)
735 {
736     int ret;
737 
738     ret = libiso_msgs__text_to_sev(severity_name, sevno, 0);
739     if (ret <= 0)
740     	*sevno = LIBISO_MSGS_SEV_FATAL;
741     return ret;
742 }
743 
744 
iso_sev_to_text(int severity_number,char ** severity_name)745 int iso_sev_to_text(int severity_number, char **severity_name)
746 {
747     int ret;
748 
749     ret = libiso_msgs__sev_to_text(severity_number, severity_name, 0);
750     return ret;
751 }
752 
753 
754 /**
755  * Return the messenger object handle used by libisofs. This handle
756  * may be used by related libraries to  their own compatible
757  * messenger objects and thus to direct their messages to the libisofs
758  * message queue. See also: libburn, API function burn_set_messenger().
759  *
760  * @return the handle. Do only use with compatible
761  */
iso_get_messenger()762 void *iso_get_messenger()
763 {
764     return libiso_msgr;
765 }
766 
iso_error_get_severity(int e)767 int iso_error_get_severity(int e)
768 {
769     return ISO_ERR_SEV(e);
770 }
771 
iso_error_get_priority(int e)772 int iso_error_get_priority(int e)
773 {
774     return ISO_ERR_PRIO(e);
775 }
776 
iso_error_get_code(int e)777 int iso_error_get_code(int e)
778 {
779     return ISO_ERR_CODE(e);
780 }
781 
782 
iso_report_errfile(char * path,int error_code,int os_errno,int flag)783 int iso_report_errfile(char *path, int error_code, int os_errno, int flag)
784 {
785     libiso_msgs_submit(libiso_msgr, 0, error_code,
786                        LIBISO_MSGS_SEV_ERRFILE, LIBISO_MSGS_PRIO_HIGH,
787                        path, os_errno, 0);
788     return(1);
789 }
790 
791 
iso_libjte_forward_msgs(void * libjte_handle,int imgid,int errcode,int flag)792 int iso_libjte_forward_msgs(void *libjte_handle,
793                             int imgid, int errcode, int flag)
794 {
795 
796 #ifdef Libisofs_with_libjtE
797 
798     char *msg = NULL;
799     int res;
800     struct libjte_env *handle = (struct libjte_env *) libjte_handle;
801 
802     res = ISO_SUCCESS;
803     while(1) {
804        msg= libjte_get_next_message(handle);
805        if(msg == NULL)
806     break;
807        res = iso_msg_submit(imgid, errcode, 0, msg);
808        free(msg);
809     }
810     return res;
811 
812 #else /* Libisofs_with_libjtE */
813 
814     return ISO_SUCCESS;
815 
816 #endif /* ! Libisofs_with_libjtE */
817 
818 }
819 
820