iPhone 的 TAR 编码/解码库(最好是 cocoa)

发布于 2024-07-29 11:25:07 字数 1542 浏览 7 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

划一舟意中人 2024-08-05 11:25:07

我发现的最好的库是libarchive。 它设计精良,文档齐全,而且速度很快。

我刚刚在 GitHub 上创建了一个存储库,其中包含将 libarchivelibbz2 构建为 iOS 4.2+ 静态库的工具。 (也应该可以使用它来定位 3.x。)

http://github.com /davepeck/iOS-libarchive/

其他人指出 libarchive 包含在 SDK 中。 这并不完全正确。 包含二进制 libarchive.2.dylib,但不包含标头。 这同样适用于libbz2(但奇怪的是,不适用于libz。)这意味着libarchive被视为私有API——换句话说,如果您打算在 App Store 上发布,则无法使用它。 因此我的存储库。

The best library I've found is libarchive. It is well-designed, well-documented, and fast.

I just created a repository on GitHub that has the tools to build libarchive and libbz2 as static libraries for iOS 4.2+. (It should be possible to use it to target 3.x, too.)

http://github.com/davepeck/iOS-libarchive/

Others have pointed out that libarchive is included in the SDK. This is not quite true. The binary libarchive.2.dylib is included, but the headers are not. The same applies to libbz2 (but, oddly, not to libz.) This means that libarchive is considered a private API -- in other words, you can't use it if you intend to ship on the App Store. Hence my repository.

拥醉 2024-08-05 11:25:07

事实上,libarchive.dylib 包含在 iPhone SDK 中。 您只需添加它即可。 问题是Apple 不知何故没有包含头文件archive.h。 但是,首先,如果您确定要调用的函数存在(尽管编译器会抱怨),则不需要头文件;其次,如果您不想让编译器抱怨,则可以下载头文件libarchive 2.6 并将其包含在您的程序中...

如果您想了解如何使用 libarchive,请从网络下载其源代码并研究给出的示例(尤其是 minitar)。 这确实非常简单。

In fact, libarchive.dylib is included in the iPhone SDK. You just have to add it. The problem is that somehow Apple did not include the header file archive.h. However, first, you do not need the header files if you know for sure the functions you are going to call exist (though the compiler will whine), second, if you do not want the compiler to complain, you can download the header file for libarchive 2.6 and include it in your program ...

If you want to know know to use libarchive, download its source from the web and study the example given (especially minitar). It is really very straightforward.

梦旅人picnic 2024-08-05 11:25:07

您可以尝试 libxad。 这是 Mac 应用程序 The Unarchiver 使用的库。

You might try libxad. This is the library that The Unarchiver, a Mac app, uses.

作死小能手 2024-08-05 11:25:07

更好的链接:http://code.google.com/p/libarchive/downloads/detail?name=libarchive-2.6.2.tar.gz&can=2&q=

版本 2.6.2 包含在iOS 4.0 和 4.1 SDK。 它在 3.2 中不存在(或者我认为更早的版本)。

如果您下载了该文件,请运行 ./configure --prefix=$HOME && 制作&& make install 你会发现两个头文件放置在 $HOME/include 中

Even better link: http://code.google.com/p/libarchive/downloads/detail?name=libarchive-2.6.2.tar.gz&can=2&q=

Version 2.6.2 is included in the iOS 4.0 and 4.1 SDK's. It's not present in 3.2 (or earlier I assume).

If you download that, run ./configure --prefix=$HOME && make && make install and you'll find the two header files placed in $HOME/include

雨轻弹 2024-08-05 11:25:07

对于 libarchive,只需将“libarchive”添加到框架列表中即可开箱即用,但缺少标头。 您可以从 libarchive 源复制标头。 或者,如果您想保持简单,请尝试以下操作:

////////////////////////////////////////////////////////////////////////////////////////////////////
//  LibArchive "Header" - ios is missing this header.  go figure.
////////////////////////////////////////////////////////////////////////////////////////////////////

// from ftp://ftp8.freebsd.org/pub/FreeBSD/FreeBSD-current/src/lib/libarchive/archive.h.in

