theme_loader.cpp 20.3 KB
Newer Older
1
2
3
/*****************************************************************************
 * theme_loader.cpp
 *****************************************************************************
4
 * Copyright (C) 2003 the VideoLAN team
5
 * $Id$
6
7
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8
 *          Olivier Teulière <ipkiss@via.ecp.fr>
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23
24
25
26
27
 *****************************************************************************/

#include "theme_loader.hpp"
#include "theme.hpp"
#include "../parser/builder.hpp"
28
#include "../parser/skin_parser.hpp"
29
#include "../src/os_factory.hpp"
30
#include "../src/vlcproc.hpp"
31
32
#include "../src/window_manager.hpp"

33
34
#include <cctype>

35
36
37
#ifdef HAVE_FCNTL_H
#   include <fcntl.h>
#endif
38
39
40
41
#ifdef HAVE_SYS_STAT_H
#   include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
42
#   include <unistd.h>
43
#elif defined( WIN32 ) && !defined( UNDER_CE )
44
45
46
#   include <direct.h>
#endif

47
#ifdef HAVE_DIRENT_H
48
49
50
#   include <dirent.h>
#endif

51
52
53
54

#if defined( HAVE_ZLIB_H )
#   include <zlib.h>
#   include <errno.h>
Rafaël Carré's avatar
Rafaël Carré committed
55
int gzopen_frontend ( const char *pathname, int oflags, int mode );
56
57
58
int gzclose_frontend( int );
int gzread_frontend ( int, void *, size_t );
int gzwrite_frontend( int, const void *, size_t );
59
60
61
62
63
64
65
#if defined( HAVE_LIBTAR_H )
#   include <libtar.h>
#else
typedef gzFile TAR;
int tar_open        ( TAR **t, char *pathname, int oflags );
int tar_extract_all ( TAR *t, char *prefix );
int tar_close       ( TAR *t );
66
int getoct( char *p, int width );
67
#endif
68
int makedir( const char *newdir );
69
70
71
#endif

#define DEFAULT_XML_FILE "theme.xml"
72
#define WINAMP2_XML_FILE "winamp2.xml"
73
#define ZIP_BUFFER_SIZE 4096
74
75
76
77


bool ThemeLoader::load( const string &fileName )
{
78
79
80
81
82
83
84
    string path = getFilePath( fileName );

    //Before all, let's see if the file is present
    struct stat p_stat;
    if( utf8_stat( path.c_str(), &p_stat ) )
        return false;

85
86
    // First, we try to un-targz the file, and if it fails we hope it's a XML
    // file...
87

88
#if defined( HAVE_ZLIB_H )
89
    if( ! extract( sToLocale( fileName ) ) && ! parse( path, fileName ) )
90
91
        return false;
#else
92
    if( ! parse( path, fileName ) )
93
94
95
        return false;
#endif

96
97
98
99
100
101
    Theme *pNewTheme = getIntf()->p_sys->p_theme;
    if( !pNewTheme )
    {
        return false;
    }

102
    // Check if the skin to load is in the config file, to load its config
gbazin's avatar
   
gbazin committed
103
    char *skin_last = config_GetPsz( getIntf(), "skins2-last" );
104
105
    if( skin_last != NULL && fileName == (string)skin_last )
    {
106
107
        // Restore the theme configuration
        getIntf()->p_sys->p_theme->loadConfig();
108
109
        // Used to anchor the windows at the beginning
        pNewTheme->getWindowManager().stopMove();
110
111
112
    }
    else
    {
gbazin's avatar
   
gbazin committed
113
        config_PutPsz( getIntf(), "skins2-last", fileName.c_str() );
114
        // Show the windows
115
        pNewTheme->getWindowManager().showAll( true );
116
    }
117
    free( skin_last );
118

119
    // The new theme cannot embed a video output yet
120
    VlcProc::instance( getIntf() )->dropVout();
121

122
123
124
125
126
127
128
129
130
    return true;
}


