📄 gbx_archive.c
字号:
/*************************************************************************** archive.c The archive management routines (c) 2000-2004 Beno� Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_ARCHIVE_C#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include "gb_common.h"#include "gb_common_swap.h"#include "gb_error.h"#include "gbx_value.h"#include "gb_limit.h"#include "gb_magic.h"#include "gb_alloc.h"#include "gbx_string.h"#include "gbx_regexp.h"#include "gbx_exec.h"#include "gbx_list.h"#include "gbx_project.h"#include "gbx_archive.h"/*PRIVATE int arch_fd = -1;PRIVATE ARCH_HEADER arch_header;PRIVATE char *arch_string;PRIVATE ARCH_SYMBOL *arch_symbol;*/PUBLIC ARCHIVE *ARCHIVE_main = NULL;PUBLIC ARCHIVE *ARCHIVE_last = NULL;PRIVATE char *arch_pattern = NULL;PRIVATE long arch_index = 0;PRIVATE ARCHIVE *arch_dir = NULL;PRIVATE ARCHIVE *_arch_list = NULL;static bool _swap;PRIVATE void arch_error(const char *msg){ if (msg == NULL) THROW(E_ARCH, strerror(errno)); else THROW(E_ARCH, msg);}PRIVATE void set_pos(ARCHIVE *arch, long pos){ if (lseek(arch->fd, pos, SEEK_SET) < 0) arch_error(NULL);}PRIVATE void read_at(ARCHIVE *arch, long pos, void *buf, long len){ set_pos(arch, pos); if (read(arch->fd, buf, len) != len) arch_error(NULL);}PUBLIC void ARCH_create(const char *path){ ARCHIVE *arch; long len; int i; long pos; /*fprintf(stderr, "Using archive: %s\n", path);*/ ALLOC_ZERO(&arch, sizeof(ARCHIVE), "ARCH_create"); LIST_insert(&_arch_list, arch, &arch->list); arch->fd = open(path, O_RDONLY); if (arch->fd < 0) THROW(E_OPEN, path, strerror(errno)); /* Lecture de l'ent�e */ read_at(arch, 32, &arch->header, sizeof(ARCH_HEADER)); _swap = arch->header.magic != ARCH_MAGIC; if (_swap) { fprintf(stderr, "gbx: Swapping archive\n"); SWAP_longs((long *)&arch->header, 6); } /* Lecture des cha�es */ len = arch->header.pos_table - arch->header.pos_string; if (len <= 0) arch_error("corrupted header"); ALLOC(&arch->string, len, "ARCH_init"); read_at(arch, arch->header.pos_string, arch->string, len); /* Lecture de la table */ len = arch->header.n_symbol * sizeof(ARCH_SYMBOL); if (len <= 0) arch_error("corrupted header"); ALLOC(&arch->symbol, len, "ARCH_init"); read_at(arch, arch->header.pos_table, arch->symbol, len); /* Relocation des cha�es */ pos = 0; for (i = 0; i < arch->header.n_symbol; i++) { if (_swap) { SWAP_short((short *)&arch->symbol[i].sym.sort); SWAP_short((short *)&arch->symbol[i].sym.len); SWAP_long(&arch->symbol[i].pos); SWAP_long(&arch->symbol[i].len); } arch->symbol[i].sym.name = &arch->string[pos]; pos += arch->symbol[i].sym.len; }}PUBLIC void ARCH_delete(ARCHIVE *arch){ LIST_remove(&_arch_list, arch, &arch->list); FREE(&arch->string, "ARCH_delete"); FREE(&arch->symbol, "ARCH_delete"); close(arch->fd); FREE(&arch, "ARCH_delete");}PUBLIC void ARCH_init(const char *path){ ARCH_create(path); ARCHIVE_main = _arch_list;}PUBLIC void ARCH_exit(void){ while (_arch_list) ARCH_delete(_arch_list); STRING_free(&arch_pattern);}PUBLIC void ARCH_add(const char *path){ const char *arch_path; struct stat info; char *name; if (FILE_is_relative(path)) { arch_path = FILE_cat(FILE_get_dir(PROJECT_path), path, NULL); if (stat(arch_path, &info) == 0) { if (S_ISDIR(info.st_mode)) { STRING_new(&name, FILE_get_name(arch_path), 0); arch_path = FILE_cat(arch_path, name, NULL); STRING_free(&name); } } else arch_path = FILE_cat(PROJECT_exec_path, "bin", path, NULL); } else arch_path = path; if (stat(arch_path, &info) != 0) THROW(E_LIBRARY, path, "File not found"); ARCH_create(arch_path);}PRIVATE bool ARCH_current(ARCHIVE **parch){ ARCHIVE *arch = NULL; /*if (!CP) && EXEC_arch) arch = _arch_list;*/ if (CP) arch = (ARCHIVE *)CP->belong; if (!arch) arch = _arch_list; *parch = arch; return arch != NULL;}PUBLIC bool ARCH_get(const char *path, int len_path, ARCH_FIND *find){ long index; ARCH_SYMBOL *sym; ARCHIVE *arch; if (!ARCH_current(&arch)) return TRUE; if (len_path <= 0) len_path = strlen(path); if (len_path == 0) return TRUE; for(;;) { SYMBOL_find(arch->symbol, arch->header.n_symbol, sizeof(ARCH_SYMBOL), TF_NORMAL, path, len_path, 0, &index); if (index != NO_SYMBOL) break; arch = arch->list.next; if (!arch) return TRUE; } sym = &arch->symbol[index]; find->sym = sym; find->pos = find->sym->pos; find->len = sym->len; find->arch = arch; ARCHIVE_last = arch; return FALSE;}PUBLIC bool ARCH_exist(const char *path){ ARCH_FIND find; return (!ARCH_get(path, 0, &find));}PUBLIC void ARCH_stat(const char *path, FILE_STAT *info){ ARCH_FIND find; struct stat buf; if (!ARCH_get(path, 0, &find)) THROW_SYSTEM(ENOENT, path); fstat(find.arch->fd, &buf); info->type = GB_STAT_FILE; info->mode = 0400; info->size = find.len; info->atime = (long)buf.st_mtime; info->mtime = (long)buf.st_mtime; info->ctime = (long)buf.st_mtime; info->hidden = (*FILE_get_name(path) == '.'); info->uid = buf.st_uid; info->gid = buf.st_gid;}PUBLIC boolean ARCH_read(ARCHIVE *arch, long pos, void *buffer, long len){ if (lseek(arch->fd, pos, SEEK_SET) < 0) return TRUE; if (read(arch->fd, buffer, len) != len) return TRUE; return FALSE;}PUBLIC void ARCH_dir_first(const char *path, const char *pattern){ if (pattern == NULL) pattern = "*"; path = FILE_cat(path, pattern, NULL); if (arch_pattern) STRING_free(&arch_pattern); STRING_new(&arch_pattern, path, FILE_buffer_length()); arch_index = 0; arch_dir = _arch_list;}PUBLIC bool ARCH_dir_next(char **name, long *len){ SYMBOL *sym; /*if (arch_fd < 0) return FILE_dir_next(name, len);*/ if (!arch_dir) return TRUE; for(;;) { if (arch_index >= arch_dir->header.n_symbol) { arch_dir = arch_dir->list.next; if (!arch_dir) return TRUE; else { arch_index = 0; continue; } } sym = (SYMBOL *)&arch_dir->symbol[arch_index]; sym = (SYMBOL *)&arch_dir->symbol[sym->sort]; if (arch_pattern == NULL) break; arch_index++; if (REGEXP_match(arch_pattern, STRING_length(arch_pattern), sym->name, sym->len)) break; } *name = sym->name; *len = sym->len; return FALSE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -