~ubuntu-branches/ubuntu/trusty/libarchive/trusty

« back to all changes in this revision

Viewing changes to archive_write_set_compression_none.c

  • Committer: Bazaar Package Importer
  • Author(s): John Goerzen
  • Date: 2005-10-18 11:02:06 UTC
  • Revision ID: james.westby@ubuntu.com-20051018110206-akz0ys1qxoojy73o
Tags: upstream-1.02.036
ImportĀ upstreamĀ versionĀ 1.02.036

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003-2004 Tim Kientzle
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer
 
10
 *    in this position and unchanged.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 *
 
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
18
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 */
 
26
 
 
27
#include "archive_platform.h"
 
28
__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_none.c,v 1.8 2005/06/01 15:52:39 kientzle Exp $");
 
29
 
 
30
#include <errno.h>
 
31
#include <stdlib.h>
 
32
#include <string.h>
 
33
 
 
34
#include "archive.h"
 
35
#include "archive_private.h"
 
36
 
 
37
static int      archive_compressor_none_finish(struct archive *a);
 
38
static int      archive_compressor_none_init(struct archive *);
 
39
static int      archive_compressor_none_write(struct archive *, const void *,
 
40
                    size_t);
 
41
 
 
42
struct archive_none {
 
43
        char    *buffer;
 
44
        ssize_t  buffer_size;
 
45
        char    *next;          /* Current insert location */
 
46
        ssize_t  avail;         /* Free space left in buffer */
 
47
};
 
48
 
 
49
int
 
50
archive_write_set_compression_none(struct archive *a)
 
51
{
 
52
        __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_set_compression_none");
 
53
        a->compression_init = &archive_compressor_none_init;
 
54
        a->compression_code = ARCHIVE_COMPRESSION_NONE;
 
55
        a->compression_name = "none";
 
56
        return (0);
 
57
}
 
58
 
 
59
/*
 
60
 * Setup callback.
 
61
 */
 
62
static int
 
63
archive_compressor_none_init(struct archive *a)
 
64
{
 
65
        int ret;
 
66
        struct archive_none *state;
 
67
 
 
68
        a->compression_code = ARCHIVE_COMPRESSION_NONE;
 
69
        a->compression_name = "none";
 
70
 
 
71
        if (a->client_opener != NULL) {
 
72
                ret = (a->client_opener)(a, a->client_data);
 
73
                if (ret != 0)
 
74
                        return (ret);
 
75
        }
 
76
 
 
77
        state = (struct archive_none *)malloc(sizeof(*state));
 
78
        if (state == NULL) {
 
79
                archive_set_error(a, ENOMEM,
 
80
                    "Can't allocate data for output buffering");
 
81
                return (ARCHIVE_FATAL);
 
82
        }
 
83
        memset(state, 0, sizeof(*state));
 
84
 
 
85
        state->buffer_size = a->bytes_per_block;
 
86
        state->buffer = malloc(state->buffer_size);
 
87
 
 
88
        if (state->buffer == NULL) {
 
89
                archive_set_error(a, ENOMEM,
 
90
                    "Can't allocate output buffer");
 
91
                free(state);
 
92
                return (ARCHIVE_FATAL);
 
93
        }
 
94
 
 
95
        state->next = state->buffer;
 
96
        state->avail = state->buffer_size;
 
97
 
 
98
        a->compression_data = state;
 
99
        a->compression_write = archive_compressor_none_write;
 
100
        a->compression_finish = archive_compressor_none_finish;
 
101
        return (ARCHIVE_OK);
 
102
}
 
103
 
 
104
/*
 
105
 * Write data to the stream.
 
106
 */
 
107
static int
 
108
archive_compressor_none_write(struct archive *a, const void *vbuff,
 
109
    size_t length)
 
110
{
 
111
        const char *buff;
 
112
        ssize_t remaining, to_copy;
 
113
        ssize_t bytes_written;
 
114
        struct archive_none *state;
 
115
 
 
116
        state = a->compression_data;
 
117
        buff = vbuff;
 
118
        if (a->client_writer == NULL) {
 
119
                archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
 
120
                    "No write callback is registered?  "
 
121
                    "This is probably an internal programming error.");
 
122
                return (ARCHIVE_FATAL);
 
123
        }
 