#if defined( HAVE_ZLIB_H )
bool ThemeLoader::extractTarGz( const string &tarFile, const string &rootDir )
{
    TAR *t;
#if defined( HAVE_LIBTAR_H )
131
132
133
134
    tartype_t gztype = { (openfunc_t) gzopen_frontend,
                         (closefunc_t) gzclose_frontend,
                         (readfunc_t) gzread_frontend,
                         (writefunc_t) gzwrite_frontend };
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

    if( tar_open( &t, (char *)tarFile.c_str(), &gztype, O_RDONLY, 0,
                  TAR_GNU ) == -1 )
#else
    if( tar_open( &t, (char *)tarFile.c_str(), O_RDONLY ) == -1 )
#endif
    {
        return false;
    }

    if( tar_extract_all( t, (char *)rootDir.c_str() ) != 0 )
    {
        tar_close( t );
        return false;
    }

    if( tar_close( t ) != 0 )
    {
        return false;
    }

    return true;
}


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
bool ThemeLoader::extractZip( const string &zipFile, const string &rootDir )
{
    // Try to open the ZIP file
    unzFile file = unzOpen( zipFile.c_str() );
    unz_global_info info;

    if( unzGetGlobalInfo( file, &info ) != UNZ_OK )
    {
        return false;
    }
    // Extract all the files in the archive
    for( unsigned long i = 0; i < info.number_entry; i++ )
    {
        if( !extractFileInZip( file, rootDir ) )
        {
zorglub's avatar
zorglub committed
175
            msg_Warn( getIntf(), "error while unzipping %s",
176
                      zipFile.c_str() );
177
            unzClose( file );
178
179
180
181
182
183
184
185
            return false;
        }

        if( i < info.number_entry - 1 )
        {
            // Go the next file in the archive
            if( unzGoToNextFile( file ) !=UNZ_OK )
            {
zorglub's avatar
zorglub committed
186
                msg_Warn( getIntf(), "error while unzipping %s",
187
                          zipFile.c_str() );
188
                unzClose( file );
189
190
191
192
                return false;
            }
        }
    }
193
    unzClose( file );
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    return true;
}


bool ThemeLoader::extractFileInZip( unzFile file, const string &rootDir )
{
    // Read info for the current file
    char filenameInZip[256];
    unz_file_info fileInfo;
    if( unzGetCurrentFileInfo( file, &fileInfo, filenameInZip,
                               sizeof( filenameInZip), NULL, 0, NULL, 0 )
        != UNZ_OK )
    {
        return false;
    }

210
211
    // Convert the file name to lower case, because some winamp skins
    // use the wrong case...
212
    for( size_t i=0; i< strlen( filenameInZip ); i++)
213
214
215
216
    {
        filenameInZip[i] = tolower( filenameInZip[i] );
    }

217
218
219
220
    // Allocate the buffer
    void *pBuffer = malloc( ZIP_BUFFER_SIZE );
    if( !pBuffer )
    {
zorglub's avatar
zorglub committed
221
        msg_Err( getIntf(), "failed to allocate memory" );
222
223
224
225
        return false;
    }

    // Get the path of the file
226
    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
227
228
229
    string fullPath = rootDir
        + pOsFactory->getDirSeparator()
        + fixDirSeparators( filenameInZip );
230
    string basePath = getFilePath( fullPath );
231
232

    // Extract the file if is not a directory
233
    if( basePath != fullPath )
234
235
236
237
238
239
240
241
242
243
    {
        if( unzOpenCurrentFile( file ) )
        {
            free( pBuffer );
            return false;
        }
        makedir( basePath.c_str() );
        FILE *fout = fopen( fullPath.c_str(), "wb" );
        if( fout == NULL )
        {
zorglub's avatar
zorglub committed
244
            msg_Err( getIntf(), "error opening %s", fullPath.c_str() );
245
246
247
248
249
250
251
252
253
254
255
            free( pBuffer );
            return false;
        }

        // Extract the current file
        int n;
        do
        {
            n = unzReadCurrentFile( file, pBuffer, ZIP_BUFFER_SIZE );
            if( n < 0 )
            {
zorglub's avatar
zorglub committed
256
                msg_Err( getIntf(), "error while reading zip file" );
257
258
259
260
261
262
263
                free( pBuffer );
                return false;
            }
            else if( n > 0 )
            {
                if( fwrite( pBuffer, n , 1, fout) != 1 )
                {
zorglub's avatar
zorglub committed
264
                    msg_Err( getIntf(), "error while writing %s",
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
                             fullPath.c_str() );
                    free( pBuffer );
                    return false;
                }
            }
        } while( n > 0 );

        fclose(fout);

        if( unzCloseCurrentFile( file ) != UNZ_OK )
        {
            free( pBuffer );
            return false;
        }
    }

    free( pBuffer );
    return true;
}


