diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
commit | 0292059f4a16434600564cfa3f0ad2309a508a54 (patch) | |
tree | d95953cd53011917c4df679b96aedca39401b54f /kernel/kls_xcf/xcf2pnm/io-unix.c | |
download | libksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.tar.gz libksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.zip |
Added libksquirrel for KDE3
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/libksquirrel@1095624 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kernel/kls_xcf/xcf2pnm/io-unix.c')
-rw-r--r-- | kernel/kls_xcf/xcf2pnm/io-unix.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/kernel/kls_xcf/xcf2pnm/io-unix.c b/kernel/kls_xcf/xcf2pnm/io-unix.c new file mode 100644 index 0000000..38dc4e4 --- /dev/null +++ b/kernel/kls_xcf/xcf2pnm/io-unix.c @@ -0,0 +1,176 @@ +/* OS-specific IO functions for xcftools + * + * Copyright (C) 2006 Henning Makholm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xcftools.h" +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#if HAVE_MMAP +#include <sys/mman.h> +#endif + +static FILE *xcfstream = 0 ; + +void +free_or_close_xcf(void) +{ + if( xcf_file ) { + if( xcfstream ) { + munmap(xcf_file,xcf_length) ; + fclose(xcfstream); + xcf_file = 0 ; + xcfstream = 0 ; + } else { + free(xcf_file) ; + xcf_file = 0 ; + } + } +} + +void +read_or_mmap_xcf(const char *filename,const char *unzipper) +{ + struct stat statbuf ; + + free_or_close_xcf() ; + + if( strcmp(filename,"-") != 0 ) { + if( access(filename,R_OK) != 0 ) + FatalGeneric(21,"!%s",filename); + } + + if( !unzipper ) { + const char *pc ; + pc = filename + strlen(filename) ; + if( pc-filename > 2 && strcmp(pc-2,"gz") == 0 ) + unzipper = "zcat" ; + else if ( pc-filename > 3 && strcmp(pc-3,"bz2") == 0 ) + unzipper = "bzcat" ; + else + unzipper = "" ; + } else if( strcmp(unzipper,"cat") == 0 ) + unzipper = "" ; + + if( *unzipper ) { + int pid, status, outfd ; +#if HAVE_MMAP + xcfstream = tmpfile() ; + if( !xcfstream ) + FatalUnexpected(_("!Cannot create temporary unzipped file")); + outfd = fileno(xcfstream) ; +#else + int fh[2] ; + if( pipe(fh) < 0 ) + FatalUnexpected("!Cannot create pipe for %s",unzipper); + xcfstream = fdopen(fh[1],"rb") ; + if( !xcfstream ) + FatalUnexpected("!Cannot fdopen() unzipper pipe"); + outfd = fh[0] ; +#endif + if( (pid = fork()) == 0 ) { + /* We're the child */ + if( dup2(outfd,1) < 0 ) { + perror("Cannot dup2 in unzip process"); + exit(127) ; + } + fclose(xcfstream) ; + execlp(unzipper,unzipper,filename,NULL) ; + fprintf(stderr,_("Cannot execute ")); + perror(unzipper); + exit(126) ; + } +#if HAVE_MMAP + while( wait(&status) != pid ) + ; + if( WIFEXITED(status) ) { + status = WEXITSTATUS(status) ; + if( status > 0 ) { + fclose(xcfstream) ; + xcfstream = 0 ; + FatalGeneric(status,NULL); + } + } else { + fclose(xcfstream) ; + xcfstream = 0 ; + FatalGeneric(126,_("%s terminated abnormally"),unzipper); + } +#else + close(fh[0]) ; +#endif + } else if( strcmp(filename,"-") == 0 ) { + xcfstream = fdopen(dup(0),"rb") ; + if( !xcfstream ) + FatalUnexpected("!Cannot dup stdin for input") ; + } else { + xcfstream = fopen(filename,"rb") ; + if( !xcfstream ) + FatalGeneric(21,_("!Cannot open %s"),filename); + } + /* OK, now we have an open stream ... */ + if( fstat(fileno(xcfstream),&statbuf) == 0 && + (statbuf.st_mode & S_IFMT) == S_IFREG ) { + xcf_length = statbuf.st_size ; +#if HAVE_MMAP + xcf_file = mmap(0,xcf_length,PROT_READ,MAP_SHARED,fileno(xcfstream),0); + if( xcf_file != (void*)-1 ) + return ; + if( errno != ENODEV ) { + int saved = errno ; + fclose(xcfstream) ; + xcf_file = 0 ; + errno = saved ; + FatalUnexpected("!Could not mmap input"); + } +#endif + xcf_file = malloc(xcf_length); + if( xcf_file == 0 ) + FatalUnexpected(_("Out of memory for xcf data")); + if( fread(xcf_file,1,xcf_length,xcfstream) != xcf_length ) { + if( feof(xcfstream) ) + FatalUnexpected(_("XCF file shrunk while reading it")); + else + FatalUnexpected(_("!Could not read xcf data")); + } + fclose(xcfstream) ; + xcfstream = 0 ; + } else { + size_t blocksize = 0x80000 ; /* 512 KB */ + xcf_length = 0 ; + xcf_file = 0 ; + while(1) { + xcf_file = realloc(xcf_file,blocksize) ; + if( xcf_file == 0 ) + FatalUnexpected(_("Out of memory for xcf data")); + size_t actual = fread(xcf_file+xcf_length,1,blocksize-xcf_length, + xcfstream) ; + xcf_length += actual ; + if( feof(xcfstream) ) + break ; + if( xcf_length < blocksize ) { + FatalUnexpected(_("!Could not read xcf data")) ; + } + blocksize += (blocksize >> 1) & ~(size_t)0x3FFF ; /* 16 KB granularity */ + } + fclose(xcfstream) ; + xcfstream = 0 ; + } +} |