File indexing completed on 2025-03-09 04:09:53

0001 /* Generic support functions for Xcftools
0002  *
0003  * This file was written by Henning Makholm <henning@makholm.net>
0004  * It is hereby in the public domain.
0005  * 
0006  * In jurisdictions that do not recognise grants of copyright to the
0007  * public domain: I, the author and (presumably, in those jurisdictions)
0008  * copyright holder, hereby permit anyone to distribute and use this code,
0009  * in source code or binary form, with or without modifications. This
0010  * permission is world-wide and irrevocable.
0011  *
0012  * Of course, I will not be liable for any errors or shortcomings in the
0013  * code, since I give it away without asking any compenstations.
0014  *
0015  * If you use or distribute this code, I would appreciate receiving
0016  * credit for writing it, in whichever way you find proper and customary.
0017  */
0018 
0019 #include "xcftools.h"
0020 #include <string.h>
0021 #include <stdarg.h>
0022 #include <stdlib.h>
0023 #include <errno.h>
0024 
0025 const char *progname = "$0" ;
0026 int verboseFlag = 0 ;
0027 
0028 static void
0029 vFatalGeneric(int status,const char *format, va_list args)
0030 {
0031   (void) status; /* mark as unused */
0032   if( format ) {
0033     if( *format == '!' ) {
0034       vfprintf(stderr,format+1,args);
0035       fprintf(stderr,": %s\n",strerror(errno));
0036     } else {
0037       vfprintf(stderr,format,args);
0038       fputc('\n',stderr);
0039     }
0040   }
0041   /* don't exit here - Krita can't handle errors otherwise */
0042   /* exit(status); */
0043 }
0044 
0045 void
0046 FatalGeneric(int status,const char* format,...)
0047 {
0048   va_list v;
0049   va_start(v,format);
0050   if( format ) fprintf(stderr,"%s: ",progname);
0051   vFatalGeneric(status,format,v);
0052   va_end(v);
0053 }
0054 
0055 void
0056 FatalUnexpected(const char* format,...)
0057 {
0058   va_list v;
0059   va_start(v, format);
0060   fprintf(stderr,"%s: ",progname);
0061   vFatalGeneric(127, format, v);
0062   va_end(v);
0063 }
0064 
0065 void
0066 FatalBadXCF(const char* format,...)
0067 {
0068   va_list v; va_start(v,format);
0069   fprintf(stderr,"%s: %s:\n ",progname,_("Corrupted or malformed XCF file"));
0070   vFatalGeneric(125,format,v) ;
0071   va_end(v);
0072 }
0073 
0074 int
0075 xcfCheckspace(uint32_t addr,int spaceafter,const char *format,...)
0076 {
0077   if( xcf_length < spaceafter || addr > xcf_length - spaceafter ) {
0078     va_list v;
0079     va_start(v,format);
0080     fprintf(stderr,"%s: %s\n ",progname,_("Corrupted or truncated XCF file"));
0081     fprintf(stderr,"(0x%" PRIXPTR " bytes): ",(uintptr_t)xcf_length);
0082     vFatalGeneric(125,format,v) ;
0083     va_end(v);
0084     return XCF_ERROR;
0085   }
0086   return XCF_OK;
0087 }
0088 
0089 
0090 void
0091 FatalUnsupportedXCF(const char* format,...)
0092 {
0093   va_list v;
0094   va_start(v,format);
0095   fprintf(stderr,"%s: %s\n ",progname,
0096           _("The image contains features not understood by this program:"));
0097   vFatalGeneric(123,format,v) ;
0098   va_end(v);
0099 }
0100 
0101 void
0102 gpl_blurb(void)
0103 {
0104   fprintf(stderr,PACKAGE_STRING "\n");
0105   fprintf(stderr,
0106           _("Type \"%s -h\" to get an option summary.\n"),progname);
0107   /* don't exit here - Krita will close otherwise */
0108   /* exit(1) ; */
0109 }
0110 
0111 /* ******************************************************* */
0112 
0113 void *
0114 xcfmalloc(size_t size)
0115 {
0116   void *ptr = malloc(size);
0117   if( !ptr ) {
0118     FatalUnexpected(_("Out of memory"));
0119     return XCF_PTR_EMPTY;
0120   }
0121   return ptr ;
0122 }
0123 
0124 void
0125 xcffree(void *block)
0126 {
0127   if( xcf_file &&
0128       (uint8_t*)block >= xcf_file &&
0129       (uint8_t*)block < xcf_file + xcf_length )
0130     ;
0131   else
0132     free(block);
0133 }
0134 
0135 /* ******************************************************* */
0136 
0137 FILE *
0138 openout(const char *name)
0139 {
0140   FILE *newfile ;
0141   if( strcmp(name,"-") == 0 )
0142     return stdout ;
0143   newfile = fopen(name,"wb") ;
0144   if( newfile == NULL ) {
0145     FatalUnexpected(_("!Cannot create file %s"),name);
0146     return XCF_PTR_EMPTY;
0147   }
0148   return newfile ;
0149 }
0150 
0151 int
0152 closeout(FILE *f,const char *name)
0153 {
0154   if( f == NULL )
0155     return XCF_OK;
0156   if( fflush(f) == 0 ) {
0157     errno = 0 ;
0158     if( !ferror(f) ) {
0159       if( fclose(f) == 0 )
0160         return XCF_OK;
0161     } else if( errno == 0 ) {
0162       /* Attempt to coax a valid errno out of the standard library,
0163        * following an idea by Bruno Haible
0164        * https://lists.gnu.org/archive/html/bug-gnulib/2003-09/msg00157.html
0165        */
0166       if( fputc('\0', f) != EOF &&
0167           fflush(f) == 0 )
0168         errno = EIO ; /* Argh, everything succedes. Just call it an I/O error */
0169     }
0170   }
0171   FatalUnexpected(_("!Error writing file %s"),name);
0172   return XCF_ERROR;
0173 }