#define      ARCHIVE_EOF                1          /* Found end of archive. */
#define      ARCHIVE_OK                 0          /* Operation was successful. */
#define      ARCHIVE_RETRY            (-10)        /* Retry might succeed. */
#define      ARCHIVE_WARN             (-20)        /* Partial success. */
#define      ARCHIVE_FAILED           (-25)        /* Current operation cannot complete. */
#define      ARCHIVE_FATAL            (-30)        /* No more operations are possible. */

struct archive;
struct archive_entry;

int               archive_version_number(void);
const char *      archive_version_string(void);
int               archive_version_stamp(void);
const char *      archive_version(void);
int               archive_api_version(void);
int               archive_api_feature(void);
typedef ssize_t   archive_read_callback(struct archive *, void *_client_data, const void **_buffer);
//typedef ssize_t   archive_skip_callback(struct archive *, void *_client_data, size_t request);
typedef off_t     archive_skip_callback(struct archive *, void *_client_data, off_t request);
typedef ssize_t   archive_write_callback(struct archive *, void *_client_data, const void *_buffer, size_t _length);
typedef int       archive_open_callback(struct archive *, void *_client_data);
typedef int       archive_close_callback(struct archive *, void *_client_data);
struct            archive *archive_read_new(void);
int               archive_read_support_compression_all(struct archive *);
int               archive_read_support_compression_bzip2(struct archive *);
int               archive_read_support_compression_compress(struct archive *);
int               archive_read_support_compression_gzip(struct archive *);
int               archive_read_support_compression_none(struct archive *);
int               archive_read_support_compression_program(struct archive *, const char *command);
int               archive_read_support_format_all(struct archive *);
int               archive_read_support_format_ar(struct archive *);
int               archive_read_support_format_cpio(struct archive *);
int               archive_read_support_format_empty(struct archive *);
int               archive_read_support_format_gnutar(struct archive *);
int               archive_read_support_format_iso9660(struct archive *);
int               archive_read_support_format_mtree(struct archive *);
int               archive_read_support_format_tar(struct archive *);
int               archive_read_support_format_zip(struct archive *);
int               archive_read_open(struct archive *, void *_client_data, archive_open_callback *, archive_read_callback *, archive_close_callback *);
int               archive_read_open2(struct archive *, void *_client_data, archive_open_callback *, archive_read_callback *, archive_skip_callback *, archive_close_callback *);
int               archive_read_open_filename(struct archive *, const char *_filename, size_t _block_size);
int               archive_read_open_file(struct archive *, const char *_filename, size_t _block_size);
int               archive_read_open_memory(struct archive *, void * buff, size_t size);
int               archive_read_open_memory2(struct archive *a, void *buff, size_t size, size_t read_size);
int               archive_read_open_fd(struct archive *, int _fd, size_t _block_size);
int               archive_read_open_FILE(struct archive *, FILE *_file);
int               archive_read_next_header(struct archive *, struct archive_entry **);
int64_t           archive_read_header_position(struct archive *);
ssize_t           archive_read_data(struct archive *, void *, size_t);
int               archive_read_data_block(struct archive *a, const void **buff, size_t *size, off_t *offset);
int               archive_read_data_skip(struct archive *);
int               archive_read_data_into_buffer(struct archive *, void *buffer, ssize_t len);
int               archive_read_data_into_fd(struct archive *, int fd);
int               archive_read_extract(struct archive *, struct archive_entry *, int flags);
void              archive_read_extract_set_progress_callback(struct archive *, void (*_progress_func)(void *), void *_user_data);
void              archive_read_extract_set_skip_file(struct archive *, dev_t, ino_t);
int               archive_read_close(struct archive *);
int               archive_read_finish(struct archive *);
//void              archive_read_finish(struct archive *);
struct            archive *archive_write_new(void);
int               archive_write_set_bytes_per_block(struct archive *, int bytes_per_block);
int               archive_write_get_bytes_per_block(struct archive *);
int               archive_write_set_bytes_in_last_block(struct archive *, int bytes_in_last_block);
int               archive_write_get_bytes_in_last_block(struct archive *);
int               archive_write_set_skip_file(struct archive *, dev_t, ino_t);
int               archive_write_set_compression_bzip2(struct archive *);
int               archive_write_set_compression_compress(struct archive *);
int               archive_write_set_compression_gzip(struct archive *);
int               archive_write_set_compression_none(struct archive *);
int               archive_write_set_compression_program(struct archive *, const char *cmd);
int               archive_write_set_format(struct archive *, int format_code);
int               archive_write_set_format_by_name(struct archive *, const char *name);
int               archive_write_set_format_ar_bsd(struct archive *);
int               archive_write_set_format_ar_svr4(struct archive *);
int               archive_write_set_format_cpio(struct archive *);
int               archive_write_set_format_cpio_newc(struct archive *);
int               archive_write_set_format_pax(struct archive *);
int               archive_write_set_format_pax_restricted(struct archive *);
int               archive_write_set_format_shar(struct archive *);
int               archive_write_set_format_shar_dump(struct archive *);
int               archive_write_set_format_ustar(struct archive *);
int               archive_write_open(struct archive *, void *, archive_open_callback *, archive_write_callback *, archive_close_callback *);
int               archive_write_open_fd(struct archive *, int _fd);
int               archive_write_open_filename(struct archive *, const char *_file);
int               archive_write_open_file(struct archive *, const char *_file);
int               archive_write_open_FILE(struct archive *, FILE *);
int               archive_write_open_memory(struct archive *, void *_buffer, size_t _buffSize, size_t *_used);
int               archive_write_header(struct archive *, struct archive_entry *);
ssize_t           archive_write_data(struct archive *, const void *, size_t);
//int               archive_write_data(struct archive *, const void *, size_t);
ssize_t           archive_write_data_block(struct archive *, const void *, size_t, off_t);
int               archive_write_finish_entry(struct archive *);
int               archive_write_close(struct archive *);
int               archive_write_finish(struct archive *);
//void              archive_write_finish(struct archive *);
struct            archive *archive_write_disk_new(void);
int               archive_write_disk_set_skip_file(struct archive *, dev_t, ino_t);
int               archive_write_disk_set_options(struct archive *, int flags);
int               archive_write_disk_set_standard_lookup(struct archive *);
int               archive_write_disk_set_group_lookup(struct archive *, void *private_data, gid_t (*loookup)(void *, const char *gname, gid_t gid), void (*cleanup)(void *));
int               archive_write_disk_set_user_lookup(struct archive *, void *private_data, uid_t (*)(void *, const char *uname, uid_t uid), void (*cleanup)(void *));
int64_t           archive_position_compressed(struct archive *);
int64_t           archive_position_uncompressed(struct archive *);
const char *      archive_compression_name(struct archive *);
int               archive_compression(struct archive *);
int               archive_errno(struct archive *);
const char *      archive_error_string(struct archive *);
const char *      archive_format_name(struct archive *);
int               archive_format(struct archive *);
void              archive_clear_error(struct archive *);
void              archive_set_error(struct archive *, int _err, const char *fmt, ...);
void              archive_copy_error(struct archive *dest, struct archive *src);

