~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/*
2
  azio is a modified version of gzio. It  makes use of mysys and removes mallocs.
3
    -Brian Aker
4
*/
5
6
/* gzio.c -- IO on .gz files
7
 * Copyright (C) 1995-2005 Jean-loup Gailly.
8
 * For conditions of distribution and use, see copyright notice in zlib.h
9
 *
10
 */
11
12
/* @(#) $Id$ */
13
14
#include "azio.h"
15
16
#include <stdio.h>
17
#include <string.h>
598.1.1 by Super-User
Fixed solaris build crap.
18
#include <stdlib.h>
1 by brian
clean slate
19
#include <assert.h>
133 by Brian Aker
Cleanup of warning/errors.
20
#include <unistd.h>
77.1.4 by Monty Taylor
Got archive compiling cleanly.
21
1 by brian
clean slate
22
static int const az_magic[3] = {0xfe, 0x03, 0x01}; /* az magic header */
23
24
static unsigned int azwrite(azio_stream *s, void *buf, unsigned int len);
25
static int azrewind (azio_stream *s);
26
static unsigned int azio_enable_aio(azio_stream *s);
27
static int do_flush(azio_stream *file, int flush);
28
static int    get_byte(azio_stream *s);
29
static void   check_header(azio_stream *s);
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
30
static int write_header(azio_stream *s);
1 by brian
clean slate
31
static int    destroy(azio_stream *s);
32
static void putLong(azio_stream *s, uLong x);
33
static uLong  getLong(azio_stream *s);
34
static void read_header(azio_stream *s, unsigned char *buffer);
35
static void get_block(azio_stream *s);
36
#ifdef AZIO_AIO
37
static void do_aio_cleanup(azio_stream *s);
38
#endif
39
598.1.1 by Super-User
Fixed solaris build crap.
40
extern "C"
1085.1.2 by Monty Taylor
Fixed -Wmissing-declarations
41
pthread_handler_t run_task(void *p);
42
43
602 by Brian Aker
Merge in Monty's work for Solaris Sun Studio
44
pthread_handler_t run_task(void *p)
1 by brian
clean slate
45
{
46
  int fd;
47
  char *buffer;
48
  size_t offset;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
49
  azio_stream *s= (azio_stream *)p;
1 by brian
clean slate
50
51
  my_thread_init();
52
53
  while (1)
54
  {
55
    pthread_mutex_lock(&s->container.thresh_mutex);
56
    while (s->container.ready == AZ_THREAD_FINISHED)
57
    {
58
      pthread_cond_wait(&s->container.threshhold, &s->container.thresh_mutex);
59
    }
60
    offset= s->container.offset;
61
    fd= s->container.fd;
598.1.1 by Super-User
Fixed solaris build crap.
62
    buffer= (char *)s->container.buffer;
1 by brian
clean slate
63
    pthread_mutex_unlock(&s->container.thresh_mutex);
64
65
    if (s->container.ready == AZ_THREAD_DEAD)
66
      break;
67
53.2.33 by Monty Taylor
More warnings fixes.
68
    s->container.read_size= pread((int)fd, (void *)buffer,
69
                                  (size_t)AZ_BUFSIZE_READ, (off_t)offset);
1 by brian
clean slate
70
71
    pthread_mutex_lock(&s->container.thresh_mutex);
53.2.33 by Monty Taylor
More warnings fixes.
72
    s->container.ready= AZ_THREAD_FINISHED;
1 by brian
clean slate
73
    pthread_mutex_unlock(&s->container.thresh_mutex);
74
  }
75
76
  my_thread_end();
77
78
  return 0;
79
}
80
81
static void azio_kill(azio_stream *s)
82
{
83
  pthread_mutex_lock(&s->container.thresh_mutex);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
84
  s->container.ready= AZ_THREAD_DEAD;
1 by brian
clean slate
85
  pthread_mutex_unlock(&s->container.thresh_mutex);
86
87
  pthread_cond_signal(&s->container.threshhold);
598.1.1 by Super-User
Fixed solaris build crap.
88
  pthread_join(s->container.mainthread, NULL);
1 by brian
clean slate
89
}
90
91
static size_t azio_return(azio_stream *s)
92
{
93
  return s->container.read_size;
94
}
95
96
/*
97
  Worried about spin?
98
  Don't be. In tests it never has spun more then 1 times.
99
*/
100
101
static az_thread_type azio_ready(azio_stream *s)
102
{
103
  az_thread_type temp;
104
105
  while (1)
106
  {
107
    pthread_mutex_lock(&s->container.thresh_mutex);
108
    temp= s->container.ready;
109
    pthread_mutex_unlock(&s->container.thresh_mutex);
110
111
    if (temp == AZ_THREAD_FINISHED || temp == AZ_THREAD_DEAD)
112
      break;
113
  }
114
115
  return temp;
116
}
117
118
static int azio_start(azio_stream *s)
119
{
120
  int rc= 0;
121
  pthread_attr_t attr;          /* Thread attributes */
122
123
  pthread_attr_init(&attr);
124
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
125
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
126
  s->container.ready= AZ_THREAD_FINISHED;
1 by brian
clean slate
127
128
  /* If we don't create a thread, signal the caller */
129
  if (pthread_create(&s->container.mainthread, &attr, run_task,
130
                     (void *)s) != 0)
131
    rc= 1;
132
133
  pthread_attr_destroy(&attr);
134
135
  return rc;
136
}
137
138
static int azio_read(azio_stream *s)
139
{
140
  pthread_mutex_lock(&s->container.thresh_mutex);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
141
  s->container.ready= AZ_THREAD_ACTIVE;
1 by brian
clean slate
142
  pthread_mutex_unlock(&s->container.thresh_mutex);
143
  pthread_cond_broadcast(&s->container.threshhold);
144
145
  return 0;
146
}
147
148
/* ===========================================================================
149
  Opens a gzip (.gz) file for reading or writing. The mode parameter
150
  is as in fopen ("rb" or "wb"). The file is given either by file descriptor
151
  or path name (if fd == -1).
152
  az_open returns NULL if the file could not be opened or if there was
153
  insufficient memory to allocate the (de)compression state; errno
154
  can be checked to distinguish the two cases (if errno is zero, the
155
  zlib error is Z_MEM_ERROR).
156
*/
157
int azopen(azio_stream *s, const char *path, int Flags, az_method method)
158
{
159
  int err;
160
  int level = Z_DEFAULT_COMPRESSION ; /* compression level */
161
  int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
162
  File fd= -1;
163
164
  memset(s, 0, sizeof(azio_stream));
165
166
  s->stream.zalloc = (alloc_func)0;
167
  s->stream.zfree = (free_func)0;
168
  s->stream.opaque = (voidpf)0;
169
170
171
  s->container.offset= 0;
172
  s->container.buffer= (void *)s->buffer1;
173
  s->container.ready= AZ_THREAD_FINISHED;
174
175
  s->inbuf= s->buffer1;
176
  s->stream.next_in = s->inbuf;
177
  s->stream.next_out = s->outbuf;
178
  s->z_err = Z_OK;
179
  s->back = EOF;
180
  s->crc = crc32(0L, Z_NULL, 0);
181
  s->mode = 'r';
182
  s->version = (unsigned char)az_magic[1]; /* this needs to be a define to version */
183
  s->version = (unsigned char)az_magic[2]; /* minor version */
184
  s->method= method;
185
186
  /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
187
    We do our own version of append by nature.
1 by brian
clean slate
188
    We must always have write access to take card of the header.
189
  */
51.3.8 by Jay Pipes
Removed DBUG from CSV and Blackhole storage engines
190
  assert(Flags | O_APPEND);
191
  assert(Flags | O_WRONLY);
1 by brian
clean slate
192
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
193
  if (Flags & O_RDWR)
1 by brian
clean slate
194
    s->mode = 'w';
195
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
196
  if (s->mode == 'w')
1 by brian
clean slate
197
  {
198
    err = deflateInit2(&(s->stream), level,
199
                       Z_DEFLATED, -MAX_WBITS, 8, strategy);
200
    /* windowBits is passed < 0 to suppress zlib header */
201
202
    s->stream.next_out = s->outbuf;
203
    if (err != Z_OK)
204
    {
205
      destroy(s);
206
      return Z_NULL;
207
    }
208
  } else {
209
    /* Threads are only used when we are running with azio */
210
    s->stream.next_in  = s->inbuf;
211
212
    err = inflateInit2(&(s->stream), -MAX_WBITS);
213
    /* windowBits is passed < 0 to tell that there is no zlib header.
214
     * Note that in this case inflate *requires* an extra "dummy" byte
215
     * after the compressed stream in order to complete decompression and
216
     * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
217
     * present after the compressed stream.
218
   */
219
    if (err != Z_OK)
220
    {
221
      destroy(s);
222
      return Z_NULL;
223
    }
224
  }
225
  s->stream.avail_out = AZ_BUFSIZE_WRITE;
226
227
  errno = 0;
228
  s->file = fd < 0 ? my_open(path, Flags, MYF(0)) : fd;
229
#ifdef AZIO_AIO
230
  s->container.fd= s->file;
231
#endif
232
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
233
  if (s->file < 0 )
1 by brian
clean slate
234
  {
235
    destroy(s);
236
    return Z_NULL;
237
  }
238
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
239
  if (Flags & O_CREAT || Flags & O_TRUNC)
1 by brian
clean slate
240
  {
241
    s->rows= 0;
242
    s->forced_flushes= 0;
243
    s->shortest_row= 0;
244
    s->longest_row= 0;
245
    s->auto_increment= 0;
246
    s->check_point= 0;
247
    s->comment_start_pos= 0;
248
    s->comment_length= 0;
249
    s->frm_start_pos= 0;
250
    s->frm_length= 0;
251
    s->dirty= 1; /* We create the file dirty */
252
    s->start = AZHEADER_SIZE + AZMETA_BUFFER_SIZE;
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
253
    if(write_header(s))
254
      return Z_NULL;
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
255
    s->pos= (size_t)lseek(s->file, 0, SEEK_END);
1 by brian
clean slate
256
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
257
  else if (s->mode == 'w')
1 by brian
clean slate
258
  {
481 by Brian Aker
Remove all of uchar.
259
    unsigned char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
260
    const ssize_t read_size= AZHEADER_SIZE + AZMETA_BUFFER_SIZE;
261
    if(pread(s->file, buffer, read_size, 0) < read_size)
262
      return Z_NULL;
1 by brian
clean slate
263
    read_header(s, buffer);
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
264
    s->pos= (size_t)lseek(s->file, 0, SEEK_END);
1 by brian
clean slate
265
  }
266
  else
267
  {
268
    check_header(s); /* skip the .az header */
269
  }
270
271
  switch (s->method)
272
  {
273
  case AZ_METHOD_AIO:
274
    azio_enable_aio(s);
275
    break;
276
  case AZ_METHOD_BLOCK:
277
  case AZ_METHOD_MAX:
278
    break;
279
  }
280
281
  return 1;
282
}
283
284
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
285
int write_header(azio_stream *s)
1 by brian
clean slate
286
{
287
  char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
288
  char *ptr= buffer;
289
290
  s->block_size= AZ_BUFSIZE_WRITE;
291
  s->version = (unsigned char)az_magic[1];
292
  s->minor_version = (unsigned char)az_magic[2];
293
294
295
  /* Write a very simple .az header: */
296
  memset(buffer, 0, AZHEADER_SIZE + AZMETA_BUFFER_SIZE);
297
  *(ptr + AZ_MAGIC_POS)= az_magic[0];
298
  *(ptr + AZ_VERSION_POS)= (unsigned char)s->version;
299
  *(ptr + AZ_MINOR_VERSION_POS)= (unsigned char)s->minor_version;
300
  *(ptr + AZ_BLOCK_POS)= (unsigned char)(s->block_size/1024); /* Reserved for block size */
301
  *(ptr + AZ_STRATEGY_POS)= (unsigned char)Z_DEFAULT_STRATEGY; /* Compression Type */
302
303
  int4store(ptr + AZ_FRM_POS, s->frm_start_pos); /* FRM Block */
304
  int4store(ptr + AZ_FRM_LENGTH_POS, s->frm_length); /* FRM Block */
305
  int4store(ptr + AZ_COMMENT_POS, s->comment_start_pos); /* COMMENT Block */
306
  int4store(ptr + AZ_COMMENT_LENGTH_POS, s->comment_length); /* COMMENT Block */
307
  int4store(ptr + AZ_META_POS, 0); /* Meta Block */
308
  int4store(ptr + AZ_META_LENGTH_POS, 0); /* Meta Block */
481.1.2 by Monty Taylor
Replaced all unsigned long long with uint64_t.
309
  int8store(ptr + AZ_START_POS, (uint64_t)s->start); /* Start of Data Block Index Block */
310
  int8store(ptr + AZ_ROW_POS, (uint64_t)s->rows); /* Start of Data Block Index Block */
311
  int8store(ptr + AZ_FLUSH_POS, (uint64_t)s->forced_flushes); /* Start of Data Block Index Block */
312
  int8store(ptr + AZ_CHECK_POS, (uint64_t)s->check_point); /* Start of Data Block Index Block */
313
  int8store(ptr + AZ_AUTOINCREMENT_POS, (uint64_t)s->auto_increment); /* Start of Data Block Index Block */
1 by brian
clean slate
314
  int4store(ptr+ AZ_LONGEST_POS , s->longest_row); /* Longest row */
315
  int4store(ptr+ AZ_SHORTEST_POS, s->shortest_row); /* Shorest row */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
316
  int4store(ptr+ AZ_FRM_POS,
1 by brian
clean slate
317
            AZHEADER_SIZE + AZMETA_BUFFER_SIZE); /* FRM position */
318
  *(ptr + AZ_DIRTY_POS)= (unsigned char)s->dirty; /* Start of Data Block Index Block */
319
320
  /* Always begin at the begining, and end there as well */
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
321
  const ssize_t write_size= AZHEADER_SIZE + AZMETA_BUFFER_SIZE;
322
  if(pwrite(s->file, (unsigned char*) buffer, write_size, 0)!=write_size)
323
    return -1;
324
325
  return 0;
1 by brian
clean slate
326
}
327
328
/* ===========================================================================
329
  Read a byte from a azio_stream; update next_in and avail_in. Return EOF
330
  for end of file.
331
  IN assertion: the stream s has been sucessfully opened for reading.
332
*/
598.1.1 by Super-User
Fixed solaris build crap.
333
int get_byte(azio_stream *s)
1 by brian
clean slate
334
{
335
  if (s->z_eof) return EOF;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
336
  if (s->stream.avail_in == 0)
1 by brian
clean slate
337
  {
338
    errno = 0;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
339
    if (s->stream.avail_in == 0)
1 by brian
clean slate
340
    {
341
      s->z_eof = 1;
342
      return EOF;
343
    }
344
    else if (s->stream.avail_in == (uInt) -1)
345
    {
346
      s->z_eof= 1;
347
      s->z_err= Z_ERRNO;
348
      return EOF;
349
    }
350
    s->stream.next_in = s->inbuf;
351
  }
352
  s->stream.avail_in--;
353
  return *(s->stream.next_in)++;
354
}
355
356
/* ===========================================================================
357
  Check the gzip header of a azio_stream opened for reading.
358
  IN assertion: the stream s has already been created sucessfully;
359
  s->stream.avail_in is zero for the first time, but may be non-zero
360
  for concatenated .gz files.
361
*/
362
void check_header(azio_stream *s)
363
{
364
  uInt len;
365
366
  /* Assure two bytes in the buffer so we can peek ahead -- handle case
367
    where first byte of header is at the end of the buffer after the last
368
    gzip segment */
369
  len = s->stream.avail_in;
370
  if (len < 2) {
371
    if (len) s->inbuf[0] = s->stream.next_in[0];
372
    errno = 0;
481 by Brian Aker
Remove all of uchar.
373
    len = (uInt)pread(s->file, (unsigned char *)s->inbuf + len, AZ_BUFSIZE_READ >> len, s->pos);
1 by brian
clean slate
374
    s->pos+= len;
375
    if (len == (uInt)-1) s->z_err = Z_ERRNO;
376
    s->stream.avail_in += len;
377
    s->stream.next_in = s->inbuf;
378
  }
379
380
  /* Now we check the actual header */
381
  if ( s->stream.next_in[0] == az_magic[0]  && s->stream.next_in[1] == az_magic[1])
382
  {
383
    unsigned char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
384
385
    for (len = 0; len < (AZHEADER_SIZE + AZMETA_BUFFER_SIZE); len++)
386
      buffer[len]= get_byte(s);
387
    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
388
    read_header(s, buffer);
389
    for (; len < s->start; len++)
390
      get_byte(s);
391
  }
392
  else
393
  {
394
    s->z_err = Z_OK;
395
396
    return;
397
  }
398
}
399
400
void read_header(azio_stream *s, unsigned char *buffer)
401
{
402
  if (buffer[0] == az_magic[0]  && buffer[1] == az_magic[1])
403
  {
404
    s->version= (unsigned int)buffer[AZ_VERSION_POS];
405
    s->minor_version= (unsigned int)buffer[AZ_MINOR_VERSION_POS];
406
    s->block_size= 1024 * buffer[AZ_BLOCK_POS];
407
    s->start= (size_t)uint8korr(buffer + AZ_START_POS);
481.1.2 by Monty Taylor
Replaced all unsigned long long with uint64_t.
408
    s->rows= (uint64_t)uint8korr(buffer + AZ_ROW_POS);
409
    s->check_point= (uint64_t)uint8korr(buffer + AZ_CHECK_POS);
410
    s->forced_flushes= (uint64_t)uint8korr(buffer + AZ_FLUSH_POS);
411
    s->auto_increment= (uint64_t)uint8korr(buffer + AZ_AUTOINCREMENT_POS);
1 by brian
clean slate
412
    s->longest_row= (unsigned int)uint4korr(buffer + AZ_LONGEST_POS);
413
    s->shortest_row= (unsigned int)uint4korr(buffer + AZ_SHORTEST_POS);
414
    s->frm_start_pos= (unsigned int)uint4korr(buffer + AZ_FRM_POS);
415
    s->frm_length= (unsigned int)uint4korr(buffer + AZ_FRM_LENGTH_POS);
416
    s->comment_start_pos= (unsigned int)uint4korr(buffer + AZ_COMMENT_POS);
417
    s->comment_length= (unsigned int)uint4korr(buffer + AZ_COMMENT_LENGTH_POS);
418
    s->dirty= (unsigned int)buffer[AZ_DIRTY_POS];
419
  }
420
  else
421
  {
422
    s->z_err = Z_OK;
423
    return;
424
  }
425
}
426
427
/* ===========================================================================
428
 * Cleanup then free the given azio_stream. Return a zlib error code.
429
 Try freeing in the reverse order of allocations.
430
 */
598.1.1 by Super-User
Fixed solaris build crap.
431
int destroy (azio_stream *s)
1 by brian
clean slate
432
{
433
  int err = Z_OK;
434
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
435
  if (s->stream.state != NULL)
1 by brian
clean slate
436
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
437
    if (s->mode == 'w')
1 by brian
clean slate
438
    {
439
      err = deflateEnd(&(s->stream));
440
      my_sync(s->file, MYF(0));
441
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
442
    else if (s->mode == 'r')
1 by brian
clean slate
443
      err = inflateEnd(&(s->stream));
444
  }
445
446
  do_aio_cleanup(s);
447
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
448
  if (s->file > 0 && my_close(s->file, MYF(0)))
1 by brian
clean slate
449
      err = Z_ERRNO;
450
451
  s->file= -1;
452
453
  if (s->z_err < 0) err = s->z_err;
454
455
  return err;
456
}
457
458
/* ===========================================================================
459
  Reads the given number of uncompressed bytes from the compressed file.
460
  azread returns the number of bytes actually read (0 for end of file).
461
*/
462
unsigned int azread_internal( azio_stream *s, voidp buf, unsigned int len, int *error)
463
{
464
  Bytef *start = (Bytef*)buf; /* starting point for crc computation */
465
  Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
466
  *error= 0;
467
468
  if (s->mode != 'r')
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
469
  {
1 by brian
clean slate
470
    *error= Z_STREAM_ERROR;
471
    return 0;
472
  }
473
474
  if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
475
  {
1 by brian
clean slate
476
    *error= s->z_err;
477
    return 0;
478
  }
479
480
  if (s->z_err == Z_STREAM_END)  /* EOF */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
481
  {
1 by brian
clean slate
482
    return 0;
483
  }
484
485
  next_out = (Byte*)buf;
486
  s->stream.next_out = (Bytef*)buf;
487
  s->stream.avail_out = len;
488
489
  if (s->stream.avail_out && s->back != EOF) {
490
    *next_out++ = s->back;
491
    s->stream.next_out++;
492
    s->stream.avail_out--;
493
    s->back = EOF;
494
    s->out++;
495
    start++;
496
    if (s->last) {
497
      s->z_err = Z_STREAM_END;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
498
      {
1 by brian
clean slate
499
        return 1;
500
      }
501
    }
502
  }
503
504
  while (s->stream.avail_out != 0) {
505
506
    if (s->stream.avail_in == 0 && !s->z_eof) {
507
508
      errno = 0;
509
      get_block(s);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
510
      if (s->stream.avail_in == 0)
1 by brian
clean slate
511
      {
512
        s->z_eof = 1;
513
      }
514
      s->stream.next_in = (Bytef *)s->inbuf;
515
    }
516
    s->in += s->stream.avail_in;
517
    s->out += s->stream.avail_out;
518
    s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
519
    s->in -= s->stream.avail_in;
520
    s->out -= s->stream.avail_out;
521
522
    if (s->z_err == Z_STREAM_END) {
523
      /* Check CRC and original size */
524
      s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
525
      start = s->stream.next_out;
526
527
      if (getLong(s) != s->crc) {
528
        s->z_err = Z_DATA_ERROR;
529
      } else {
530
        (void)getLong(s);
531
        /* The uncompressed length returned by above getlong() may be
532
         * different from s->out in case of concatenated .gz files.
533
         * Check for such files:
534
       */
535
        check_header(s);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
536
        if (s->z_err == Z_OK)
1 by brian
clean slate
537
        {
538
          inflateReset(&(s->stream));
539
          s->crc = crc32(0L, Z_NULL, 0);
540
        }
541
      }
542
    }
543
    if (s->z_err != Z_OK || s->z_eof) break;
544
  }
545
  s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
546
547
  if (len == s->stream.avail_out &&
548
      (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
549
  {
550
    *error= s->z_err;
551
552
    return 0;
553
  }
554
555
  return (len - s->stream.avail_out);
556
}
557
558
/* ===========================================================================
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
559
  Experimental Interface. We abstract out a concecpt of rows
1 by brian
clean slate
560
*/
561
size_t azwrite_row(azio_stream *s, void *buf, unsigned int len)
562
{
563
  size_t length;
564
  /* First we write length */
565
  length= azwrite(s, &len, sizeof(unsigned int));
566
567
  if (length != sizeof(unsigned int))
568
    return length;
569
570
  /* Now we write the actual data */
571
  length= (size_t)azwrite(s, buf, len);
572
573
  if (length > 0)
574
    s->rows++;
575
576
  if (len > s->longest_row)
577
    s->longest_row= len;
578
579
  if (len < s->shortest_row || !(s->shortest_row))
580
    s->shortest_row= len;
581
582
  return length;
583
}
584
585
size_t azread_row(azio_stream *s, int *error)
586
{
587
  unsigned int row_length; /* Currently we are limited to this size for rows */
588
  char buffer[sizeof(unsigned int)];
589
  char *new_ptr;
590
  size_t read;
591
592
  read= azread_internal(s, buffer, sizeof(unsigned int), error);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
593
1 by brian
clean slate
594
  /* On error the return value will be zero as well */
595
  if (read == 0)
596
    return read;
597
  memcpy(&row_length, buffer, sizeof(unsigned int));
598
599
  new_ptr= (char *)realloc(s->row_ptr, (sizeof(char) * row_length));
600
601
  if (!new_ptr)
590.2.11 by Monty
Fixed some negative to size_t casts.
602
    return SIZE_MAX;
1 by brian
clean slate
603
604
  s->row_ptr= new_ptr;
605
606
  /* TODO We should now adjust the length... */
607
  read= azread_internal(s, (voidp)s->row_ptr, row_length, error);
608
609
  return read;
610
}
611
612
613
/* ===========================================================================
614
  Writes the given number of uncompressed bytes into the compressed file.
615
  azwrite returns the number of bytes actually written (0 in case of error).
616
*/
617
static unsigned int azwrite(azio_stream *s, void *buf, unsigned int len)
618
{
619
  s->stream.next_in = (Bytef*)buf;
620
  s->stream.avail_in = len;
621
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
622
  while (s->stream.avail_in != 0)
1 by brian
clean slate
623
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
624
    if (s->stream.avail_out == 0)
1 by brian
clean slate
625
    {
626
627
      s->stream.next_out = s->outbuf;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
628
      if (pwrite(s->file, (unsigned char *)s->outbuf, AZ_BUFSIZE_WRITE, s->pos) != AZ_BUFSIZE_WRITE)
1 by brian
clean slate
629
      {
630
        s->z_err = Z_ERRNO;
631
        break;
632
      }
633
      s->pos+= AZ_BUFSIZE_WRITE;
634
      s->stream.avail_out = AZ_BUFSIZE_WRITE;
635
    }
636
    s->in += s->stream.avail_in;
637
    s->out += s->stream.avail_out;
638
    s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
639
    s->in -= s->stream.avail_in;
640
    s->out -= s->stream.avail_out;
641
    if (s->z_err != Z_OK) break;
642
  }
643
  s->crc = crc32(s->crc, (const Bytef *)buf, len);
644
645
  return (unsigned int)(len - s->stream.avail_in);
646
}
647
648
649
/* ===========================================================================
650
  Flushes all pending output into the compressed file. The parameter
651
  flush is as in the deflate() function.
652
*/
653
int do_flush (azio_stream *s, int flush)
654
{
655
  uInt len;
656
  int done = 0;
657
  size_t afterwrite_pos;
658
659
  if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
660
661
  s->stream.avail_in = 0; /* should be zero already anyway */
662
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
663
  for (;;)
1 by brian
clean slate
664
  {
665
    len = AZ_BUFSIZE_WRITE - s->stream.avail_out;
666
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
667
    if (len != 0)
1 by brian
clean slate
668
    {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
669
      if ((uInt)pwrite(s->file, (unsigned char *)s->outbuf, len, s->pos) != len)
1 by brian
clean slate
670
      {
671
        s->z_err = Z_ERRNO;
672
        assert(0);
673
        return Z_ERRNO;
674
      }
675
      s->pos+= len;
676
      s->check_point= s->pos;
677
      s->stream.next_out = s->outbuf;
678
      s->stream.avail_out = AZ_BUFSIZE_WRITE;
679
    }
680
    if (done) break;
681
    s->out += s->stream.avail_out;
682
    s->z_err = deflate(&(s->stream), flush);
683
    s->out -= s->stream.avail_out;
684
685
    /* Ignore the second of two consecutive flushes: */
686
    if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
687
688
    /* deflate has finished flushing only when it hasn't used up
689
     * all the available space in the output buffer:
690
   */
691
    done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
692
693
    if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
694
  }
695
696
  if (flush == Z_FINISH)
697
    s->dirty= AZ_STATE_CLEAN; /* Mark it clean, we should be good now */
698
  else
699
    s->dirty= AZ_STATE_SAVED; /* Mark it clean, we should be good now */
700
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
701
  afterwrite_pos= (size_t)lseek(s->file, 0, SEEK_CUR);
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
702
  if(write_header(s))
703
    return Z_ERRNO;
1 by brian
clean slate
704
705
  return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
706
}
707
708
static unsigned int azio_enable_aio(azio_stream *s)
709
{
398.1.10 by Monty Taylor
Actually removed VOID() this time.
710
  pthread_cond_init(&s->container.threshhold, NULL);
711
  pthread_mutex_init(&s->container.thresh_mutex, NULL);
1 by brian
clean slate
712
  azio_start(s);
713
714
  return 0;
715
}
716
53.2.33 by Monty Taylor
More warnings fixes.
717
static void azio_disable_aio(azio_stream *s)
1 by brian
clean slate
718
{
719
  azio_kill(s);
720
398.1.10 by Monty Taylor
Actually removed VOID() this time.
721
  pthread_mutex_destroy(&s->container.thresh_mutex);
722
  pthread_cond_destroy(&s->container.threshhold);
1 by brian
clean slate
723
724
  s->method= AZ_METHOD_BLOCK;
725
}
726
598.1.1 by Super-User
Fixed solaris build crap.
727
int ZEXPORT azflush (azio_stream *s,int flush)
1 by brian
clean slate
728
{
729
  int err;
730
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
731
  if (s->mode == 'r')
1 by brian
clean slate
732
  {
733
    unsigned char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
734
    const ssize_t read_size= AZHEADER_SIZE + AZMETA_BUFFER_SIZE;
735
    if(pread(s->file, (unsigned char*) buffer, read_size, 0)!=read_size)
736
      return Z_ERRNO;
1 by brian
clean slate
737
    read_header(s, buffer); /* skip the .az header */
738
    azrewind(s);
739
740
    return Z_OK;
741
  }
742
  else
743
  {
744
    s->forced_flushes++;
745
    err= do_flush(s, flush);
746
747
    if (err) return err;
748
    my_sync(s->file, MYF(0));
749
    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
750
  }
751
}
752
753
/* ===========================================================================
754
  Initiazliaze for reading
755
*/
756
int azread_init(azio_stream *s)
757
{
758
  int returnable;
759
760
  /* This will reset any aio reads */
761
  returnable= azrewind(s);
762
763
  if (returnable == -1)
764
    return returnable;
765
766
  /* Put one in the chamber */
767
  if (s->method != AZ_METHOD_BLOCK)
768
  {
769
    do_aio_cleanup(s);
770
    s->container.offset= s->pos;
771
    s->container.buffer= (unsigned char *)s->buffer1;
772
    azio_read(s);
773
    s->aio_inited= 1;
774
  }
775
776
777
  return returnable;
778
}
779
780
/* ===========================================================================
781
  Rewinds input file.
782
*/
598.1.1 by Super-User
Fixed solaris build crap.
783
int azrewind (azio_stream *s)
1 by brian
clean slate
784
{
785
  if (s == NULL || s->mode != 'r') return -1;
786
787
#ifdef AZIO_AIO
788
  do_aio_cleanup(s);
789
#endif
790
  s->z_err = Z_OK;
791
  s->z_eof = 0;
792
  s->back = EOF;
793
  s->stream.avail_in = 0;
794
  s->stream.next_in = (Bytef *)s->inbuf;
795
  s->crc = crc32(0L, Z_NULL, 0);
796
  (void)inflateReset(&s->stream);
797
  s->in = 0;
798
  s->out = 0;
799
  s->aio_inited= 0; /* Reset the AIO reader */
800
  s->pos= s->start;
801
  return 0;
802
}
803
804
/* ===========================================================================
805
  Sets the starting position for the next azread or azwrite on the given
806
  compressed file. The offset represents a number of bytes in the
807
  azseek returns the resulting offset location as measured in bytes from
808
  the beginning of the uncompressed stream, or -1 in case of error.
809
  SEEK_END is not implemented, returns error.
810
  In this version of the library, azseek can be extremely slow.
811
*/
598.1.1 by Super-User
Fixed solaris build crap.
812
size_t azseek (azio_stream *s, size_t offset, int whence)
1 by brian
clean slate
813
{
814
815
  if (s == NULL || whence == SEEK_END ||
816
      s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
590.2.11 by Monty
Fixed some negative to size_t casts.
817
    return SIZE_MAX;
1 by brian
clean slate
818
  }
819
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
820
  if (s->mode == 'w')
1 by brian
clean slate
821
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
822
    if (whence == SEEK_SET)
1 by brian
clean slate
823
      offset -= s->in;
824
825
    /* At this point, offset is the number of zero bytes to write. */
826
    /* There was a zmemzero here if inbuf was null -Brian */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
827
    while (offset > 0)
1 by brian
clean slate
828
    {
829
      uInt size = AZ_BUFSIZE_READ;
830
      if (offset < AZ_BUFSIZE_READ) size = (uInt)offset;
831
832
      size = azwrite(s, s->inbuf, size);
590.2.11 by Monty
Fixed some negative to size_t casts.
833
      if (size == 0)
834
        return SIZE_MAX;
1 by brian
clean slate
835
836
      offset -= size;
837
    }
838
    return s->in;
839
  }
840
  /* Rest of function is for reading only */
841
842
  /* compute absolute position */
843
  if (whence == SEEK_CUR) {
844
    offset += s->out;
845
  }
846
847
  /* For a negative seek, rewind and use positive seek */
848
  if (offset >= s->out) {
849
    offset -= s->out;
850
  } else if (azrewind(s)) {
590.2.11 by Monty
Fixed some negative to size_t casts.
851
    return SIZE_MAX;
1 by brian
clean slate
852
  }
853
  /* offset is now the number of bytes to skip. */
854
855
  if (offset && s->back != EOF) {
856
    s->back = EOF;
857
    s->out++;
858
    offset--;
859
    if (s->last) s->z_err = Z_STREAM_END;
860
  }
861
  while (offset > 0)  {
862
    int error;
863
    unsigned int size = AZ_BUFSIZE_WRITE;
864
    if (offset < AZ_BUFSIZE_WRITE) size = (int)offset;
865
866
    size = azread_internal(s, s->outbuf, size, &error);
590.2.11 by Monty
Fixed some negative to size_t casts.
867
    if (error < 0) return SIZE_MAX;
1 by brian
clean slate
868
    offset -= size;
869
  }
870
  return s->out;
871
}
872
873
/* ===========================================================================
874
  Returns the starting position for the next azread or azwrite on the
875
  given compressed file. This position represents a number of bytes in the
876
  uncompressed data stream.
877
*/
598.1.1 by Super-User
Fixed solaris build crap.
878
size_t ZEXPORT aztell (azio_stream *file)
1 by brian
clean slate
879
{
880
  return azseek(file, 0L, SEEK_CUR);
881
}
882
883
884
/* ===========================================================================
885
  Outputs a long in LSB order to the given file
886
*/
887
void putLong (azio_stream *s, uLong x)
888
{
889
  int n;
481 by Brian Aker
Remove all of uchar.
890
  unsigned char buffer[1];
1 by brian
clean slate
891
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
892
  for (n = 0; n < 4; n++)
1 by brian
clean slate
893
  {
894
    buffer[0]= (int)(x & 0xff);
1090.1.3 by Monty Taylor
Removed dangerous asserts... mainly to upset Stewart.
895
    size_t ret= pwrite(s->file, buffer, 1, s->pos);
896
    assert(ret == 1);
1 by brian
clean slate
897
    s->pos++;
898
    x >>= 8;
899
  }
900
}
901
902
/* ===========================================================================
903
  Reads a long in LSB order from the given azio_stream. Sets z_err in case
904
  of error.
905
*/
906
uLong getLong (azio_stream *s)
907
{
908
  uLong x = (uLong)get_byte(s);
909
  int c;
910
911
  x += ((uLong)get_byte(s))<<8;
912
  x += ((uLong)get_byte(s))<<16;
913
  c = get_byte(s);
914
  if (c == EOF) s->z_err = Z_DATA_ERROR;
915
  x += ((uLong)c)<<24;
916
  return x;
917
}
918
919
/* ===========================================================================
920
  Flushes all pending output if necessary, closes the compressed file
921
  and deallocates all the (de)compression state.
922
*/
923
int azclose (azio_stream *s)
924
{
925
  int returnable;
926
927
  if (s == NULL) return Z_STREAM_ERROR;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
928
1 by brian
clean slate
929
  if (s->file < 1) return Z_OK;
930
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
931
  if (s->mode == 'w')
1 by brian
clean slate
932
  {
933
    if (do_flush(s, Z_FINISH) != Z_OK)
934
      return destroy(s);
935
936
    putLong(s, s->crc);
937
    putLong(s, (uLong)(s->in & 0xffffffff));
938
    s->dirty= AZ_STATE_CLEAN;
939
    write_header(s);
940
  }
941
942
  returnable= destroy(s);
943
944
  switch (s->method)
945
  {
946
  case AZ_METHOD_AIO:
947
    azio_disable_aio(s);
948
    break;
949
  case AZ_METHOD_BLOCK:
950
  case AZ_METHOD_MAX:
951
    break;
952
  }
953
954
  /* If we allocated memory for row reading, now free it */
955
  if (s->row_ptr)
956
    free(s->row_ptr);
957
958
  return returnable;
959
}
960
961
/*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
962
  Though this was added to support MySQL's FRM file, anything can be
1 by brian
clean slate
963
  stored in this location.
964
*/
965
int azwrite_frm(azio_stream *s, char *blob, unsigned int length)
966
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
967
  if (s->mode == 'r')
1 by brian
clean slate
968
    return 1;
969
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
970
  if (s->rows > 0)
1 by brian
clean slate
971
    return 1;
972
973
  s->frm_start_pos= (uint) s->start;
974
  s->frm_length= length;
975
  s->start+= length;
976
517 by Brian Aker
Fix for ssize_t to unsigned int (not a great fix... should compare with
977
  if (pwrite(s->file, (unsigned char*) blob, s->frm_length, s->frm_start_pos) != (ssize_t)s->frm_length)
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
978
    return 1;
1 by brian
clean slate
979
980
  write_header(s);
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
981
  s->pos= (size_t)lseek(s->file, 0, SEEK_END);
1 by brian
clean slate
982
983
  return 0;
984
}
985
986
int azread_frm(azio_stream *s, char *blob)
987
{
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
988
  ssize_t r= pread(s->file, (unsigned char*) blob,
989
                   s->frm_length, s->frm_start_pos);
517 by Brian Aker
Fix for ssize_t to unsigned int (not a great fix... should compare with
990
  if (r != (ssize_t)s->frm_length)
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
991
    return r;
1 by brian
clean slate
992
993
  return 0;
994
}
995
996
997
/*
998
  Simple comment field
999
*/
1000
int azwrite_comment(azio_stream *s, char *blob, unsigned int length)
1001
{
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1002
  if (s->mode == 'r')
1 by brian
clean slate
1003
    return 1;
1004
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1005
  if (s->rows > 0)
1 by brian
clean slate
1006
    return 1;
1007
1008
  s->comment_start_pos= (uint) s->start;
1009
  s->comment_length= length;
1010
  s->start+= length;
1011
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
1012
  ssize_t r= pwrite(s->file, (unsigned char*) blob,
1013
                    s->comment_length, s->comment_start_pos);
517 by Brian Aker
Fix for ssize_t to unsigned int (not a great fix... should compare with
1014
  if (r != (ssize_t)s->comment_length)
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
1015
    return r;
1 by brian
clean slate
1016
1017
  write_header(s);
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
1018
  s->pos= (size_t)lseek(s->file, 0, SEEK_END);
1 by brian
clean slate
1019
1020
  return 0;
1021
}
1022
1023
int azread_comment(azio_stream *s, char *blob)
1024
{
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
1025
  ssize_t r= pread(s->file, (unsigned char*) blob,
1026
                   s->comment_length, s->comment_start_pos);
517 by Brian Aker
Fix for ssize_t to unsigned int (not a great fix... should compare with
1027
  if (r != (ssize_t)s->comment_length)
512.1.3 by Stewart Smith
fix not checked return values for ARCHIVE's azio.c
1028
    return r;
1 by brian
clean slate
1029
1030
  return 0;
1031
}
1032
1033
#ifdef AZIO_AIO
1034
static void do_aio_cleanup(azio_stream *s)
1035
{
1036
  if (s->method == AZ_METHOD_BLOCK)
1037
    return;
1038
1039
  azio_ready(s);
1040
1041
}
1042
#endif
1043
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1044
/*
1 by brian
clean slate
1045
  Normally all IO goes through azio_read(), but in case of error or non-support
1046
  we make use of pread().
1047
*/
1048
static void get_block(azio_stream *s)
1049
{
1050
#ifdef AZIO_AIO
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1051
  if (s->method == AZ_METHOD_AIO && s->mode == 'r'
1 by brian
clean slate
1052
      && s->pos < s->check_point
1053
      && s->aio_inited)
1054
  {
1055
    azio_ready(s);
1056
    s->stream.avail_in= (unsigned int)azio_return(s);
1057
    if ((int)(s->stream.avail_in) == -1)
1058
      goto use_pread;
1059
    else if ((int)(s->stream.avail_in) == 0)
1060
    {
1061
      s->aio_inited= 0;
1062
      return;
1063
    }
1064
    s->pos+= s->stream.avail_in;
1065
    s->inbuf= (Byte *)s->container.buffer;
1066
    /* We only aio_read when we know there is more data to be read */
1067
    if (s->pos >= s->check_point)
1068
    {
1069
      s->aio_inited= 0;
1070
      return;
1071
    }
1072
    s->container.buffer= (s->container.buffer == s->buffer2) ? s->buffer1 : s->buffer2;
1073
    s->container.offset= s->pos;
1074
    azio_read(s);
1075
  }
1076
  else
1077
#endif
1078
  {
1079
#ifdef AZIO_AIO
1080
use_pread:
1081
#endif
481 by Brian Aker
Remove all of uchar.
1082
    s->stream.avail_in = (uInt)pread(s->file, (unsigned char *)s->inbuf,
53.2.33 by Monty Taylor
More warnings fixes.
1083
                                     AZ_BUFSIZE_READ, s->pos);
1 by brian
clean slate
1084
    s->pos+= s->stream.avail_in;
1085
  }
1086
}