286
287
bool ThemeLoader::extract( const string &fileName )
{
288
    bool result = true;
289
    char *tmpdir = tempnam( NULL, "vlt" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
290
    string tempPath = sFromLocale( tmpdir );
291
292
293
    free( tmpdir );

    // Extract the file in a temporary directory
294
295
    if( ! extractTarGz( fileName, tempPath ) &&
        ! extractZip( fileName, tempPath ) )
296
297
    {
        deleteTempFiles( tempPath );
298
        return false;
299
    }
300

301
    string path;
302
    string xmlFile;
303
304
305
    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
    // Find the XML file in the theme
    if( findFile( tempPath, DEFAULT_XML_FILE, xmlFile ) )
306
    {
307
308
309
310
        path = getFilePath( xmlFile );
    }
    else
    {
311
312
313
        // No XML file, check if it is a winamp2 skin
        string mainBmp;
        if( findFile( tempPath, "main.bmp", mainBmp ) )
314
        {
zorglub's avatar
zorglub committed
315
            msg_Dbg( getIntf(), "trying to load a winamp2 skin" );
316
317
318
319
320
321
322
            path = getFilePath( mainBmp );

            // Look for winamp2.xml in the resource path
            list<string> resPath = pOsFactory->getResourcePath();
            list<string>::const_iterator it;
            for( it = resPath.begin(); it != resPath.end(); it++ )
            {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
323
                if( findFile( *it, WINAMP2_XML_FILE, xmlFile ) )
324
325
                    break;
            }
326
327
328
329
330
331
332
333
        }
    }

    if( !xmlFile.empty() )
    {
        // Parse the XML file
        if (! parse( path, xmlFile ) )
        {
zorglub's avatar
zorglub committed
334
            msg_Err( getIntf(), "error while parsing %s", xmlFile.c_str() );
335
336
337
338
339
            result = false;
        }
    }
    else
    {
zorglub's avatar
zorglub committed
340
        msg_Err( getIntf(), "no XML found in theme %s", fileName.c_str() );
341
        result = false;
342
343
344
345
    }

    // Clean-up
    deleteTempFiles( tempPath );
346
    return result;
347
348
349
350
351
352
353
354
355
356
}


void ThemeLoader::deleteTempFiles( const string &path )
{
    OSFactory::instance( getIntf() )->rmDir( path );
}
#endif // HAVE_ZLIB_H


357
bool ThemeLoader::parse( const string &path, const string &xmlFile )
358
359
{
    // File loaded
zorglub's avatar
zorglub committed
360
    msg_Dbg( getIntf(), "using skin file: %s", xmlFile.c_str() );
361
362

    // Start the parser
363
364
    SkinParser parser( getIntf(), xmlFile, path );
    if( ! parser.parse() )
365
    {
zorglub's avatar
zorglub committed
366
        msg_Err( getIntf(), "failed to parse %s", xmlFile.c_str() );
367
368
369
370
        return false;
    }

    // Build and store the theme
371
    Builder builder( getIntf(), parser.getData(), path );
372
373
374
375
376
377
    getIntf()->p_sys->p_theme = builder.build();

    return true;
}


378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
string ThemeLoader::getFilePath( const string &rFullPath )
{
    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
    const string &sep = pOsFactory->getDirSeparator();
    // Find the last separator ('/' or '\')
    string::size_type p = rFullPath.rfind( sep, rFullPath.size() );
    string basePath;
    if( p != string::npos )
    {
        if( p < rFullPath.size() - 1)
        {
            basePath = rFullPath.substr( 0, p );
        }
        else
        {
            basePath = rFullPath;
        }
    }
    return basePath;
}


400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
string ThemeLoader::fixDirSeparators( const string &rPath )
{
    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
    const string &sep = pOsFactory->getDirSeparator();
    string::size_type p = rPath.find( "/", 0 );
    string newPath = rPath;
    while( p != string::npos )
    {
        newPath = newPath.replace( p, 1, sep );
        p = newPath.find( "/", p + 1 );
    }
    return newPath;
}


415
416
bool ThemeLoader::findFile( const string &rootDir, const string &rFileName,
                            string &themeFilePath )
417
418
419
420
421
{
    // Path separator
    const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();

    DIR *pCurrDir;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
422
    char *pszDirContent;
423
424

    // Open the dir
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
425
    pCurrDir = utf8_opendir( rootDir.c_str() );
426
427
428
429

    if( pCurrDir == NULL )
    {
        // An error occurred
zorglub's avatar
zorglub committed
430
        msg_Dbg( getIntf(), "cannot open directory %s", rootDir.c_str() );
431
432
433
434
        return false;
    }

    // While we still have entries in the directory
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
435
    while( ( pszDirContent = utf8_readdir( pCurrDir ) ) != NULL )
436
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
437
        string newURI = rootDir + sep + pszDirContent;
438
439

        // Skip . and ..
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
440
441
        if( string( pszDirContent ) != "." &&
            string( pszDirContent ) != ".." )
442
443
444
        {
#if defined( S_ISDIR )
            struct stat stat_data;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
445
446
447

            if( ( utf8_stat( newURI.c_str(), &stat_data ) == 0 )
             && S_ISDIR(stat_data.st_mode) )
448
#elif defined( DT_DIR )
449
            if( pDirContent->d_type & DT_DIR )
450
451
452
453
#else
            if( 0 )
#endif
            {
454
455
                // Can we find the file in this subdirectory?
                if( findFile( newURI, rFileName, themeFilePath ) )
456
                {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
457
                    free( pszDirContent );
458
                    closedir( pCurrDir );
459
460
461
462
463
464
                    return true;
                }
            }
            else
            {
                // Found the theme file?
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
465
                if( rFileName == string( pszDirContent ) )
466
                {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
467
468
                    themeFilePath = newURI;
                    free( pszDirContent );
469
                    closedir( pCurrDir );
470
471
472
473
474
                    return true;
                }
            }
        }

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
475
        free( pszDirContent );
476
477
    }

478
    closedir( pCurrDir );
479
480
481
482
    return false;
}