// From ftp://ftp8.freebsd.org/pub/FreeBSD/FreeBSD-current/src/lib/libarchive/archive_entry.h

time_t            archive_entry_atime(struct archive_entry *);
long              archive_entry_atime_nsec(struct archive_entry *);
time_t            archive_entry_ctime(struct archive_entry *);
long              archive_entry_ctime_nsec(struct archive_entry *);
dev_t             archive_entry_dev(struct archive_entry *);
dev_t             archive_entry_devmajor(struct archive_entry *);
dev_t             archive_entry_devminor(struct archive_entry *);
mode_t            archive_entry_filetype(struct archive_entry *);
void              archive_entry_fflags(struct archive_entry *, unsigned long *set, unsigned long *clear);
const char*       archive_entry_fflags_text(struct archive_entry *);
gid_t             archive_entry_gid(struct archive_entry *);
const char*       archive_entry_gname(struct archive_entry *);
const wchar_t*    archive_entry_gname_w(struct archive_entry *);
const char*       archive_entry_hardlink(struct archive_entry *);
const wchar_t*    archive_entry_hardlink_w(struct archive_entry *);
ino_t             archive_entry_ino(struct archive_entry *);
mode_t            archive_entry_mode(struct archive_entry *);
time_t            archive_entry_mtime(struct archive_entry *);
long              archive_entry_mtime_nsec(struct archive_entry *);
unsigned int      archive_entry_nlink(struct archive_entry *);
const char*       archive_entry_pathname(struct archive_entry *);
const wchar_t*    archive_entry_pathname_w(struct archive_entry *);
dev_t             archive_entry_rdev(struct archive_entry *);
dev_t             archive_entry_rdevmajor(struct archive_entry *);
dev_t             archive_entry_rdevminor(struct archive_entry *);
int64_t           archive_entry_size(struct archive_entry *);
const char*       archive_entry_strmode(struct archive_entry *);
const char*       archive_entry_symlink(struct archive_entry *);
const wchar_t*    archive_entry_symlink_w(struct archive_entry *);
uid_t             archive_entry_uid(struct archive_entry *);
const char*       archive_entry_uname(struct archive_entry *);
const wchar_t*    archive_entry_uname_w(struct archive_entry *);

我只关心阅读,因此我不关心某些 archive_entry.h 突变函数。 另外,一些方法被注释掉了。 这些是不同版本的替代方案,#ifdef 已被淘汰。 祝你好运,狩猎愉快!

以下是使用它将存档解压到 ios 上的目录的示例:

+ (void)unpackArchive: (NSData*) archiveData
{
    int r;
    struct archive* a;
    struct archive_entry *entry;
    const char *entry_path;
    NSString *baseDir = [self baseDir];
    NSFileHandle* file;
    NSError* error;
    NSDictionary* result = @{};

    NSLog(@"Unpacking %d byte static assets tarball into %@", [archiveData length], baseDir);

    if (![[NSFileManager defaultManager] createDirectoryAtPath:baseDir
                                   withIntermediateDirectories:YES
                                                    attributes:nil
                                                         error:&error])
    {
        NSLog(@"Create directory error: %@", error);
    }

    a = archive_read_new();
    archive_read_support_format_gnutar(a);
    archive_read_support_format_tar(a);
    archive_read_support_compression_gzip(a);

    r = archive_read_open_memory(a, (void*)[archiveData bytes], [archiveData length]);
    if (r != ARCHIVE_OK) {
        NSLog(@"ERROR[%d] in archive_read_open_file(): %s", r, archive_error_string(a));
        return;
    }
    for (;;) {
        r = archive_read_next_header(a, &entry);
        if (r == ARCHIVE_EOF) {
            break;
        }
        if (r != ARCHIVE_OK) {
            NSLog(@"ERROR[%d] in archive_read_next_header(): %s", r, archive_error_string(a));
            return;
        }
        entry_path = archive_entry_pathname(entry);

        NSString* path = [baseDir stringByAppendingPathComponent: [NSString stringWithUTF8String: entry_path]];
        NSLog(@"Tarball Entry: %s", entry_path);

        // Create the file and blank it out
        [[NSFileManager defaultManager] createFileAtPath: path contents:[[NSMutableData alloc] init] attributes:nil];
        // Actually write the file
        file = [NSFileHandle fileHandleForWritingAtPath:path];
        r = archive_read_data_into_fd(a, [file fileDescriptor]);
        if (r != ARCHIVE_OK) {
            NSLog(@"ERROR[%d] in archive_read_data_into_fd(): %s", r, archive_error_string(a));
            return;
        }
        [file closeFile];
    }
    r = archive_read_close(a);
    if (r != ARCHIVE_OK) {
        NSLog(@"ERROR[%d] in archive_read_close(): %s", r, archive_error_string(a));
        return;
    }
}

--- Dave

For libarchive, it works out of the box by just adding "libarchive" to your framework list, but the header is missing. You can copy the headers from the libarchive source. Or if you want to keep it simple, try this:

////////////////////////////////////////////////////////////////////////////////////////////////////
//  LibArchive "Header" - ios is missing this header.  go figure.
////////////////////////////////////////////////////////////////////////////////////////////////////

// from ftp://ftp8.freebsd.org/pub/FreeBSD/FreeBSD-current/src/lib/libarchive/archive.h.in

