mostly working
This commit is contained in:
parent
ae5ad85338
commit
65ae9be515
|
@ -1,2 +1,2 @@
|
|||
#!/bin/bash
|
||||
/usr/local/bin/fusea2pi $1 -o uid=`id -u` -o gid=`id -g`
|
||||
/usr/local/bin/fusea2pi $1 $2 -o uid=`id -u` -o gid=`id -g`
|
||||
|
|
550
src/fusea2pi.c
550
src/fusea2pi.c
|
@ -99,36 +99,114 @@ static int pifd = 0;
|
|||
#define CACHE_BLOCKS_MAX 16
|
||||
static char cachepath[128] = "";
|
||||
static unsigned char cachedata[512][CACHE_BLOCKS_MAX]; /* !!! Is this enough !!! */
|
||||
static unsigned char volumes[256];
|
||||
/*
|
||||
* Filename & date/time conversion routines.
|
||||
*/
|
||||
static char *unix_name(unsigned char *pname, int type, int aux)
|
||||
static char hexchar(int h)
|
||||
{
|
||||
h &= 0x0F;
|
||||
if (h > 9)
|
||||
h += 'A' - 10;
|
||||
else
|
||||
h += '0';
|
||||
return (char) h;
|
||||
}
|
||||
static char *unix_name(unsigned char *pname, int type, int aux, char *uname)
|
||||
{
|
||||
int l;
|
||||
static char filename[24];
|
||||
char extname[8];
|
||||
if (uname == NULL)
|
||||
uname = filename;
|
||||
l = pname[0] & 0x0F;
|
||||
strncpy(filename, pname + 1, l);
|
||||
// if (type != 0x0F) /* Directory type */
|
||||
// {
|
||||
// sprintf(extname, "#%02X%04X", type, aux);
|
||||
// strcpy(filename + l, extname);
|
||||
// }
|
||||
// else
|
||||
filename[l] = '\0';
|
||||
return filename;
|
||||
strncpy(uname, pname + 1, l);
|
||||
if (type != 0x0F) /* Directory type */
|
||||
{
|
||||
uname[l + 0] = '#';
|
||||
uname[l + 1] = hexchar(type >> 4);
|
||||
uname[l + 2] = hexchar(type);
|
||||
uname[l + 3] = hexchar(aux >> 12);
|
||||
uname[l + 4] = hexchar(aux >> 8);
|
||||
uname[l + 5] = hexchar(aux >> 4);
|
||||
uname[l + 6] = hexchar(aux);
|
||||
uname[l + 7] = '\0';
|
||||
}
|
||||
else
|
||||
uname[l] = '\0';
|
||||
return uname;
|
||||
}
|
||||
|
||||
static unsigned char *prodos_name(char *uname, int *type, int *aux)
|
||||
static int hexval(char h)
|
||||
{
|
||||
int l;
|
||||
static unsigned char filename[25];
|
||||
if ((l = strlen(uname)) > 15)
|
||||
l = 15;
|
||||
strncpy(filename + 1, uname, l);
|
||||
filename[0] = l;
|
||||
filename[l + 1] = '\0';
|
||||
return filename;
|
||||
if (h >= 'a')
|
||||
h -= 'a' - 10;
|
||||
else if (h >= 'A')
|
||||
h -= 'A' - 10;
|
||||
else
|
||||
h -= '0';
|
||||
return h;
|
||||
}
|
||||
static unsigned char *prodos_path(const char *uname, int *type, int *aux, unsigned char *pname)
|
||||
{
|
||||
static unsigned char filename[72];
|
||||
int l = strlen(uname);
|
||||
if (type)
|
||||
*type = 0;
|
||||
if (aux)
|
||||
*aux = 0;
|
||||
if (pname == NULL)
|
||||
pname = filename;
|
||||
if (l > 7 && uname[l - 7] == '#')
|
||||
{
|
||||
if (type)
|
||||
*type = hexval(uname[l - 6]) * 16 + hexval(uname[l - 5]);
|
||||
if (aux)
|
||||
*aux = hexval(uname[l - 4]) * 4096 + hexval(uname[l - 3]) * 256
|
||||
+ hexval(uname[l - 2]) * 16 + hexval(uname[l - 1]);
|
||||
l -= 7;
|
||||
}
|
||||
if (l > 64)
|
||||
l = 64;
|
||||
strncpy(pname + 1, uname, l);
|
||||
pname[0] = l;
|
||||
pname[l + 1] = '\0';
|
||||
return pname;
|
||||
}
|
||||
static unsigned int prodos_time(int year, int month, int day, int hour, int minute)
|
||||
{
|
||||
return (day & 0x1F) | ((month & 0x0F) << 5) | ((year & 0x7F) << 9)
|
||||
| ((minute & 0x3F) << 16) | ((hour & 0x1F) << 24);
|
||||
}
|
||||
static time_t unix_time(unsigned int ptime)
|
||||
{
|
||||
struct tm tm;
|
||||
memset(&tm, 0, sizeof(struct tm));
|
||||
tm.tm_mday = ptime & 0x1F;
|
||||
tm.tm_mon = (ptime >> 5) & 0x0F;
|
||||
tm.tm_year = (ptime >> 9) & 0x7F + 1900;
|
||||
tm.tm_min = (ptime >> 16) & 0x3F;
|
||||
tm.tm_hour = (ptime >> 24) & 0x1F;
|
||||
if (tm.tm_year < 1980)
|
||||
tm.tm_year += 100;
|
||||
return mktime(&tm);
|
||||
}
|
||||
struct stat *unix_stat(struct stat *stbuf, int storage, int access, int blocks, int size, int mod, int create)
|
||||
{
|
||||
memset(stbuf, 0, sizeof(struct stat));
|
||||
if (storage == 0x0F || storage == 0x0D)
|
||||
{
|
||||
stbuf->st_mode = (access & 0xC3 == 0xC3) ? S_IFDIR | 0777 : S_IFDIR | 0444;
|
||||
stbuf->st_nlink = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
stbuf->st_mode = (access & 0xC3 == 0xC3) ? S_IFREG | 0666 : S_IFREG | 0444;
|
||||
stbuf->st_nlink = 1;
|
||||
stbuf->st_blocks = blocks;
|
||||
stbuf->st_size = size;
|
||||
}
|
||||
stbuf->st_atime = stbuf->st_mtime = unix_time(mod);
|
||||
stbuf->st_ctime = unix_time(create);
|
||||
return stbuf;
|
||||
}
|
||||
/*
|
||||
* ProDOS calls to Apple II Pi.
|
||||
|
@ -153,15 +231,11 @@ static int prodos_free_io_buff(int buf)
|
|||
io_buff_mask &= ~(1 << i);
|
||||
return i;
|
||||
}
|
||||
static int prodos_open(const char *path, int *io_buff)
|
||||
static int prodos_open(unsigned char *prodos_path, int *io_buff)
|
||||
{
|
||||
char prodos_path[65], refnum = 0;
|
||||
unsigned char refnum;
|
||||
int result;
|
||||
|
||||
prodos_path[0] = strlen(path);
|
||||
if (path[0] > 64)
|
||||
return -PRODOS_ERR_INVLD_PATH;
|
||||
strcpy(prodos_path+1, path);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER, prodos_path[0] + 1, prodos_path);
|
||||
if (*io_buff == 0)
|
||||
{
|
||||
|
@ -329,33 +403,28 @@ static int prodos_get_eof(int refnum)
|
|||
}
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_on_line(char *data_buff)
|
||||
static int prodos_on_line(int unit, char *data_buff)
|
||||
{
|
||||
int result;
|
||||
|
||||
prodos[PRODOS_CMD] = PRODOS_ON_LINE;
|
||||
prodos[PRODOS_PARAM_CNT] = 2;
|
||||
prodos[PRODOS_PARAMS + 1] = 0;
|
||||
prodos[PRODOS_PARAMS + 1] = (unsigned char) unit;
|
||||
prodos[PRODOS_PARAMS + 2] = (unsigned char) PRODOS_DATA_BUFFER;
|
||||
prodos[PRODOS_PARAMS + 3] = (unsigned char) (PRODOS_DATA_BUFFER >> 8);
|
||||
a2write(pifd, PRODOS_CALL, PRODOS_CALL_LEN + 3, prodos);
|
||||
if (a2call(pifd, PRODOS_CALL, &result))
|
||||
{
|
||||
if (result == 0)
|
||||
a2read(pifd, PRODOS_DATA_BUFFER, 256, data_buff);
|
||||
a2read(pifd, PRODOS_DATA_BUFFER, (unit == 0) ? 256 : 16, data_buff);
|
||||
return -result;
|
||||
}
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_set_file_info(const char *path, int access, int type, int aux, int mod, int create)
|
||||
static int prodos_set_file_info(unsigned char *prodos_path, int access, int type, int aux, int mod, int create)
|
||||
{
|
||||
char prodos_path[65];
|
||||
int result;
|
||||
|
||||
prodos_path[0] = strlen(path);
|
||||
if (prodos_path[0] > 64)
|
||||
return -PRODOS_ERR_INVLD_PATH;
|
||||
strcpy(prodos_path+1, path);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER, prodos_path[0] + 1, prodos_path);
|
||||
prodos[PRODOS_CMD] = PRODOS_SET_FILE_INFO;
|
||||
prodos[PRODOS_PARAM_CNT] = 7;
|
||||
|
@ -377,15 +446,10 @@ static int prodos_set_file_info(const char *path, int access, int type, int aux,
|
|||
return -result;
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_get_file_info(const char *path, int *access, int *type, int *aux, int *storage, int *numblks, int *mod, int *create)
|
||||
static int prodos_get_file_info(unsigned char *prodos_path, int *access, int *type, int *aux, int *storage, int *numblks, int *mod, int *create)
|
||||
{
|
||||
char prodos_path[65];
|
||||
int result;
|
||||
|
||||
prodos_path[0] = strlen(path);
|
||||
if (prodos_path[0] > 64)
|
||||
return -PRODOS_ERR_INVLD_PATH;
|
||||
strcpy(prodos_path+1, path);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER, prodos_path[0] + 1, prodos_path);
|
||||
prodos[PRODOS_CMD] = PRODOS_GET_FILE_INFO;
|
||||
prodos[PRODOS_PARAM_CNT] = 10;
|
||||
|
@ -432,21 +496,12 @@ static int prodos_get_file_info(const char *path, int *access, int *type, int *a
|
|||
}
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_rename(const char *filename, const char *new_filename)
|
||||
static int prodos_rename(unsigned char *from, unsigned char *to)
|
||||
{
|
||||
char prodos_path[65];
|
||||
int result;
|
||||
|
||||
prodos_path[0] = strlen(filename);
|
||||
if (prodos_path[0] > 64)
|
||||
return -PRODOS_ERR_INVLD_PATH;
|
||||
strcpy(prodos_path+1, filename);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER, prodos_path[0] + 1, prodos_path);
|
||||
prodos_path[0] = strlen(new_filename);
|
||||
if (prodos_path[0] > 64)
|
||||
return -PRODOS_ERR_INVLD_PATH;
|
||||
strcpy(prodos_path+1, new_filename);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER+256, prodos_path[0] + 1, prodos_path);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER, from[0] + 1, from);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER + 256, to[0] + 1, to);
|
||||
prodos[PRODOS_CMD] = PRODOS_RENAME;
|
||||
prodos[PRODOS_PARAM_CNT] = 2;
|
||||
prodos[PRODOS_PARAMS + 1] = (unsigned char) PRODOS_DATA_BUFFER;
|
||||
|
@ -458,15 +513,10 @@ static int prodos_rename(const char *filename, const char *new_filename)
|
|||
return -result;
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_destroy(const char *path)
|
||||
static int prodos_destroy(unsigned char *prodos_path)
|
||||
{
|
||||
char prodos_path[65];
|
||||
int result;
|
||||
|
||||
prodos_path[0] = strlen(path);
|
||||
if (prodos_path[0] > 64)
|
||||
return -PRODOS_ERR_INVLD_PATH;
|
||||
strcpy(prodos_path+1, path);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER, prodos_path[0] + 1, prodos_path);
|
||||
prodos[PRODOS_CMD] = PRODOS_DESTROY;
|
||||
prodos[PRODOS_PARAM_CNT] = 1;
|
||||
|
@ -477,15 +527,10 @@ static int prodos_destroy(const char *path)
|
|||
return -result;
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_create(const char *path, char access, char type, int aux, int create)
|
||||
static int prodos_create(unsigned char *prodos_path, char access, char type, int aux, int create)
|
||||
{
|
||||
char prodos_path[65];
|
||||
int result;
|
||||
|
||||
prodos_path[0] = strlen(path);
|
||||
if (prodos_path[0] > 64)
|
||||
return -PRODOS_ERR_INVLD_PATH;
|
||||
strcpy(prodos_path+1, path);
|
||||
a2write(pifd, PRODOS_DATA_BUFFER, prodos_path[0] + 1, prodos_path);
|
||||
prodos[PRODOS_CMD] = PRODOS_CREATE;
|
||||
prodos[PRODOS_PARAM_CNT] = 7;
|
||||
|
@ -505,6 +550,44 @@ static int prodos_create(const char *path, char access, char type, int aux, int
|
|||
return -result;
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_read_block(int unit, char *data_buff, int block_num)
|
||||
{
|
||||
int result;
|
||||
|
||||
prodos[PRODOS_CMD] = PRODOS_READ_BLOCK;
|
||||
prodos[PRODOS_PARAM_CNT] = 3;
|
||||
prodos[PRODOS_PARAMS + 1] = (unsigned char) unit;
|
||||
prodos[PRODOS_PARAMS + 2] = (unsigned char) PRODOS_DATA_BUFFER;
|
||||
prodos[PRODOS_PARAMS + 3] = (unsigned char) (PRODOS_DATA_BUFFER >> 8);
|
||||
prodos[PRODOS_PARAMS + 4] = (unsigned char) block_num;
|
||||
prodos[PRODOS_PARAMS + 5] = (unsigned char) (block_num >> 8);
|
||||
a2write(pifd, PRODOS_CALL, PRODOS_CALL_LEN + 5, prodos);
|
||||
if (a2call(pifd, PRODOS_CALL, &result))
|
||||
{
|
||||
if (result == 0)
|
||||
a2read(pifd, PRODOS_DATA_BUFFER, 512, data_buff);
|
||||
return -result;
|
||||
}
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_write_block(int unit, char *data_buff, int block_num)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (a2write(pifd, PRODOS_DATA_BUFFER, 512, data_buff) != 0)
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
prodos[PRODOS_CMD] = PRODOS_WRITE_BLOCK;
|
||||
prodos[PRODOS_PARAM_CNT] = 3;
|
||||
prodos[PRODOS_PARAMS + 1] = (unsigned char) unit;
|
||||
prodos[PRODOS_PARAMS + 2] = (unsigned char) PRODOS_DATA_BUFFER;
|
||||
prodos[PRODOS_PARAMS + 3] = (unsigned char) (PRODOS_DATA_BUFFER >> 8);
|
||||
prodos[PRODOS_PARAMS + 4] = (unsigned char) block_num;
|
||||
prodos[PRODOS_PARAMS + 5] = (unsigned char) (block_num >> 8);
|
||||
a2write(pifd, PRODOS_CALL, PRODOS_CALL_LEN + 5, prodos);
|
||||
if (a2call(pifd, PRODOS_CALL, &result))
|
||||
return -result;
|
||||
return -PRODOS_ERR_UNKNOWN;
|
||||
}
|
||||
static int prodos_map_errno(int perr)
|
||||
{
|
||||
int uerr = 0;
|
||||
|
@ -555,83 +638,21 @@ static int prodos_map_errno(int perr)
|
|||
/*
|
||||
* FUSE functions.
|
||||
*/
|
||||
struct stat *fillstat(struct stat *stbuf, int storage, int access, int blocks, int size, int mod, int create)
|
||||
{
|
||||
memset(stbuf, 0, sizeof(struct stat));
|
||||
if (storage == 0x0F || storage == 0x0D)
|
||||
{
|
||||
stbuf->st_mode = (access & 0xC3 == 0xC3) ? S_IFDIR | 0777 : S_IFDIR | 0444;
|
||||
stbuf->st_nlink = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
stbuf->st_mode = (access & 0xC3 == 0xC3) ? S_IFREG | 0666 : S_IFREG | 0444;
|
||||
stbuf->st_nlink = 1;
|
||||
stbuf->st_blocks = blocks;
|
||||
stbuf->st_size = size;
|
||||
}
|
||||
return stbuf;
|
||||
}
|
||||
static int cache_get_file_info(const char *path, int *access, int *type, int *aux, int *storage, int *numblks, int *size, int *mod, int *create)
|
||||
{
|
||||
char dirpath[128], filename[32];
|
||||
unsigned char *entry;
|
||||
unsigned char *entry, prodos_name[65];
|
||||
int refnum, iblk, entrylen, entriesblk, filecnt, io_buff = 0;
|
||||
int i, dl, l = strlen(path);
|
||||
|
||||
for (dl = l - 1; dl; dl--)
|
||||
if (path[dl] == '/')
|
||||
break;
|
||||
strncpy(dirpath, path, dl);
|
||||
dirpath[dl] = '\0';
|
||||
//printf("Match path %s to cached dir %s\n", dirpath, cachepath);
|
||||
if (strcmp(dirpath, cachepath) == 0)
|
||||
{
|
||||
strcpy(filename, path + dl + 1);
|
||||
l = l - dl - 1;
|
||||
//printf("Match filename %s len %d\n", filename, l);
|
||||
iblk = 0;
|
||||
entrylen = cachedata[0][0x23];
|
||||
entriesblk = cachedata[0][0x24];
|
||||
filecnt = cachedata[0][0x25] + cachedata[0][0x26] * 256;
|
||||
entry = &cachedata[0][4] + entrylen;
|
||||
do
|
||||
{
|
||||
for (i = (iblk == 0) ? 1 : 0; i < entriesblk && filecnt; i++)
|
||||
{
|
||||
if (entry[0])
|
||||
{
|
||||
entry[(entry[0] & 0x0F) + 1] = 0;
|
||||
//printf("Searching directory entry: %s len %d\n", entry + 1, entry[0] & 0x0F);
|
||||
if ((entry[0] & 0x0F) == l)
|
||||
{
|
||||
//printf("Compare %s with %s\n", entry + 1, filename);
|
||||
if (strncmp(entry + 1, filename, l) == 0)
|
||||
{
|
||||
*storage = entry[0x00] >> 4;
|
||||
*type = entry[0x10];
|
||||
*access = entry[0x1E];
|
||||
*aux = entry[0x1F] + entry[0x20] * 256;
|
||||
*numblks = entry[0x13] + entry[0x14] * 256;
|
||||
*size = entry[0x15] + entry[0x16] * 256 + entry[0x17] * 65536;
|
||||
*mod = entry[0x21] | (entry[0x22] << 8)
|
||||
| (entry[0x23] << 16) | (entry[0x24] << 24);
|
||||
*create = entry[0x18] | (entry[0x19] << 8)
|
||||
| (entry[0x1A] << 16) | (entry[0x1B] << 24);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
entry += entrylen;
|
||||
filecnt--;
|
||||
}
|
||||
}
|
||||
if (++iblk > CACHE_BLOCKS_MAX)
|
||||
break;
|
||||
entry = &cachedata[iblk][4];
|
||||
} while (filecnt != 0);
|
||||
}
|
||||
if (dl == 0)
|
||||
{
|
||||
/*
|
||||
* Volume directory
|
||||
*/
|
||||
*storage = 0x0F;
|
||||
*type = 0x0F;
|
||||
*access = 0xC3;
|
||||
|
@ -641,24 +662,82 @@ static int cache_get_file_info(const char *path, int *access, int *type, int *au
|
|||
*mod = 0;
|
||||
*create = 0;
|
||||
}
|
||||
else if (prodos_get_file_info(path, access, type, aux, storage, numblks, mod, create) == 0)
|
||||
{
|
||||
//printf("prodos: %s access = $%02X, type = $%02X, aux = $%04X, storage = $%02X\n", path, *access, *type, *aux, *storage);
|
||||
if (*storage == 0x0F || *storage == 0x0D)
|
||||
*size = 0;
|
||||
else
|
||||
{
|
||||
if ((refnum = prodos_open(path, &io_buff) > 0))
|
||||
{
|
||||
*size = prodos_get_eof(refnum);
|
||||
prodos_close(refnum, &io_buff);
|
||||
}
|
||||
else
|
||||
return prodos_map_errno(refnum);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
{
|
||||
strncpy(dirpath, path, dl);
|
||||
dirpath[dl] = '\0';
|
||||
//printf("Match path %s to cached dir %s\n", dirpath, cachepath);
|
||||
if (strcmp(dirpath, cachepath) == 0)
|
||||
{
|
||||
strcpy(filename, path + dl + 1);
|
||||
l = l - dl - 1;
|
||||
if (l > 7 && filename[l - 7] == '#')
|
||||
{
|
||||
l -= 7;
|
||||
filename[l] = '\0';
|
||||
}
|
||||
//printf("Match filename %s len %d\n", filename, l);
|
||||
iblk = 0;
|
||||
entrylen = cachedata[0][0x23];
|
||||
entriesblk = cachedata[0][0x24];
|
||||
filecnt = cachedata[0][0x25] + cachedata[0][0x26] * 256;
|
||||
entry = &cachedata[0][4] + entrylen;
|
||||
//printf("Cached entrylen = %d, filecnt = %d\n", entrylen, filecnt);
|
||||
do
|
||||
{
|
||||
for (i = (iblk == 0) ? 1 : 0; i < entriesblk && filecnt; i++)
|
||||
{
|
||||
if (entry[0])
|
||||
{
|
||||
entry[(entry[0] & 0x0F) + 1] = 0;
|
||||
//printf("Searching directory entry: %s len %d\n", entry + 1, entry[0] & 0x0F);
|
||||
if ((entry[0] & 0x0F) == l)
|
||||
{
|
||||
//printf("Compare %s with %s\n", entry + 1, filename);
|
||||
if (strncmp(entry + 1, filename, l) == 0)
|
||||
{
|
||||
*storage = entry[0x00] >> 4;
|
||||
*type = entry[0x10];
|
||||
*access = entry[0x1E];
|
||||
*aux = entry[0x1F] + entry[0x20] * 256;
|
||||
*numblks = entry[0x13] + entry[0x14] * 256;
|
||||
*size = entry[0x15] + entry[0x16] * 256 + entry[0x17] * 65536;
|
||||
*mod = entry[0x21] | (entry[0x22] << 8)
|
||||
| (entry[0x23] << 16) | (entry[0x24] << 24);
|
||||
*create = entry[0x18] | (entry[0x19] << 8)
|
||||
| (entry[0x1A] << 16) | (entry[0x1B] << 24);
|
||||
//printf("Cache hit: %s access = $%02X, type = $%02X, aux = $%04X, storage = $%02X, size = %d\n", filename, *access, *type, *aux, *storage, *size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
entry += entrylen;
|
||||
filecnt--;
|
||||
}
|
||||
}
|
||||
if (++iblk > CACHE_BLOCKS_MAX)
|
||||
break;
|
||||
entry = &cachedata[iblk][4];
|
||||
} while (filecnt != 0);
|
||||
}
|
||||
if (prodos_get_file_info(prodos_path(path, NULL, NULL, prodos_name), access, type, aux, storage, numblks, mod, create) == 0)
|
||||
{
|
||||
//printf("prodos: %s access = $%02X, type = $%02X, aux = $%04X, storage = $%02X\n", path, *access, *type, *aux, *storage);
|
||||
if (*storage == 0x0F || *storage == 0x0D)
|
||||
*size = 0;
|
||||
else
|
||||
{
|
||||
if ((refnum = prodos_open(prodos_name, &io_buff) > 0))
|
||||
{
|
||||
*size = prodos_get_eof(refnum);
|
||||
prodos_close(refnum, &io_buff);
|
||||
}
|
||||
else
|
||||
return prodos_map_errno(refnum);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -670,7 +749,7 @@ static int a2pi_getattr(const char *path, struct stat *stbuf)
|
|||
/*
|
||||
* Root directory of volumes.
|
||||
*/
|
||||
fillstat(stbuf, 0x0F, 0xE3, 0, 0, 0, 0);
|
||||
unix_stat(stbuf, 0x0F, 0xE3, 0, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -681,7 +760,7 @@ static int a2pi_getattr(const char *path, struct stat *stbuf)
|
|||
{
|
||||
if (storage == 0x0F || storage == 0x0D)
|
||||
size = 0;
|
||||
fillstat(stbuf, storage, access, numblks, size, mod, create);
|
||||
unix_stat(stbuf, storage, access, numblks, size, mod, create);
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
|
@ -689,6 +768,25 @@ static int a2pi_getattr(const char *path, struct stat *stbuf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int a2pi_access(const char *path, int mask)
|
||||
{
|
||||
int storage, access, type, numblks, size, aux, mod, create, access_ok = 0;
|
||||
|
||||
if (cache_get_file_info(path, &access, &type, &aux, &storage, &numblks, &size, &mod, &create) == 0)
|
||||
{
|
||||
//printf("Check access bits $%02X to mask 0x%02X\n", access, mask);
|
||||
if ((mask & R_OK) && !(access & 0x01))
|
||||
access_ok = -1;
|
||||
if ((mask & W_OK) && ((access & 0xC2) != 0xC2))
|
||||
access_ok = -1;
|
||||
if ((mask & X_OK) && (type != 0x0F))
|
||||
access_ok = -1;
|
||||
}
|
||||
else
|
||||
access_ok = -1;
|
||||
return access_ok;
|
||||
}
|
||||
|
||||
static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||
off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
|
@ -696,6 +794,7 @@ static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
int storage, access, type, numblks, size, aux, mod, create;
|
||||
int i, l, iscached, refnum, iblk, entrylen, entriesblk, filecnt, io_buff = 0;
|
||||
struct stat stentry;
|
||||
|
||||
(void) offset;
|
||||
(void) fi;
|
||||
if (strcmp(path, "/") == 0)
|
||||
|
@ -703,21 +802,16 @@ static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
/*
|
||||
* Root directory, fill with volume names.
|
||||
*/
|
||||
fillstat(&stentry, 0x0F, 0xC3, 0, 0, 0, 0);
|
||||
unix_stat(&stentry, 0x0F, 0xC3, 0, 0, 0, 0);
|
||||
filler(buf, ".", &stentry, 0);
|
||||
filler(buf, "..", &stentry, 0);
|
||||
if (prodos_on_line(data_buff) == 0)
|
||||
{
|
||||
for (i = 0; i < 256; i += 16)
|
||||
if ((l = data_buff[i] & 0x0F))
|
||||
{
|
||||
strncpy(filename, data_buff + i + 1, l);
|
||||
filename[l] = '\0';
|
||||
filler(buf, filename, &stentry, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
for (i = 0; i < 256; i += 16)
|
||||
if ((l = volumes[i] & 0x0F))
|
||||
{
|
||||
strncpy(filename, volumes + i + 1, l);
|
||||
filename[l] = '\0';
|
||||
filler(buf, filename, &stentry, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -725,9 +819,9 @@ static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
* Read ProDOS directory.
|
||||
*/
|
||||
iscached = (strcmp(path, cachepath) == 0);
|
||||
if (iscached || (refnum = prodos_open(path, &io_buff)) > 0)
|
||||
{
|
||||
fillstat(&stentry, 0x0F, 0xC3, 0, 0, 0, 0);
|
||||
if (iscached || (refnum = prodos_open(prodos_path(path, NULL, NULL, NULL), &io_buff)) > 0)
|
||||
{
|
||||
unix_stat(&stentry, 0x0F, 0xC3, 0, 0, 0, 0);
|
||||
filler(buf, ".", &stentry, 0);
|
||||
filler(buf, "..", &stentry, 0);
|
||||
iblk = 0;
|
||||
|
@ -757,7 +851,7 @@ static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
| (entry[0x23] << 16) | (entry[0x24] << 24);
|
||||
create = entry[0x18] | (entry[0x19] << 8)
|
||||
| (entry[0x1A] << 16) | (entry[0x1B] << 24);
|
||||
filler(buf, unix_name(entry, type, aux), fillstat(&stentry, storage, access, numblks, size, mod, create), 0);
|
||||
filler(buf, unix_name(entry, type, aux, NULL), unix_stat(&stentry, storage, access, numblks, size, mod, create), 0);
|
||||
entry += entrylen;
|
||||
filecnt--;
|
||||
}
|
||||
|
@ -782,20 +876,26 @@ static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||
|
||||
static int a2pi_mkdir(const char *path, mode_t mode)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm = localtime(&now);
|
||||
int create = prodos_time(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
|
||||
cachepath[0] = '\0';
|
||||
return prodos_map_errno(prodos_create(path, 0xE3, 0x0F, 0, 0));
|
||||
return prodos_map_errno(prodos_create(prodos_path(path, NULL, NULL, NULL), 0xE3, 0x0F, create, create));
|
||||
}
|
||||
|
||||
static int a2pi_destroy(const char *path)
|
||||
static int a2pi_remove(const char *path)
|
||||
{
|
||||
cachepath[0] = '\0';
|
||||
return prodos_map_errno(prodos_destroy(path));
|
||||
return prodos_map_errno(prodos_destroy(prodos_path(path, NULL, NULL, NULL)));
|
||||
}
|
||||
|
||||
static int a2pi_rename(const char *from, const char *to)
|
||||
{
|
||||
unsigned char prodos_from[65], prodos_to[65];
|
||||
prodos_path(from, NULL, NULL, prodos_from);
|
||||
prodos_path(to, NULL, NULL, prodos_to);
|
||||
cachepath[0] = '\0';
|
||||
return prodos_map_errno(prodos_rename(from, to));
|
||||
return prodos_map_errno(prodos_rename(prodos_from, prodos_to));
|
||||
}
|
||||
|
||||
static int a2pi_chmod(const char *path, mode_t mode)
|
||||
|
@ -807,7 +907,7 @@ static int a2pi_chmod(const char *path, mode_t mode)
|
|||
access = (mode & 0x04) ? 0x01 : 0x00;
|
||||
access |= (mode & 0x02) ? 0xC2 : 0x00;
|
||||
cachepath[0] = '\0';
|
||||
return prodos_map_errno(prodos_set_file_info(path, access, type, aux, mod, create));
|
||||
return prodos_map_errno(prodos_set_file_info(prodos_path(path, NULL, NULL, NULL), access, type, aux, mod, create));
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -817,7 +917,7 @@ static int a2pi_truncate(const char *path, off_t size)
|
|||
int refnum, io_buff = 0;
|
||||
|
||||
cachepath[0] = '\0';
|
||||
if ((refnum = prodos_open(path, &io_buff)) > 0)
|
||||
if ((refnum = prodos_open(prodos_path(path, NULL, NULL, NULL), &io_buff)) > 0)
|
||||
{
|
||||
prodos_set_eof(refnum, size);
|
||||
return prodos_map_errno(prodos_close(refnum, &io_buff));
|
||||
|
@ -829,7 +929,7 @@ static int a2pi_open(const char *path, struct fuse_file_info *fi)
|
|||
{
|
||||
int refnum, io_buff = 0;
|
||||
|
||||
if ((refnum = prodos_open(path, &io_buff)) > 0)
|
||||
if ((refnum = prodos_open(prodos_path(path, NULL, NULL, NULL), &io_buff)) > 0)
|
||||
{
|
||||
return prodos_map_errno(prodos_close(refnum, &io_buff));
|
||||
}
|
||||
|
@ -840,7 +940,7 @@ static int a2pi_read(const char *path, char *buf, size_t size, off_t offset, str
|
|||
{
|
||||
int refnum, io_buff = 0;
|
||||
|
||||
if ((refnum = prodos_open(path, &io_buff)) > 0)
|
||||
if ((refnum = prodos_open(prodos_path(path, NULL, NULL, NULL), &io_buff)) > 0)
|
||||
{
|
||||
if (offset && prodos_set_mark(refnum, offset) == -PRODOS_ERR_EOF)
|
||||
size = 0;
|
||||
|
@ -859,7 +959,7 @@ static int a2pi_write(const char *path, const char *buf, size_t size, off_t offs
|
|||
int refnum, io_buff = 0;
|
||||
cachepath[0] = '\0';
|
||||
|
||||
if ((refnum = prodos_open(path, &io_buff)) > 0)
|
||||
if ((refnum = prodos_open(prodos_path(path, NULL, NULL, NULL), &io_buff)) > 0)
|
||||
{
|
||||
if (offset && prodos_set_mark(refnum, offset) == -PRODOS_ERR_EOF)
|
||||
size = 0;
|
||||
|
@ -873,27 +973,90 @@ static int a2pi_write(const char *path, const char *buf, size_t size, off_t offs
|
|||
|
||||
static int a2pi_create(const char * path, mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
int refnum, io_buff = 0;
|
||||
unsigned char prodos_name[65];
|
||||
int refnum, type, aux, io_buff = 0;
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm = localtime(&now);
|
||||
int create = prodos_time(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
|
||||
cachepath[0] = '\0';
|
||||
|
||||
if ((refnum = prodos_open(path, &io_buff)) == -PRODOS_ERR_FILE_NOT_FND)
|
||||
return prodos_map_errno(prodos_create(path, 0xC3, 0x04, 0, 0));
|
||||
if ((refnum = prodos_open(prodos_path(path, &type, &aux, prodos_name), &io_buff)) == -PRODOS_ERR_FILE_NOT_FND)
|
||||
return prodos_map_errno(prodos_create(prodos_name, 0xC3, type, aux, create));
|
||||
return prodos_map_errno(refnum);
|
||||
}
|
||||
|
||||
int a2pi_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
cachepath[0] = '\0';
|
||||
return a2pi_truncate(path, offset);
|
||||
}
|
||||
|
||||
int a2pi_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
|
||||
{
|
||||
return a2pi_getattr(path, stbuf);
|
||||
}
|
||||
|
||||
static int a2pi_statfs(const char *path, struct statvfs *stbuf)
|
||||
{
|
||||
unsigned char voldir[16], voldata[512];
|
||||
int i, storage, access, type, numblks, aux, mod, create;
|
||||
|
||||
memset(stbuf, 0, sizeof(struct statvfs));
|
||||
/*
|
||||
* Copy first element of path = volume directory.
|
||||
*/
|
||||
voldir[1] = '/';
|
||||
for (i = 1; path[i] && path[i] != '/'; i++)
|
||||
voldir[i + 1] = path[i];
|
||||
voldir[0] = i;
|
||||
if ((prodos_get_file_info(voldir, &access, &type, &aux, &storage, &numblks, &mod, &create)) > 0)
|
||||
{
|
||||
stbuf->f_bsize = 512;
|
||||
stbuf->f_fsid = 0xa2;
|
||||
// stbuf->f_namelen = 22; /* include space for #typeattrib */
|
||||
stbuf->f_blocks = aux;
|
||||
stbuf->f_bfree =
|
||||
stbuf->f_bavail = aux - numblks;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int a2pi_utimens(const char *path, const struct timespec tv[2])
|
||||
{
|
||||
int access, type, aux, storage, size, numblks, mod, create, refnum, io_buff = 0;
|
||||
struct tm *tm = localtime(&tv[0].tv_sec);
|
||||
cachepath[0] = '\0';
|
||||
/*
|
||||
* Get file info.
|
||||
*/
|
||||
if (cache_get_file_info(path, &access, &type, &aux, &storage, &numblks, &size, &mod, &create) == 0)
|
||||
return prodos_map_errno(prodos_set_file_info(prodos_path(path, NULL, NULL, NULL),
|
||||
access,
|
||||
type,
|
||||
aux,
|
||||
prodos_time(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min),
|
||||
create));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static struct fuse_operations a2pi_oper = {
|
||||
.getattr = a2pi_getattr,
|
||||
.readdir = a2pi_readdir,
|
||||
.mkdir = a2pi_mkdir,
|
||||
.unlink = a2pi_destroy,
|
||||
.rmdir = a2pi_destroy,
|
||||
.rename = a2pi_rename,
|
||||
.chmod = a2pi_chmod,
|
||||
.truncate = a2pi_truncate,
|
||||
.open = a2pi_open,
|
||||
.read = a2pi_read,
|
||||
.write = a2pi_write,
|
||||
.create = a2pi_create,
|
||||
.getattr = a2pi_getattr,
|
||||
.access = a2pi_access,
|
||||
.readdir = a2pi_readdir,
|
||||
.mkdir = a2pi_mkdir,
|
||||
.unlink = a2pi_remove,
|
||||
.rmdir = a2pi_remove,
|
||||
.rename = a2pi_rename,
|
||||
.chmod = a2pi_chmod,
|
||||
.truncate = a2pi_truncate,
|
||||
.open = a2pi_open,
|
||||
.read = a2pi_read,
|
||||
.write = a2pi_write,
|
||||
.create = a2pi_create,
|
||||
.ftruncate = a2pi_ftruncate,
|
||||
.fgetattr = a2pi_fgetattr,
|
||||
.statfs = a2pi_statfs,
|
||||
.utimens = a2pi_utimens,
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -905,6 +1068,7 @@ int main(int argc, char *argv[])
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
prodos_close(0, NULL);
|
||||
prodos_on_line(0, volumes);
|
||||
umask(0);
|
||||
return fuse_main(argc, argv, &a2pi_oper, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue