Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
apk-tools
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
61
Issues
61
List
Boards
Labels
Service Desk
Milestones
Merge Requests
15
Merge Requests
15
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
alpine
apk-tools
Commits
aef0f036
Commit
aef0f036
authored
Nov 07, 2008
by
Timo Teräs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use zlib internally to decompress
parent
6967c28b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
469 additions
and
222 deletions
+469
-222
TODO
TODO
+1
-2
src/Makefile
src/Makefile
+3
-1
src/apk_archive.h
src/apk_archive.h
+12
-9
src/apk_io.h
src/apk_io.h
+38
-0
src/apk_package.h
src/apk_package.h
+2
-1
src/archive.c
src/archive.c
+66
-175
src/database.c
src/database.c
+19
-21
src/gunzip.c
src/gunzip.c
+93
-0
src/io.c
src/io.c
+221
-0
src/package.c
src/package.c
+14
-13
No files found.
TODO
View file @
aef0f036
- Internal gunzip (via lib) to speed up stuff, and avoid threads
- mmap() if possible for reading
- mmapped block stream from file
- Index/pkginfo reader: same field multiple times -> memleak
...
...
src/Makefile
View file @
aef0f036
...
...
@@ -15,6 +15,8 @@ apk_OBJS = \
package.o
\
archive.o
\
version.o
\
io.o
\
gunzip.o
\
blob.o
\
hash.o
\
md5.o
\
...
...
@@ -30,7 +32,7 @@ ALL_OBJS = $(apk_OBJS)
all
:
$(TARGETS)
apk
:
$(apk_OBJS)
$(CC)
$(LDFLAGS)
-o
$@
$^
$(LIBS)
$(CC)
$(LDFLAGS)
-o
$@
$^
$(LIBS)
/usr/lib/libz.a
clean
::
@
rm
-f
$(TARGETS)
$(ALL_OBJS)
...
...
src/apk_archive.h
View file @
aef0f036
...
...
@@ -13,8 +13,8 @@
#define APK_ARCHIVE
#include <sys/types.h>
#include <pthread.h>
#include "apk_blob.h"
#include "apk_io.h"
struct
apk_archive_entry
{
char
*
name
;
...
...
@@ -27,16 +27,19 @@ struct apk_archive_entry {
mode_t
mode
;
time_t
mtime
;
dev_t
device
;
int
read_fd
;
};
typedef
int
(
*
apk_archive_entry_parser
)(
struct
apk_archive_entry
*
entry
,
void
*
ctx
);
typedef
int
(
*
apk_archive_entry_parser
)(
void
*
ctx
,
const
struct
apk_archive_entry
*
ae
,
struct
apk_istream
*
istream
);
pid_t
apk_open_gz
(
int
*
fd
);
int
apk_parse_tar
(
int
fd
,
apk_archive_entry_parser
parser
,
void
*
ctx
);
int
apk_parse_tar_gz
(
int
fd
,
apk_archive_entry_parser
parser
,
void
*
ctx
);
apk_blob_t
apk_archive_entry_read
(
struct
apk_archive_entry
*
ae
);
int
apk_archive_entry_extract
(
struct
apk_archive_entry
*
ae
,
const
char
*
to
);
pthread_t
apk_checksum_and_tee
(
int
*
fd
,
void
*
ptr
);
struct
apk_istream
*
apk_gunzip_bstream
(
struct
apk_bstream
*
);
int
apk_parse_tar
(
struct
apk_istream
*
,
apk_archive_entry_parser
parser
,
void
*
ctx
);
int
apk_parse_tar_gz
(
struct
apk_bstream
*
,
apk_archive_entry_parser
parser
,
void
*
ctx
);
int
apk_archive_entry_extract
(
const
struct
apk_archive_entry
*
ae
,
struct
apk_istream
*
is
,
const
char
*
to
);
#endif
src/apk_io.h
0 → 100644
View file @
aef0f036
/* apk_io.h - Alpine Package Keeper (APK)
*
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
#ifndef APK_IO
#define APK_IO
#include "apk_defines.h"
#include "apk_blob.h"
struct
apk_istream
{
size_t
(
*
read
)(
void
*
stream
,
void
*
ptr
,
size_t
size
);
size_t
(
*
splice
)(
void
*
stream
,
int
fd
,
size_t
size
);
void
(
*
close
)(
void
*
stream
);
};
struct
apk_bstream
{
size_t
(
*
read
)(
void
*
stream
,
void
**
ptr
);
void
(
*
close
)(
void
*
stream
,
csum_t
csum
);
};
struct
apk_istream
*
apk_istream_from_fd
(
int
fd
);
struct
apk_istream
*
apk_istream_from_file
(
const
char
*
file
);
size_t
apk_istream_skip
(
struct
apk_istream
*
istream
,
size_t
size
);
size_t
apk_istream_splice
(
void
*
stream
,
int
fd
,
size_t
size
);
struct
apk_bstream
*
apk_bstream_from_istream
(
struct
apk_istream
*
istream
);
struct
apk_bstream
*
apk_bstream_from_fd
(
int
fd
);
apk_blob_t
apk_blob_from_istream
(
struct
apk_istream
*
istream
,
size_t
size
);
#endif
src/apk_package.h
View file @
aef0f036
...
...
@@ -14,6 +14,7 @@
#include "apk_version.h"
#include "apk_hash.h"
#include "apk_io.h"
struct
apk_database
;
struct
apk_name
;
...
...
@@ -75,7 +76,7 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *name);
void
apk_pkg_free
(
struct
apk_package
*
pkg
);
int
apk_pkg_get_state
(
struct
apk_package
*
pkg
);
int
apk_pkg_add_script
(
struct
apk_package
*
pkg
,
int
fd
,
int
apk_pkg_add_script
(
struct
apk_package
*
pkg
,
struct
apk_istream
*
is
,
unsigned
int
type
,
unsigned
int
size
);
int
apk_pkg_run_script
(
struct
apk_package
*
pkg
,
int
root_fd
,
unsigned
int
type
);
...
...
src/archive.c
View file @
aef0f036
...
...
@@ -47,75 +47,62 @@ struct tar_header {
char
padding
[
12
];
/* 500-512 */
};
static
int
get_dev_null
(
void
)
{
static
int
fd_null
=
0
;
#define GET_OCTAL(s) apk_blob_uint(APK_BLOB_PTR_LEN(s, sizeof(s)), 8)
if
(
fd_null
==
0
)
{
fd_null
=
open
(
"/dev/null"
,
O_WRONLY
);
if
(
fd_null
<
0
)
err
(
EX_OSFILE
,
"/dev/null"
);
}
return
fd_null
;
}
struct
apk_tar_entry_istream
{
struct
apk_istream
is
;
struct
apk_istream
*
tar_is
;
size_t
bytes_left
;
};
pid_t
apk_open_gz
(
int
*
fd
)
static
size_t
tar_entry_read
(
void
*
stream
,
void
*
ptr
,
size_t
size
)
{
int
pipe_fd
[
2
];
pid_t
child_pid
;
if
(
pipe
(
pipe_fd
)
<
0
)
err
(
EX_OSERR
,
"pipe"
);
child_pid
=
fork
();
if
(
child_pid
<
0
)
err
(
EX_OSERR
,
"fork"
);
if
(
child_pid
==
0
)
{
close
(
pipe_fd
[
0
]);
dup2
(
pipe_fd
[
1
],
STDOUT_FILENO
);
dup2
(
*
fd
,
STDIN_FILENO
);
dup2
(
get_dev_null
(),
STDERR_FILENO
);
close
(
pipe_fd
[
1
]);
execl
(
GUNZIP_BINARY
,
"gunzip"
,
"-c"
,
NULL
);
err
(
EX_UNAVAILABLE
,
GUNZIP_BINARY
);
}
close
(
pipe_fd
[
1
]);
*
fd
=
pipe_fd
[
0
];
return
child_pid
;
struct
apk_tar_entry_istream
*
teis
=
container_of
(
stream
,
struct
apk_tar_entry_istream
,
is
);
if
(
size
>
teis
->
bytes_left
)
size
=
teis
->
bytes_left
;
size
=
teis
->
tar_is
->
read
(
teis
->
tar_is
,
ptr
,
size
);
if
(
size
>=
0
)
teis
->
bytes_left
-=
size
;
return
size
;
}
#define GET_OCTAL(s) apk_blob_uint(APK_BLOB_PTR_LEN(s, sizeof(s)), 8)
static
int
do_splice
(
int
from_fd
,
int
to_fd
,
int
len
)
static
size_t
tar_entry_splice
(
void
*
stream
,
int
fd
,
size_t
size
)
{
int
i
=
0
,
r
;
while
(
i
!=
len
)
{
r
=
splice
(
from_fd
,
NULL
,
to_fd
,
NULL
,
len
-
i
,
SPLICE_F_MOVE
);
if
(
r
==
-
1
)
return
i
;
i
+=
r
;
}
return
i
;
struct
apk_tar_entry_istream
*
teis
=
container_of
(
stream
,
struct
apk_tar_entry_istream
,
is
);
if
(
size
>
teis
->
bytes_left
)
size
=
teis
->
bytes_left
;
size
=
teis
->
tar_is
->
splice
(
teis
->
tar_is
,
fd
,
size
);
if
(
size
>=
0
)
teis
->
bytes_left
-=
size
;
return
size
;
}
int
apk_parse_tar
(
int
fd
,
apk_archive_entry_parser
parser
,
void
*
ctx
)
int
apk_parse_tar
(
struct
apk_istream
*
is
,
apk_archive_entry_parser
parser
,
void
*
ctx
)
{
struct
apk_tar_entry_istream
teis
=
{
.
is
.
read
=
tar_entry_read
,
.
is
.
splice
=
tar_entry_splice
,
.
tar_is
=
is
,
};
struct
apk_archive_entry
entry
;
struct
tar_header
buf
;
unsigned
long
offset
=
0
;
int
end
=
0
,
r
;
size_t
toskip
;
memset
(
&
entry
,
0
,
sizeof
(
entry
));
while
(
read
(
fd
,
&
buf
,
512
)
==
512
)
{
while
(
(
r
=
is
->
read
(
is
,
&
buf
,
512
)
)
==
512
)
{
offset
+=
512
;
if
(
buf
.
name
[
0
]
==
'\0'
)
{
if
(
end
)
if
(
end
)
{
r
=
0
;
break
;
}
end
++
;
continue
;
}
...
...
@@ -131,7 +118,6 @@ int apk_parse_tar(int fd, apk_archive_entry_parser parser, void *ctx)
.
gname
=
buf
.
gname
,
.
device
=
makedev
(
GET_OCTAL
(
buf
.
devmajor
),
GET_OCTAL
(
buf
.
devminor
)),
.
read_fd
=
fd
,
};
switch
(
buf
.
typeflag
)
{
...
...
@@ -139,7 +125,7 @@ int apk_parse_tar(int fd, apk_archive_entry_parser parser, void *ctx)
if
(
entry
.
name
!=
NULL
)
free
(
entry
.
name
);
entry
.
name
=
malloc
(
entry
.
size
+
1
);
read
(
fd
,
entry
.
name
,
entry
.
size
);
is
->
read
(
is
,
entry
.
name
,
entry
.
size
);
offset
+=
entry
.
size
;
entry
.
size
=
0
;
break
;
...
...
@@ -168,74 +154,48 @@ int apk_parse_tar(int fd, apk_archive_entry_parser parser, void *ctx)
break
;
}
teis
.
bytes_left
=
entry
.
size
;
if
(
entry
.
mode
&
S_IFMT
)
{
if
(
entry
.
name
==
NULL
)
entry
.
name
=
strdup
(
buf
.
name
);
/* callback parser function */
offset
+=
entry
.
size
;
r
=
parser
(
&
entry
,
ctx
);
r
=
parser
(
ctx
,
&
entry
,
&
teis
.
is
);
if
(
r
!=
0
)
return
r
;
offset
-=
entry
.
size
;
free
(
entry
.
name
);
entry
.
name
=
NULL
;
}
if
(
entry
.
size
)
offset
+=
do_splice
(
fd
,
get_dev_null
(),
entry
.
size
);
offset
+=
entry
.
size
-
teis
.
bytes_left
;
toskip
=
teis
.
bytes_left
;
if
((
offset
+
toskip
)
&
511
)
toskip
+=
512
-
((
offset
+
toskip
)
&
511
);
offset
+=
toskip
;
if
(
toskip
!=
0
)
is
->
read
(
is
,
NULL
,
toskip
);
}
/* align to next 512 block */
if
(
offset
&
511
)
offset
+=
do_splice
(
fd
,
get_dev_null
(),
512
-
(
offset
&
511
));
if
(
r
!=
0
)
{
apk_error
(
"Bad TAR header (r=%d)"
,
r
);
return
-
1
;
}
return
0
;
}
int
apk_parse_tar_gz
(
int
fd
,
apk_archive_entry_parser
parser
,
void
*
ctx
)
{
pid_t
pid
;
int
r
,
status
;
pid
=
apk_open_gz
(
&
fd
);
if
(
pid
<
0
)
return
pid
;
r
=
apk_parse_tar
(
fd
,
parser
,
ctx
);
close
(
fd
);
waitpid
(
pid
,
&
status
,
0
);
return
r
;
}
apk_blob_t
apk_archive_entry_read
(
struct
apk_archive_entry
*
ae
)
int
apk_parse_tar_gz
(
struct
apk_bstream
*
bs
,
apk_archive_entry_parser
parser
,
void
*
ctx
)
{
char
*
str
;
int
pos
=
0
;
ssize_t
r
;
str
=
malloc
(
ae
->
size
+
1
);
pos
=
0
;
while
(
ae
->
size
)
{
r
=
read
(
ae
->
read_fd
,
&
str
[
pos
],
ae
->
size
);
if
(
r
<
0
)
{
free
(
str
);
return
APK_BLOB_NULL
;
}
pos
+=
r
;
ae
->
size
-=
r
;
}
str
[
pos
]
=
0
;
return
APK_BLOB_PTR_LEN
(
str
,
pos
+
1
);
return
apk_parse_tar
(
apk_gunzip_bstream
(
bs
),
parser
,
ctx
);
}
int
apk_archive_entry_extract
(
struct
apk_archive_entry
*
ae
,
const
char
*
fn
)
int
apk_archive_entry_extract
(
const
struct
apk_archive_entry
*
ae
,
struct
apk_istream
*
is
,
const
char
*
fn
)
{
int
r
=
-
1
;
int
r
=
-
1
,
fd
;
if
(
fn
==
NULL
)
fn
=
ae
->
name
;
...
...
@@ -251,12 +211,14 @@ int apk_archive_entry_extract(struct apk_archive_entry *ae, const char *fn)
break
;
case
S_IFREG
:
if
(
ae
->
link_target
==
NULL
)
{
r
=
open
(
fn
,
O_WRONLY
|
O_CREAT
,
ae
->
mode
&
07777
);
if
(
r
<
0
)
fd
=
open
(
fn
,
O_WRONLY
|
O_CREAT
,
ae
->
mode
&
07777
);
if
(
fd
<
0
)
{
r
=
-
1
;
break
;
ae
->
size
-=
do_splice
(
ae
->
read_fd
,
r
,
ae
->
size
);
close
(
r
);
r
=
ae
->
size
?
-
1
:
0
;
}
if
(
is
->
splice
(
is
,
fd
,
ae
->
size
)
==
ae
->
size
)
r
=
0
;
close
(
fd
);
}
else
{
r
=
link
(
ae
->
link_target
,
fn
);
}
...
...
@@ -284,74 +246,3 @@ int apk_archive_entry_extract(struct apk_archive_entry *ae, const char *fn)
}
return
r
;
}
struct
checksum_and_tee
{
int
in_fd
,
tee_fd
;
void
*
ptr
;
};
static
void
*
__apk_checksum_and_tee
(
void
*
arg
)
{
struct
checksum_and_tee
*
args
=
(
struct
checksum_and_tee
*
)
arg
;
char
buf
[
2
*
1024
];
int
r
,
w
,
wt
;
__off64_t
offset
;
csum_ctx_t
ctx
;
int
dosplice
=
1
;
offset
=
lseek
(
args
->
in_fd
,
0
,
SEEK_CUR
);
csum_init
(
&
ctx
);
do
{
r
=
read
(
args
->
in_fd
,
buf
,
sizeof
(
buf
));
if
(
r
<=
0
)
break
;
wt
=
0
;
do
{
if
(
dosplice
)
{
w
=
splice
(
args
->
in_fd
,
&
offset
,
args
->
tee_fd
,
NULL
,
r
-
wt
,
SPLICE_F_MOVE
);
if
(
w
<
0
)
{
dosplice
=
0
;
continue
;
}
}
else
{
w
=
write
(
args
->
tee_fd
,
&
buf
[
wt
],
r
-
wt
);
if
(
w
<
0
)
break
;
}
wt
+=
w
;
}
while
(
wt
!=
r
);
csum_process
(
&
ctx
,
buf
,
r
);
}
while
(
r
==
sizeof
(
buf
));
csum_finish
(
&
ctx
,
args
->
ptr
);
close
(
args
->
tee_fd
);
close
(
args
->
in_fd
);
free
(
args
);
return
NULL
;
}
pthread_t
apk_checksum_and_tee
(
int
*
fd
,
void
*
ptr
)
{
struct
checksum_and_tee
*
args
;
int
fds
[
2
];
pthread_t
tid
;
if
(
pipe
(
fds
)
<
0
)
return
-
1
;
fcntl
(
fds
[
0
],
F_SETFD
,
FD_CLOEXEC
);
fcntl
(
fds
[
1
],
F_SETFD
,
FD_CLOEXEC
);
args
=
malloc
(
sizeof
(
*
args
));
*
args
=
(
struct
checksum_and_tee
){
*
fd
,
fds
[
1
],
ptr
};
if
(
pthread_create
(
&
tid
,
NULL
,
__apk_checksum_and_tee
,
args
)
<
0
)
return
-
1
;
*
fd
=
fds
[
0
];
return
tid
;
}
src/database.c
View file @
aef0f036
...
...
@@ -376,14 +376,14 @@ static int apk_db_write_scriptdb(struct apk_database *db, int fd)
return
0
;
}
static
int
apk_db_read_scriptdb
(
struct
apk_database
*
db
,
int
fd
)
static
int
apk_db_read_scriptdb
(
struct
apk_database
*
db
,
struct
apk_istream
*
is
)
{
struct
apk_package
*
pkg
;
struct
apk_script_header
hdr
;
while
(
read
(
fd
,
&
hdr
,
sizeof
(
hdr
))
==
sizeof
(
hdr
))
{
while
(
is
->
read
(
is
,
&
hdr
,
sizeof
(
hdr
))
==
sizeof
(
hdr
))
{
pkg
=
apk_db_get_pkg
(
db
,
hdr
.
csum
);
apk_pkg_add_script
(
pkg
,
fd
,
hdr
.
type
,
hdr
.
size
);
apk_pkg_add_script
(
pkg
,
is
,
hdr
.
type
,
hdr
.
size
);
}
return
0
;
...
...
@@ -416,6 +416,7 @@ int apk_db_create(const char *root)
static
int
apk_db_read_config
(
struct
apk_database
*
db
)
{
struct
apk_istream
*
is
;
struct
stat
st
;
char
*
buf
;
int
fd
;
...
...
@@ -452,10 +453,10 @@ static int apk_db_read_config(struct apk_database *db)
close
(
fd
);
}
fd
=
open
(
"var/lib/apk/scripts"
,
O_RDONLY
);
if
(
fd
>=
0
)
{
apk_db_read_scriptdb
(
db
,
fd
);
close
(
fd
);
is
=
apk_istream_from_file
(
"var/lib/apk/scripts"
);
if
(
is
!=
NULL
)
{
apk_db_read_scriptdb
(
db
,
is
);
is
->
close
(
is
);
}
return
0
;
...
...
@@ -664,9 +665,11 @@ int apk_db_recalculate_and_commit(struct apk_database *db)
return
r
;
}
static
int
apk_db_install_archive_entry
(
struct
apk_archive_entry
*
ae
,
struct
install_ctx
*
ctx
)
static
int
apk_db_install_archive_entry
(
void
*
_ctx
,
const
struct
apk_archive_entry
*
ae
,
struct
apk_istream
*
is
)
{
struct
install_ctx
*
ctx
=
(
struct
install_ctx
*
)
_ctx
;
struct
apk_database
*
db
=
ctx
->
db
;
struct
apk_package
*
pkg
=
ctx
->
pkg
;
apk_blob_t
name
=
APK_BLOB_STR
(
ae
->
name
);
...
...
@@ -698,8 +701,7 @@ static int apk_db_install_archive_entry(struct apk_archive_entry *ae,
/* Handle script */
if
(
type
!=
APK_SCRIPT_INVALID
)
{
ae
->
size
-=
apk_pkg_add_script
(
pkg
,
ae
->
read_fd
,
type
,
ae
->
size
);
apk_pkg_add_script
(
pkg
,
is
,
type
,
ae
->
size
);
if
(
type
==
APK_SCRIPT_GENERIC
||
type
==
ctx
->
script
)
{
...
...
@@ -736,7 +738,7 @@ static int apk_db_install_archive_entry(struct apk_archive_entry *ae,
if
(
strncmp
(
file
->
filename
,
".keep_"
,
6
)
==
0
)
return
0
;
r
=
apk_archive_entry_extract
(
ae
,
NULL
);
r
=
apk_archive_entry_extract
(
ae
,
is
,
NULL
);
}
else
{
if
(
name
.
ptr
[
name
.
len
-
1
]
==
'/'
)
name
.
len
--
;
...
...
@@ -775,10 +777,10 @@ int apk_db_install_pkg(struct apk_database *db,
struct
apk_package
*
oldpkg
,
struct
apk_package
*
newpkg
)
{
struct
apk_bstream
*
bs
;
struct
install_ctx
ctx
;
csum_t
csum
;
char
file
[
256
];
pthread_t
tid
=
0
;
int
fd
,
r
;
if
(
fchdir
(
db
->
root_fd
)
<
0
)
...
...
@@ -813,8 +815,8 @@ int apk_db_install_pkg(struct apk_database *db,
fcntl
(
fd
,
F_SETFD
,
FD_CLOEXEC
);
tid
=
apk_checksum_and_tee
(
&
fd
,
csum
);
if
(
tid
<
0
)
bs
=
apk_bstream_from_fd
(
fd
);
if
(
bs
==
NULL
)
goto
err_close
;
ctx
=
(
struct
install_ctx
)
{
...
...
@@ -823,12 +825,10 @@ int apk_db_install_pkg(struct apk_database *db,
.
script
=
(
oldpkg
==
NULL
)
?
APK_SCRIPT_PRE_INSTALL
:
APK_SCRIPT_PRE_UPGRADE
,
};
if
(
apk_parse_tar_gz
(
fd
,
(
apk_archive_entry_parser
)
apk_db_install_archive_entry
,
&
ctx
)
!=
0
)
if
(
apk_parse_tar_gz
(
bs
,
apk_db_install_archive_entry
,
&
ctx
)
!=
0
)
goto
err_close
;
pthread_join
(
tid
,
NULL
);
close
(
fd
);
bs
->
close
(
bs
,
csum
);
db
->
installed
.
stats
.
packages
++
;
hlist_add_head
(
&
newpkg
->
installed_pkgs_list
,
&
db
->
installed
.
packages
);
...
...
@@ -850,7 +850,5 @@ int apk_db_install_pkg(struct apk_database *db,
err_close:
close
(
fd
);
if
(
tid
!=
0
)
pthread_join
(
tid
,
NULL
);
return
-
1
;
}
src/gunzip.c
0 → 100644
View file @
aef0f036
/* gunzip.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
#include <zlib.h>
#include "apk_defines.h"
#include "apk_io.h"
struct
apk_gzip_istream
{
struct
apk_istream
is
;
struct
apk_bstream
*
bs
;
z_stream
zs
;
int
z_err
;
};
static
size_t
gz_read
(
void
*
stream
,
void
*
ptr
,
size_t
size
)
{
struct
apk_gzip_istream
*
gis
=
container_of
(
stream
,
struct
apk_gzip_istream
,
is
);
if
(
gis
->
z_err
==
Z_DATA_ERROR
||
gis
->
z_err
==
Z_ERRNO
)
return
-
1
;
if
(
gis
->
z_err
==
Z_STREAM_END
)
return
0
;
if
(
ptr
==
NULL
)
return
apk_istream_skip
(
&
gis
->
is
,
size
);
gis
->
zs
.
avail_out
=
size
;
gis
->
zs
.
next_out
=
ptr
;
while
(
gis
->
zs
.
avail_out
!=
0
&&
gis
->
z_err
==
Z_OK
)
{
if
(
gis
->
zs
.
avail_in
==
0
)
{
gis
->
zs
.
avail_in
=
gis
->
bs
->
read
(
gis
->
bs
,
(
void
**
)
&
gis
->
zs
.
next_in
);
if
(
gis
->
zs
.
avail_in
<
0
)
{
gis
->
z_err
=
Z_DATA_ERROR
;
return
size
-
gis
->
zs
.
avail_out
;
}
}
gis
->
z_err
=
inflate
(
&
gis
->
zs
,
Z_NO_FLUSH
);
}
if
(
gis
->
z_err
!=
Z_OK
&&
gis
->
z_err
!=
Z_STREAM_END
)
return
-
1
;
return
size
-
gis
->
zs
.
avail_out
;
}
static
void
gz_close
(
void
*
stream
)
{
struct
apk_gzip_istream
*
gis
=
container_of
(
stream
,
struct
apk_gzip_istream
,
is
);
inflateEnd
(
&
gis
->
zs
);
free
(
gis
);
}
struct
apk_istream
*
apk_gunzip_bstream
(
struct
apk_bstream
*
bs
)
{
struct
apk_gzip_istream
*
gis
;
gis
=
malloc
(
sizeof
(
struct
apk_gzip_istream
));
if
(
gis
==
NULL
)
return
NULL
;
*
gis
=
(
struct
apk_gzip_istream
)
{
.
is
.
read
=
gz_read
,
.
is
.
splice
=
apk_istream_splice
,
.
is
.
close
=
gz_close
,
.
bs
=
bs
,
.
z_err
=
0
,
};
if
(
inflateInit2
(
&
gis
->
zs
,
15
+
32
)
!=
Z_OK
)
{
free
(
gis
);
return
NULL
;
}
return
&
gis
->
is
;
}
src/io.c
0 → 100644
View file @
aef0f036