#define      ARCHIVE_EOF                1          /* Found end of archive. */
#define      ARCHIVE_OK                 0          /* Operation was successful. */
#define      ARCHIVE_RETRY            (-10)        /* Retry might succeed. */
#define      ARCHIVE_WARN             (-20)        /* Partial success. */
#define      ARCHIVE_FAILED           (-25)        /* Current operation cannot complete. */
#define      ARCHIVE_FATAL            (-30)        /* No more operations are possible. */

struct archive;
struct archive_entry;

int               archive_version_number(void);
const char *      archive_version_string(void);
int               archive_version_stamp(void);
const char *      archive_version(void);
int               archive_api_version(void);
int               archive_api_feature(void);
typedef ssize_t   archive_read_callback(struct archive *, void *_client_data, const void **_buffer);
//typedef ssize_t   archive_skip_callback(struct archive *, void *_client_data, size_t request);
typedef off_t     archive_skip_callback(struct archive *, void *_client_data, off_t request);
typedef ssize_t   archive_write_callback(struct archive *, void *_client_data, const void *_buffer, size_t _length);
typedef int       archive_open_callback(struct archive *, void *_client_data);
typedef int       archive_close_callback(struct archive *, void *_client_data);
struct            archive *archive_read_new(void);
int               archive_read_support_compression_all(struct archive *);
int               archive_read_support_compression_bzip2(struct archive *);
int               archive_read_support_compression_compress(struct archive *);
int               archive_read_support_compression_gzip(struct archive *);
int               archive_read_support_compression_none(struct archive *);
int               archive_read_support_compression_program(struct archive *, const char *command);
int               archive_read_support_format_all(struct archive *);
int               archive_read_support_format_ar(struct archive *);
int               archive_read_support_format_cpio(struct archive *);
int               archive_read_support_format_empty(struct archive *);
int               archive_read_support_format_gnutar(struct archive *);
int               archive_read_support_format_iso9660(struct archive *);
int               archive_read_support_format_mtree(struct archive *);
int               archive_read_support_format_tar(struct archive *);
int               archive_read_support_format_zip(struct archive *);
int               archive_read_open(struct archive *, void *_client_data, archive_open_callback *, archive_read_callback *, archive_close_callback *);
int               archive_read_open2(struct archive *, void *_client_data, archive_open_callback *, archive_read_callback *, archive_skip_callback *, archive_close_callback *);
int               archive_read_open_filename(struct archive *, const char *_filename, size_t _block_size);
int               archive_read_open_file(struct archive *, const char *_filename, size_t _block_size);
int               archive_read_open_memory(struct archive *, void * buff, size_t size);
int               archive_read_open_memory2(struct archive *a, void *buff, size_t size, size_t read_size);
int               archive_read_open_fd(struct archive *, int _fd, size_t _block_size);
int               archive_read_open_FILE(struct archive *, FILE *_file);
int               archive_read_next_header(struct archive *, struct archive_entry **);
int64_t           archive_read_header_position(struct archive *);
ssize_t           archive_read_data(struct archive *, void *, size_t);
int               archive_read_data_block(struct archive *a, const void **buff, size_t *size, off_t *offset);
int               archive_read_data_skip(struct archive *);
int               archive_read_data_into_buffer(struct archive *, void *buffer, ssize_t len);
int               archive_read_data_into_fd(struct archive *, int fd);
int               archive_read_extract(struct archive *, struct archive_entry *, int flags);
void              archive_read_extract_set_progress_callback(struct archive *, void (*_progress_func)(void *), void *_user_data);
void              archive_read_extract_set_skip_file(struct archive *, dev_t, ino_t);
int               archive_read_close(struct archive *);
int               archive_read_finish(struct archive *);
//void              archive_read_finish(struct archive *);
struct            archive *archive_write_new(void);
int               archive_write_set_bytes_per_block(struct archive *, int bytes_per_block);
int               archive_write_get_bytes_per_block(struct archive *);
int               archive_write_set_bytes_in_last_block(struct archive *, int bytes_in_last_block);
int               archive_write_get_bytes_in_last_block(struct archive *);
int               archive_write_set_skip_file(struct archive *, dev_t, ino_t);
int               archive_write_set_compression_bzip2(struct archive *);
int               archive_write_set_compression_compress(struct archive *);
int               archive_write_set_compression_gzip(struct archive *);
int               archive_write_set_compression_none(struct archive *);
int               archive_write_set_compression_program(struct archive *, const char *cmd);
int               archive_write_set_format(struct archive *, int format_code);
int               archive_write_set_format_by_name(struct archive *, const char *name);
int               archive_write_set_format_ar_bsd(struct archive *);
int               archive_write_set_format_ar_svr4(struct archive *);
int               archive_write_set_format_cpio(struct archive *);
int               archive_write_set_format_cpio_newc(struct archive *);
int               archive_write_set_format_pax(struct archive *);
int               archive_write_set_format_pax_restricted(struct archive *);
int               archive_write_set_format_shar(struct archive *);
int               archive_write_set_format_shar_dump(struct archive *);
int               archive_write_set_format_ustar(struct archive *);
int               archive_write_open(struct archive *, void *, archive_open_callback *, archive_write_callback *, archive_close_callback *);
int               archive_write_open_fd(struct archive *, int _fd);
int               archive_write_open_filename(struct archive *, const char *_file);
int               archive_write_open_file(struct archive *, const char *_file);
int               archive_write_open_FILE(struct archive *, FILE *);
int               archive_write_open_memory(struct archive *, void *_buffer, size_t _buffSize, size_t *_used);
int               archive_write_header(struct archive *, struct archive_entry *);
ssize_t           archive_write_data(struct archive *, const void *, size_t);
//int               archive_write_data(struct archive *, const void *, size_t);
ssize_t           archive_write_data_block(struct archive *, const void *, size_t, off_t);
int               archive_write_finish_entry(struct archive *);
int               archive_write_close(struct archive *);
int               archive_write_finish(struct archive *);
//void              archive_write_finish(struct archive *);
struct            archive *archive_write_disk_new(void);
int               archive_write_disk_set_skip_file(struct archive *, dev_t, ino_t);
int               archive_write_disk_set_options(struct archive *, int flags);
int               archive_write_disk_set_standard_lookup(struct archive *);
int               archive_write_disk_set_group_lookup(struct archive *, void *private_data, gid_t (*loookup)(void *, const char *gname, gid_t gid), void (*cleanup)(void *));
int               archive_write_disk_set_user_lookup(struct archive *, void *private_data, uid_t (*)(void *, const char *uname, uid_t uid), void (*cleanup)(void *));
int64_t           archive_position_compressed(struct archive *);
int64_t           archive_position_uncompressed(struct archive *);
const char *      archive_compression_name(struct archive *);
int               archive_compression(struct archive *);
int               archive_errno(struct archive *);
const char *      archive_error_string(struct archive *);
const char *      archive_format_name(struct archive *);
int               archive_format(struct archive *);
void              archive_clear_error(struct archive *);
void              archive_set_error(struct archive *, int _err, const char *fmt, ...);
void              archive_copy_error(struct archive *dest, struct archive *src);