124
 
 
125
        remaining = length;
 
126
        while (remaining > 0) {
 
127
                /*
 
128
                 * If we have a full output block, write it and reset the
 
129
                 * output buffer.
 
130
                 */
 
131
                if (state->avail == 0) {
 
132
                        bytes_written = (a->client_writer)(a, a->client_data,
 
133
                            state->buffer, state->buffer_size);
 
134
                        if (bytes_written <= 0)
 
135
                                return (ARCHIVE_FATAL);
 
136
                        /* XXX TODO: if bytes_written < state->buffer_size */
 
137
                        a->raw_position += bytes_written;
 
138
                        state->next = state->buffer;
 
139
                        state->avail = state->buffer_size;
 
140
                }
 
141
 
 
142
                /* Now we have space in the buffer; copy new data into it. */
 
143
                to_copy = (remaining > state->avail) ?
 
144
                    state->avail : remaining;
 
145
                memcpy(state->next, buff, to_copy);
 
146
                state->next += to_copy;
 
147
                state->avail -= to_copy;
 
148
                buff += to_copy;
 
149
                remaining -= to_copy;
 
150
        }
 
151
        a->file_position += length;
 
152
        return (ARCHIVE_OK);
 
153
}
 
154
 
 
155
 
 
156
/*
 
157
 * Finish the compression.
 
158
 */
 
159
static int
 
160
archive_compressor_none_finish(struct archive *a)
 
161
{
 
162
        ssize_t block_length;
 
163
        ssize_t target_block_length;
 
164
        ssize_t bytes_written;
 
165
        int ret;
 
166
        int ret2;
 
167
        struct archive_none *state;
 
168
 
 
169
        state = a->compression_data;
 
170
        ret = ret2 = ARCHIVE_OK;
 
171
        if (a->client_writer == NULL) {
 
172
                archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
 
173
                    "No write callback is registered?  "
 
174
                    "This is probably an internal programming error.");
 
175
                return (ARCHIVE_FATAL);
 
176
        }
 
177
 
 
178
        /* If there's pending data, pad and write the last block */
 
179
        if (state->next != state->buffer) {
 
180
                block_length = state->buffer_size - state->avail;
 
181
 
 
182
                /* Tricky calculation to determine size of last block */
 
183
                target_block_length = block_length;
 
184
                if (a->bytes_in_last_block <= 0)
 
185
                        /* Default or Zero: pad to full block */
 
186
                        target_block_length = a->bytes_per_block;
 
187
                else
 
188
                        /* Round to next multiple of bytes_in_last_block. */
 
189
                        target_block_length = a->bytes_in_last_block *
 
190
                            ( (block_length + a->bytes_in_last_block - 1) /
 
191
                                a->bytes_in_last_block);
 
192
                if (target_block_length > a->bytes_per_block)
 
193
                        target_block_length = a->bytes_per_block;
 
194
                if (block_length < target_block_length) {
 
195
                        memset(state->next, 0,
 
196
                            target_block_length - block_length);
 
197
                        block_length = target_block_length;
 
198
                }
 
199
                bytes_written = (a->client_writer)(a, a->client_data,
 
200
                    state->buffer, block_length);
 
201
                if (bytes_written <= 0)
 
202
                        ret = ARCHIVE_FATAL;
 
203
                else {
 
204
                        a->raw_position += bytes_written;
 
205
                        ret = ARCHIVE_OK;
 
206
                }
 
207
        }
 
208
 
 
209
        /* Close the output */
 
210
        if (a->client_closer != NULL)
 
211
                ret2 = (a->client_closer)(a, a->client_data);
 
212
 
 
213
        free(state->buffer);
 
214
        free(state);
 
215
        a->compression_data = NULL;
 
216
 
 
217
        return (ret != ARCHIVE_OK ? ret : ret2);
 
218
}