483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
#if !defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )

/* Values used in typeflag field */
#define REGTYPE  '0'            /* regular file */
#define AREGTYPE '\0'           /* regular file */
#define DIRTYPE  '5'            /* directory */

#define BLOCKSIZE 512

struct tar_header
{                               /* byte offset */
    char name[100];             /*   0 */
    char mode[8];               /* 100 */
    char uid[8];                /* 108 */
    char gid[8];                /* 116 */
    char size[12];              /* 124 */
    char mtime[12];             /* 136 */
    char chksum[8];             /* 148 */
    char typeflag;              /* 156 */
    char linkname[100];         /* 157 */
    char magic[6];              /* 257 */
    char version[2];            /* 263 */
    char uname[32];             /* 265 */
    char gname[32];             /* 297 */
    char devmajor[8];           /* 329 */
    char devminor[8];           /* 337 */
    char prefix[155];           /* 345 */
                                /* 500 */
};


union tar_buffer {
    char              buffer[BLOCKSIZE];
    struct tar_header header;
};



int tar_open( TAR **t, char *pathname, int oflags )
{
    gzFile f = gzopen( pathname, "rb" );
    if( f == NULL )
    {
        fprintf( stderr, "Couldn't gzopen %s\n", pathname );
        return -1;
    }

    *t = (gzFile *)malloc( sizeof(gzFile) );
    **t = f;
    return 0;
}


int tar_extract_all( TAR *t, char *prefix )
{
    union tar_buffer buffer;
    int   len, err, getheader = 1, remaining = 0;
    FILE  *outfile = NULL;
    char  fname[BLOCKSIZE + PATH_MAX];

    while( 1 )
    {
        len = gzread( *t, &buffer, BLOCKSIZE );
        if( len < 0 )
        {
            fprintf( stderr, "%s\n", gzerror(*t, &err) );
        }

        /*
         * Always expect complete blocks to process
         * the tar information.
         */
        if( len != 0 && len != BLOCKSIZE )
        {
            fprintf( stderr, "gzread: incomplete block read\n" );
            return -1;
        }

        /*
         * If we have to get a tar header
         */
        if( getheader == 1 )
        {
            /*
             * If we met the end of the tar
             * or the end-of-tar block, we are done
             */
            if( (len == 0) || (buffer.header.name[0] == 0) )
            {
                break;
            }

            sprintf( fname, "%s/%s", prefix, buffer.header.name );

            /* Check magic value in header */
            if( strncmp( buffer.header.magic, "GNUtar", 6 ) &&
                strncmp( buffer.header.magic, "ustar", 5 ) )
            {
                //fprintf(stderr, "not a tar file\n");
                return -1;
            }

            switch( buffer.header.typeflag )
            {
                case DIRTYPE:
                    makedir( fname );
                    break;
                case REGTYPE:
                case AREGTYPE:
                    remaining = getoct( buffer.header.size, 12 );
                    if( remaining )
                    {
                        outfile = fopen( fname, "wb" );
                        if( outfile == NULL )
                        {
                            /* try creating directory */
                            char *p = strrchr( fname, '/' );
                            if( p != NULL )
                            {
                                *p = '\0';
                                makedir( fname );
                                *p = '/';
                                outfile = fopen( fname, "wb" );
                                if( !outfile )
                                {
                                    fprintf( stderr, "tar couldn't create %s\n",
                                             fname );
                                }
                            }
                        }
                    }
                    else outfile = NULL;

                /*
                 * could have no contents
                 */
                getheader = (remaining) ? 0 : 1;
                break;
            default:
                break;
            }
        }
        else
        {
            unsigned int bytes = (remaining > BLOCKSIZE)?BLOCKSIZE:remaining;

            if( outfile != NULL )
            {
                if( fwrite( &buffer, sizeof(char), bytes, outfile ) != bytes )
                {
                    fprintf( stderr, "error writing %s skipping...\n", fname );
                    fclose( outfile );
Rafaël Carré's avatar
Rafaël Carré committed
635
                    outfile = NULL;
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
                    unlink( fname );
                }
            }
            remaining -= bytes;
            if( remaining == 0 )
            {
                getheader = 1;
                if( outfile != NULL )
                {
                    fclose(outfile);
                    outfile = NULL;
                }
            }
        }
    }

    return 0;
}


int tar_close( TAR *t )
{
    if( gzclose( *t ) != Z_OK ) fprintf( stderr, "failed gzclose\n" );
    free( t );
    return 0;
}


/* helper functions */
int getoct( char *p, int width )
{
    int result = 0;
    char c;

    while( width-- )
    {
        c = *p++;
        if( c == ' ' )
            continue;
        if( c == 0 )
            break;
        result = result * 8 + (c - '0');
    }
    return result;
}

682
683
684
685
686
#endif

#ifdef WIN32
#  define mkdir(dirname,mode) _mkdir(dirname)
#endif
687
688
689
690
691
692
693

/* Recursive make directory
 * Abort if you get an ENOENT errno somewhere in the middle
 * e.g. ignore error "mkdir on existing directory"
 *
 * return 1 if OK, 0 on error
 */
694
int makedir( const char *newdir )
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
{
    char *p, *buffer = strdup( newdir );
    int  len = strlen( buffer );

    if( len <= 0 )
    {
        free( buffer );
        return 0;
    }

    if( buffer[len-1] == '/' )
    {
        buffer[len-1] = '\0';
    }

    if( mkdir( buffer, 0775 ) == 0 )
    {
        free( buffer );
        return 1;
    }

    p = buffer + 1;
    while( 1 )
    {
        char hold;

        while( *p && *p != '\\' && *p != '/' ) p++;
        hold = *p;
        *p = 0;
        if( ( mkdir( buffer, 0775 ) == -1 ) && ( errno == ENOENT ) )
        {
            fprintf( stderr, "couldn't create directory %s\n", buffer );
            free( buffer );
            return 0;
        }
        if( hold == 0 ) break;
        *p++ = hold;
    }
    free( buffer );
    return 1;
}
736
737

#ifdef HAVE_ZLIB_H
738
739
740
741

static int currentGzFd = -1;
static void * currentGzVp = NULL;

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
742
int gzopen_frontend( const char *pathname, int oflags, int mode )
743
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
744
    const char *gzflags;
745
746
    gzFile gzf;

747
    switch( oflags )
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
    {
        case O_WRONLY:
            gzflags = "wb";
            break;
        case O_RDONLY:
            gzflags = "rb";
            break;
        case O_RDWR:
        default:
            errno = EINVAL;
            return -1;
    }

    gzf = gzopen( pathname, gzflags );
    if( !gzf )
    {
        errno = ENOMEM;
        return -1;
    }

768
769
770
771
772
773
774
775
776
777
778
    /** Hum ... */
    currentGzFd = 42;
    currentGzVp = gzf;

    return currentGzFd;
}

int gzclose_frontend( int fd )
{
    if( currentGzVp != NULL && fd != -1 )
    {
zorglub's avatar
zorglub committed
779
780
781
        void *toClose = currentGzVp;
        currentGzVp = NULL;  currentGzFd = -1;
        return gzclose( toClose );
782
783
    }
    return -1;
784
}
785
786
787
788
789
790
791
792
793
794
795
796
797
798

int gzread_frontend( int fd, void *p_buffer, size_t i_length )
{
    if( currentGzVp != NULL && fd != -1 )
    {
        return gzread( currentGzVp, p_buffer, i_length );
    }
    return -1;
}

int gzwrite_frontend( int fd, const void * p_buffer, size_t i_length )
{
    if( currentGzVp != NULL && fd != -1 )
    {
damienf's avatar
damienf committed
799
        return gzwrite( currentGzVp, const_cast<void*>(p_buffer), i_length );
800
801
802
803
    }
    return -1;
}

804
#endif