// From ftp://ftp8.freebsd.org/pub/FreeBSD/FreeBSD-current/src/lib/libarchive/archive_entry.h

time_t            archive_entry_atime(struct archive_entry *);
long              archive_entry_atime_nsec(struct archive_entry *);
time_t            archive_entry_ctime(struct archive_entry *);
long              archive_entry_ctime_nsec(struct archive_entry *);
dev_t             archive_entry_dev(struct archive_entry *);
dev_t             archive_entry_devmajor(struct archive_entry *);
dev_t             archive_entry_devminor(struct archive_entry *);
mode_t            archive_entry_filetype(struct archive_entry *);
void              archive_entry_fflags(struct archive_entry *, unsigned long *set, unsigned long *clear);
const char*       archive_entry_fflags_text(struct archive_entry *);
gid_t             archive_entry_gid(struct archive_entry *);
const char*       archive_entry_gname(struct archive_entry *);
const wchar_t*    archive_entry_gname_w(struct archive_entry *);
const char*       archive_entry_hardlink(struct archive_entry *);
const wchar_t*    archive_entry_hardlink_w(struct archive_entry *);
ino_t             archive_entry_ino(struct archive_entry *);
mode_t            archive_entry_mode(struct archive_entry *);
time_t            archive_entry_mtime(struct archive_entry *);
long              archive_entry_mtime_nsec(struct archive_entry *);
unsigned int      archive_entry_nlink(struct archive_entry *);
const char*       archive_entry_pathname(struct archive_entry *);
const wchar_t*    archive_entry_pathname_w(struct archive_entry *);
dev_t             archive_entry_rdev(struct archive_entry *);
dev_t             archive_entry_rdevmajor(struct archive_entry *);
dev_t             archive_entry_rdevminor(struct archive_entry *);
int64_t           archive_entry_size(struct archive_entry *);
const char*       archive_entry_strmode(struct archive_entry *);
const char*       archive_entry_symlink(struct archive_entry *);
const wchar_t*    archive_entry_symlink_w(struct archive_entry *);
uid_t             archive_entry_uid(struct archive_entry *);
const char*       archive_entry_uname(struct archive_entry *);
const wchar_t*    archive_entry_uname_w(struct archive_entry *);

I only cared about reading so I didn't bother with some of the archive_entry.h mutation functions. Also, a few of the methods are commented out. Those are the alternates for different versions that get #ifdef'd out. Good luck and good bug hunting!

Here's a sample of using it to unpack an archive to a directory on ios:

+ (void)unpackArchive: (NSData*) archiveData
{
    int r;
    struct archive* a;
    struct archive_entry *entry;
    const char *entry_path;
    NSString *baseDir = [self baseDir];
    NSFileHandle* file;
    NSError* error;
    NSDictionary* result = @{};

    NSLog(@"Unpacking %d byte static assets tarball into %@", [archiveData length], baseDir);

    if (![[NSFileManager defaultManager] createDirectoryAtPath:baseDir
                                   withIntermediateDirectories:YES
                                                    attributes:nil
                                                         error:&error])
    {
        NSLog(@"Create directory error: %@", error);
    }

    a = archive_read_new();
    archive_read_support_format_gnutar(a);
    archive_read_support_format_tar(a);
    archive_read_support_compression_gzip(a);

    r = archive_read_open_memory(a, (void*)[archiveData bytes], [archiveData length]);
    if (r != ARCHIVE_OK) {
        NSLog(@"ERROR[%d] in archive_read_open_file(): %s", r, archive_error_string(a));
        return;
    }
    for (;;) {
        r = archive_read_next_header(a, &entry);
        if (r == ARCHIVE_EOF) {
            break;
        }
        if (r != ARCHIVE_OK) {
            NSLog(@"ERROR[%d] in archive_read_next_header(): %s", r, archive_error_string(a));
            return;
        }
        entry_path = archive_entry_pathname(entry);

        NSString* path = [baseDir stringByAppendingPathComponent: [NSString stringWithUTF8String: entry_path]];
        NSLog(@"Tarball Entry: %s", entry_path);

        // Create the file and blank it out
        [[NSFileManager defaultManager] createFileAtPath: path contents:[[NSMutableData alloc] init] attributes:nil];
        // Actually write the file
        file = [NSFileHandle fileHandleForWritingAtPath:path];
        r = archive_read_data_into_fd(a, [file fileDescriptor]);
        if (r != ARCHIVE_OK) {
            NSLog(@"ERROR[%d] in archive_read_data_into_fd(): %s", r, archive_error_string(a));
            return;
        }
        [file closeFile];
    }
    r = archive_read_close(a);
    if (r != ARCHIVE_OK) {
        NSLog(@"ERROR[%d] in archive_read_close(): %s", r, archive_error_string(a));
        return;
    }
}

--- Dave

清引 2024-08-05 11:25:07

iOS 上预装了 libarchive。

libarchive comes preinstalled on iOS.

罪歌 2024-08-05 11:25:07

似乎有两个更现代的库,它们都可以作为 Cocoapods 提供:

  • NVHTarGzip:支持进度报告,以及有同步和异步两种方法。 不支持tar写入。
  • tarkit:支持 tar 写入,但没有其他不错的功能。

它们都非常相似,因为它们都基于 Light-Untar-for-iOS< /a>.

There seem to be two more modern libraries, both of them available as Cocoapods:

  • NVHTarGzip: Supports progress reporting, and has both sync and async methods. Doesn't support tar writing.
  • tarkit: Supports tar writing, but doesn't have the other nice features.

Both of them are very similar, as they are both based on Light-Untar-for-iOS.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文