mirror of
https://github.com/digarok/gsplus.git
synced 2025-02-21 09:29:00 +00:00
AFP_AfpInfo attribute support!
This commit is contained in:
parent
a84dd7b424
commit
a2d165840b
@ -70,15 +70,22 @@ struct AFP_Info {
|
|||||||
static void free_directory(struct directory *dd);
|
static void free_directory(struct directory *dd);
|
||||||
static struct directory *read_directory(const char *path, word16 *error);
|
static struct directory *read_directory(const char *path, word16 *error);
|
||||||
|
|
||||||
|
static int file_type_to_finder_info(byte *buffer, word16 file_type, word32 aux_type);
|
||||||
|
static int finder_info_to_filetype(const byte *buffer, word16 *file_type, word32 *aux_type);
|
||||||
|
|
||||||
static void init_afp_info(struct AFP_Info *info) {
|
|
||||||
|
static void afp_init(struct AFP_Info *info, word16 file_type, word32 aux_type) {
|
||||||
//static_assert(sizeof(AFP_Info) == 60, "Incorrect AFP_Info size");
|
//static_assert(sizeof(AFP_Info) == 60, "Incorrect AFP_Info size");
|
||||||
memset(info, 0, sizeof(*info));
|
memset(info, 0, sizeof(*info));
|
||||||
info->magic = 0x00504641;
|
info->magic = 0x00504641;
|
||||||
info->version = 0x00010000;
|
info->version = 0x00010000;
|
||||||
|
info->prodos_file_type = file_type;
|
||||||
|
info->prodos_aux_type = aux_type;
|
||||||
|
if (file_type || aux_type)
|
||||||
|
file_type_to_finder_info(info->finder_info, file_type, aux_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL verify_afp_info(struct AFP_Info *info) {
|
static BOOL afp_verify(struct AFP_Info *info) {
|
||||||
if (!info) return 0;
|
if (!info) return 0;
|
||||||
|
|
||||||
if (info->magic != 0x00504641) return 0;
|
if (info->magic != 0x00504641) return 0;
|
||||||
@ -88,6 +95,32 @@ static BOOL verify_afp_info(struct AFP_Info *info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int afp_to_filetype(struct AFP_Info *info, word16 *file_type, word32 *aux_type) {
|
||||||
|
// check for prodos ftype/auxtype...
|
||||||
|
if (info->prodos_file_type || info->prodos_aux_type) {
|
||||||
|
*file_type = info->prodos_file_type;
|
||||||
|
*aux_type = info->prodos_aux_type;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ok = finder_info_to_filetype(info->finder_info, file_type, aux_type);
|
||||||
|
if (ok == 0) {
|
||||||
|
info->prodos_file_type = *file_type;
|
||||||
|
info->prodos_aux_type = *aux_type;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void afp_synchronize(struct AFP_Info *info) {
|
||||||
|
// if ftype/auxtype is inconsistent between prodos and finder info, use
|
||||||
|
// prodos as source of truth.
|
||||||
|
word16 f;
|
||||||
|
word32 a;
|
||||||
|
if (finder_info_to_filetype(info->finder_info, &f, &a) != 0) return;
|
||||||
|
if (f == info->prodos_file_type && a == info->prodos_aux_type) return;
|
||||||
|
file_type_to_finder_info(info->finder_info, info->prodos_file_type, info->prodos_aux_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define COOKIE_BASE 0x8000
|
#define COOKIE_BASE 0x8000
|
||||||
|
|
||||||
static word32 cookies[32] = {};
|
static word32 cookies[32] = {};
|
||||||
@ -109,7 +142,7 @@ static int alloc_cookie() {
|
|||||||
static int free_cookie(int cookie) {
|
static int free_cookie(int cookie) {
|
||||||
if (cookie < COOKIE_BASE) return -1;
|
if (cookie < COOKIE_BASE) return -1;
|
||||||
cookie -= COOKIE_BASE;
|
cookie -= COOKIE_BASE;
|
||||||
if (cookie >= 32 *32) return -1;
|
if (cookie >= 32 * 32) return -1;
|
||||||
|
|
||||||
int chunk = cookie / 32;
|
int chunk = cookie / 32;
|
||||||
int offset = 1 << (cookie % 32);
|
int offset = 1 << (cookie % 32);
|
||||||
@ -257,7 +290,7 @@ static word32 map_last_error() {
|
|||||||
static struct fd_entry *find_fd(int cookie) {
|
static struct fd_entry *find_fd(int cookie) {
|
||||||
struct fd_entry *head = fd_head;
|
struct fd_entry *head = fd_head;
|
||||||
|
|
||||||
while(head) {
|
while (head) {
|
||||||
if (head->cookie == cookie) return head;
|
if (head->cookie == cookie) return head;
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
@ -315,7 +348,8 @@ struct file_info {
|
|||||||
word32 resource_eof;
|
word32 resource_eof;
|
||||||
word32 resource_blocks;
|
word32 resource_blocks;
|
||||||
int has_fi;
|
int has_fi;
|
||||||
byte finder_info[32];
|
//byte finder_info[32];
|
||||||
|
struct AFP_Info afp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hex(byte c)
|
static int hex(byte c)
|
||||||
@ -327,6 +361,7 @@ static int hex(byte c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int finder_info_to_filetype(const byte *buffer, word16 *file_type, word32 *aux_type) {
|
static int finder_info_to_filetype(const byte *buffer, word16 *file_type, word32 *aux_type) {
|
||||||
|
|
||||||
if (!memcmp("pdos", buffer + 4, 4))
|
if (!memcmp("pdos", buffer + 4, 4))
|
||||||
@ -441,22 +476,22 @@ static int file_type_to_finder_info(byte *buffer, word16 file_type, word32 aux_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void get_file_xinfo(const char *path, struct file_info *fi) {
|
static void get_file_xinfo(const char *path, struct file_info *fi) {
|
||||||
|
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
|
|
||||||
char *p = append_string(path, ":AFP_Resource");
|
char *p = append_string(path, ":AFP_Resource");
|
||||||
FILE_STANDARD_INFO fsi;
|
LARGE_INTEGER size = { 0 };
|
||||||
memset(&fsi, 0, sizeof(fsi));
|
|
||||||
|
|
||||||
h = CreateFile(p, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
h = CreateFile(p, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
GetFileInformationByHandleEx(h, FileStandardInfo, &fsi, sizeof(fsi));
|
GetFileSizeEx(h, &size);
|
||||||
|
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
}
|
}
|
||||||
fi->resource_eof = fsi.EndOfFile.LowPart;
|
fi->resource_eof = size.LowPart;
|
||||||
fi->resource_blocks = (fsi.AllocationSize.LowPart + 511) / 512;
|
fi->resource_blocks = (size.LowPart + 511) / 512;
|
||||||
|
|
||||||
|
|
||||||
p = append_string(path, ":AFP_AfpInfo");
|
p = append_string(path, ":AFP_AfpInfo");
|
||||||
@ -464,18 +499,13 @@ static void get_file_xinfo(const char *path, struct file_info *fi) {
|
|||||||
h = CreateFile(p, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
h = CreateFile(p, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
// ... todo....
|
DWORD read = 0;
|
||||||
/*
|
if (ReadFile(h, &fi->afp, sizeof(struct AFP_Info), &read, NULL) && read == sizeof(struct AFP_Info)) {
|
||||||
int tmp = read(fd, fi->finder_info, 32);
|
if (afp_verify(&fi->afp)) fi->has_fi = 1;
|
||||||
if (tmp == 16 || tmp == 32) {
|
afp_to_filetype(&fi->afp, &fi->file_type, &fi->aux_type);
|
||||||
fi->has_fi = 1;
|
|
||||||
finder_info_to_filetype(fi->finder_info, &fi->file_type, &fi->aux_type);
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static word32 get_file_info(const char *path, struct file_info *fi) {
|
static word32 get_file_info(const char *path, struct file_info *fi) {
|
||||||
@ -547,8 +577,6 @@ static word32 get_file_info(const char *path, struct file_info *fi) {
|
|||||||
|
|
||||||
fi->access = access;
|
fi->access = access;
|
||||||
|
|
||||||
// get file type/aux type
|
|
||||||
|
|
||||||
|
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
return 0;
|
return 0;
|
||||||
@ -564,10 +592,12 @@ static word32 set_file_info(const char *path, struct file_info *fi) {
|
|||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (h == INVALID_HANDLE_VALUE) return map_last_error();
|
if (h == INVALID_HANDLE_VALUE) return map_last_error();
|
||||||
|
|
||||||
// todo -- verify format, update, ...
|
WriteFile(h, &fi->afp, sizeof(struct AFP_Info), NULL, NULL);
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo -- also map hidden / read only attributes.
|
||||||
|
|
||||||
if (fi->create_date.dwLowDateTime || fi->create_date.dwHighDateTime
|
if (fi->create_date.dwLowDateTime || fi->create_date.dwHighDateTime
|
||||||
|| fi->modified_date.dwLowDateTime || fi->modified_date.dwHighDateTime) {
|
|| fi->modified_date.dwLowDateTime || fi->modified_date.dwHighDateTime) {
|
||||||
// SetFileInformationByHandle can modify dates.
|
// SetFileInformationByHandle can modify dates.
|
||||||
@ -582,8 +612,8 @@ static word32 set_file_info(const char *path, struct file_info *fi) {
|
|||||||
|
|
||||||
fbi.CreationTime.LowPart = fi->create_date.dwLowDateTime;
|
fbi.CreationTime.LowPart = fi->create_date.dwLowDateTime;
|
||||||
fbi.CreationTime.HighPart = fi->create_date.dwHighDateTime;
|
fbi.CreationTime.HighPart = fi->create_date.dwHighDateTime;
|
||||||
fbi.ChangeTime.LowPart = fi->modified_date.dwLowDateTime; //?
|
//fbi.ChangeTime.LowPart = fi->modified_date.dwLowDateTime; //?
|
||||||
fbi.ChangeTime.HighPart = fi->modified_date.dwHighDateTime; //?
|
//fbi.ChangeTime.HighPart = fi->modified_date.dwHighDateTime; //?
|
||||||
fbi.LastWriteTime.LowPart = fi->modified_date.dwLowDateTime;
|
fbi.LastWriteTime.LowPart = fi->modified_date.dwLowDateTime;
|
||||||
fbi.LastWriteTime.HighPart = fi->modified_date.dwHighDateTime;
|
fbi.LastWriteTime.HighPart = fi->modified_date.dwHighDateTime;
|
||||||
|
|
||||||
@ -998,7 +1028,8 @@ static word32 fst_create(int class, const char *path) {
|
|||||||
|
|
||||||
|
|
||||||
if (pcount >= 4) {
|
if (pcount >= 4) {
|
||||||
file_type_to_finder_info(fi.finder_info, fi.file_type, fi.aux_type);
|
afp_init
|
||||||
|
(&fi.afp, fi.file_type, fi.aux_type);
|
||||||
fi.has_fi = 1;
|
fi.has_fi = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1010,12 +1041,13 @@ static word32 fst_create(int class, const char *path) {
|
|||||||
fi.storage_type = get_memory16_c(pb + CreateRec_storageType, 0);
|
fi.storage_type = get_memory16_c(pb + CreateRec_storageType, 0);
|
||||||
fi.create_date = get_date_time(pb + CreateRec_createDate);
|
fi.create_date = get_date_time(pb + CreateRec_createDate);
|
||||||
|
|
||||||
file_type_to_finder_info(fi.finder_info, fi.file_type, fi.aux_type);
|
afp_init
|
||||||
|
(&fi.afp, fi.file_type, fi.aux_type);
|
||||||
fi.has_fi = 1;
|
fi.has_fi = 1;
|
||||||
}
|
}
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
if (fi.storage_type == 0x0d) {
|
if (fi.storage_type == 0x0d || fi.storage_type == 0x0f) {
|
||||||
ok = CreateDirectory(path, NULL);
|
ok = CreateDirectory(path, NULL);
|
||||||
if (!ok) return map_last_error();
|
if (!ok) return map_last_error();
|
||||||
return 0;
|
return 0;
|
||||||
@ -1115,11 +1147,14 @@ static word32 fst_set_file_info(int class, const char *path) {
|
|||||||
if (pcount >= 8) option_list = get_memory24_c(pb + FileInfoRecGS_optionList, 0);
|
if (pcount >= 8) option_list = get_memory24_c(pb + FileInfoRecGS_optionList, 0);
|
||||||
// remainder reserved
|
// remainder reserved
|
||||||
|
|
||||||
if (pcount >= 4) {
|
if (fi.has_fi) {
|
||||||
file_type_to_finder_info(fi.finder_info, fi.file_type, fi.aux_type);
|
if (pcount < 4) fi.aux_type = fi.afp.prodos_aux_type;
|
||||||
fi.has_fi = 1;
|
if (pcount < 3) fi.file_type = fi.afp.prodos_file_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fi.access = get_memory16_c(pb + FileRec_fAccess, 0);
|
fi.access = get_memory16_c(pb + FileRec_fAccess, 0);
|
||||||
fi.file_type = get_memory16_c(pb + FileRec_fileType, 0);
|
fi.file_type = get_memory16_c(pb + FileRec_fileType, 0);
|
||||||
@ -1128,11 +1163,20 @@ static word32 fst_set_file_info(int class, const char *path) {
|
|||||||
//fi.storage_type = get_memory32_c(pb + FileRec_storageType, 0);
|
//fi.storage_type = get_memory32_c(pb + FileRec_storageType, 0);
|
||||||
fi.create_date = get_date_time(pb + FileRec_createDate);
|
fi.create_date = get_date_time(pb + FileRec_createDate);
|
||||||
fi.modified_date = get_date_time(pb + FileRec_modDate);
|
fi.modified_date = get_date_time(pb + FileRec_modDate);
|
||||||
|
}
|
||||||
|
|
||||||
file_type_to_finder_info(fi.finder_info, fi.file_type, fi.aux_type);
|
|
||||||
|
if (fi.has_fi) {
|
||||||
|
fi.afp.prodos_file_type = fi.file_type;
|
||||||
|
fi.afp.prodos_aux_type = fi.aux_type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
afp_init(&fi.afp, fi.file_type, fi.aux_type);
|
||||||
fi.has_fi = 1;
|
fi.has_fi = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (option_list) {
|
if (option_list) {
|
||||||
// total size, req size, fst id, data...
|
// total size, req size, fst id, data...
|
||||||
int total_size = get_memory16_c(option_list + 0, 0);
|
int total_size = get_memory16_c(option_list + 0, 0);
|
||||||
@ -1141,12 +1185,19 @@ static word32 fst_set_file_info(int class, const char *path) {
|
|||||||
|
|
||||||
int size = req_size - 6;
|
int size = req_size - 6;
|
||||||
if ((fst_id == proDOSFSID || fst_id == hfsFSID || fst_id == appleShareFSID) && size >= 32) {
|
if ((fst_id == proDOSFSID || fst_id == hfsFSID || fst_id == appleShareFSID) && size >= 32) {
|
||||||
|
|
||||||
|
// this should never happen...
|
||||||
|
if (!fi.has_fi) afp_init(&fi.afp, fi.file_type, fi.aux_type);
|
||||||
fi.has_fi = 1;
|
fi.has_fi = 1;
|
||||||
|
|
||||||
for (int i = 0; i <32; ++i)
|
for (int i = 0; i <32; ++i)
|
||||||
fi.finder_info[i] = get_memory_c(option_list + 6 + i, 0);
|
fi.afp.finder_info[i] = get_memory_c(option_list + 6 + i, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// one more check... if ftype/auxtype doesn't match the ftype/auxtype in finder info
|
||||||
|
// update finder info
|
||||||
|
if (fi.has_fi) afp_synchronize(&fi.afp);
|
||||||
|
|
||||||
return set_file_info(path, &fi);
|
return set_file_info(path, &fi);
|
||||||
}
|
}
|
||||||
@ -1177,7 +1228,7 @@ static word32 fst_get_file_info(int class, const char *path) {
|
|||||||
word16 fst_id = hfsFSID;
|
word16 fst_id = hfsFSID;
|
||||||
//if (fi.storage_type == 0x0f) fst_id = mfsFSID;
|
//if (fi.storage_type == 0x0f) fst_id = mfsFSID;
|
||||||
word32 option_list = get_memory24_c(pb + FileInfoRecGS_optionList, 0);
|
word32 option_list = get_memory24_c(pb + FileInfoRecGS_optionList, 0);
|
||||||
rv = set_option_list(option_list, fst_id, fi.finder_info, fi.has_fi ? 32 : 0);
|
rv = set_option_list(option_list, fst_id, fi.afp.finder_info, fi.has_fi ? 32 : 0);
|
||||||
}
|
}
|
||||||
if (pcount >= 9) set_memory32_c(pb + FileInfoRecGS_eof, fi.eof, 0);
|
if (pcount >= 9) set_memory32_c(pb + FileInfoRecGS_eof, fi.eof, 0);
|
||||||
if (pcount >= 10) set_memory32_c(pb + FileInfoRecGS_blocksUsed, fi.blocks, 0);
|
if (pcount >= 10) set_memory32_c(pb + FileInfoRecGS_blocksUsed, fi.blocks, 0);
|
||||||
@ -1533,7 +1584,7 @@ static word32 fst_open(int class, const char *path) {
|
|||||||
//if (fi.storage_type == 0x0f) fst_id = mfsFSID;
|
//if (fi.storage_type == 0x0f) fst_id = mfsFSID;
|
||||||
|
|
||||||
word32 option_list = get_memory24_c(pb + OpenRecGS_optionList, 0);
|
word32 option_list = get_memory24_c(pb + OpenRecGS_optionList, 0);
|
||||||
word32 tmp = set_option_list(option_list, fst_id, fi.finder_info, fi.has_fi ? 32 : 0);
|
word32 tmp = set_option_list(option_list, fst_id, fi.afp.finder_info, fi.has_fi ? 32 : 0);
|
||||||
if (!rv) rv = tmp;
|
if (!rv) rv = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1987,7 +2038,7 @@ static word32 fst_get_dir_entry(int class) {
|
|||||||
word16 fst_id = hfsFSID;
|
word16 fst_id = hfsFSID;
|
||||||
//if (fi.storage_type == 0x0f) fst_id = mfsFSID;
|
//if (fi.storage_type == 0x0f) fst_id = mfsFSID;
|
||||||
word32 option_list = get_memory24_c(pb + DirEntryRecGS_optionList, 0);
|
word32 option_list = get_memory24_c(pb + DirEntryRecGS_optionList, 0);
|
||||||
word32 tmp = set_option_list(option_list, fst_id, fi.finder_info, fi.has_fi ? 32 : 0);
|
word32 tmp = set_option_list(option_list, fst_id, fi.afp.finder_info, fi.has_fi ? 32 : 0);
|
||||||
if (!rv) rv = tmp;
|
if (!rv) rv = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user