redquark-amiberry-rb/src/fsdb_unix.cpp
2017-12-04 15:49:40 +01:00

210 lines
4.9 KiB
C++

/*
* UAE - The Un*x Amiga Emulator
*
* Library of functions to make emulated filesystem as independent as
* possible of the host filesystem's capabilities.
* This is the Unix version.
*
* Copyright 1999 Bernd Schmidt
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include "config.h"
#include "fsdb.h"
#include "uae.h"
/* these are deadly (but I think allowed on the Amiga): */
#define NUM_EVILCHARS 7
static TCHAR evilchars[NUM_EVILCHARS] = { '\\', '*', '?', '\"', '<', '>', '|' };
#define UAEFSDB_BEGINS _T("__uae___")
/* Return nonzero for any name we can't create on the native filesystem. */
static int fsdb_name_invalid_2 (const TCHAR *n, int dir)
{
int i;
int l = _tcslen (n);
/* the reserved fsdb filename */
if (_tcscmp (n, FSDB_FILE) == 0)
return -1;
if (dir) {
if (n[0] == '.' && l == 1)
return -1;
if (n[0] == '.' && n[1] == '.' && l == 2)
return -1;
}
/* these characters are *never* allowed */
for (i = 0; i < NUM_EVILCHARS; i++) {
if (_tcschr (n, evilchars[i]) != 0)
return 1;
}
return 0; /* the filename passed all checks, now it should be ok */
}
int fsdb_name_invalid (const TCHAR *n)
{
int v = fsdb_name_invalid_2 (n, 0);
if (v <= 0)
return v;
write_log (_T("FILESYS: '%s' illegal filename\n"), n);
return v;
}
int fsdb_name_invalid_dir (const TCHAR *n)
{
int v = fsdb_name_invalid_2 (n, 1);
if (v <= 0)
return v;
write_log (_T("FILESYS: '%s' illegal filename\n"), n);
return v;
}
int fsdb_exists (const TCHAR *nname)
{
struct stat statbuf;
return (stat (nname, &statbuf) != -1);
}
/* For an a_inode we have newly created based on a filename we found on the
* native fs, fill in information about this file/directory. */
int fsdb_fill_file_attrs (a_inode *base, a_inode *aino)
{
struct stat statbuf;
/* This really shouldn't happen... */
if (stat (aino->nname, &statbuf) == -1)
return 0;
aino->dir = S_ISDIR (statbuf.st_mode) ? 1 : 0;
aino->amigaos_mode = ((S_IXUSR & statbuf.st_mode ? 0 : A_FIBF_EXECUTE)
| (S_IWUSR & statbuf.st_mode ? 0 : A_FIBF_WRITE)
| (S_IRUSR & statbuf.st_mode ? 0 : A_FIBF_READ));
#if defined(WIN32) || defined(AMIBERRY)
// Always give execute & read permission
// Temporary do this for raspberry...
aino->amigaos_mode &= ~A_FIBF_EXECUTE;
aino->amigaos_mode &= ~A_FIBF_READ;
#endif
return 1;
}
int fsdb_set_file_attrs (a_inode *aino)
{
struct stat statbuf;
int mode;
uae_u32 mask = aino->amigaos_mode;
if (aino->vfso)
return 1;
if (stat (aino->nname, &statbuf) == -1)
return ERROR_OBJECT_NOT_AROUND;
mode = statbuf.st_mode;
if (mask & A_FIBF_READ)
mode &= ~S_IRUSR;
else
mode |= S_IRUSR;
if (mask & A_FIBF_WRITE)
mode &= ~S_IWUSR;
else
mode |= S_IWUSR;
if (mask & A_FIBF_EXECUTE)
mode &= ~S_IXUSR;
else
mode |= S_IXUSR;
chmod (aino->nname, mode);
aino->dirty = 1;
return 0;
}
/* return supported combination */
int fsdb_mode_supported (const a_inode *aino)
{
int mask = aino->amigaos_mode;
if (aino->vfso)
return mask;
if (0 && aino->dir)
return 0;
if (fsdb_mode_representable_p (aino, mask))
return mask;
mask &= ~(A_FIBF_SCRIPT | A_FIBF_READ | A_FIBF_EXECUTE);
if (fsdb_mode_representable_p (aino, mask))
return mask;
mask &= ~A_FIBF_WRITE;
if (fsdb_mode_representable_p (aino, mask))
return mask;
mask &= ~A_FIBF_DELETE;
if (fsdb_mode_representable_p (aino, mask))
return mask;
return 0;
}
/* Return nonzero if we can represent the amigaos_mode of AINO within the
* native FS. Return zero if that is not possible. */
int fsdb_mode_representable_p (const a_inode *aino, int amigaos_mode)
{
int mask = amigaos_mode ^ 15;
if (0 && aino->dir)
return amigaos_mode == 0;
if (aino->vfso)
return 1;
if (mask & A_FIBF_SCRIPT) /* script */
return 0;
if ((mask & 15) == 15) /* xxxxRWED == OK */
return 1;
if (!(mask & A_FIBF_EXECUTE)) /* not executable */
return 0;
if (!(mask & A_FIBF_READ)) /* not readable */
return 0;
if ((mask & 15) == (A_FIBF_READ | A_FIBF_EXECUTE)) /* ----RxEx == ReadOnly */
return 1;
return 0;
}
TCHAR *fsdb_create_unique_nname (a_inode *base, const TCHAR *suggestion)
{
TCHAR *c;
TCHAR tmp[256] = UAEFSDB_BEGINS;
int i;
_tcsncat (tmp, suggestion, 240);
/* replace the evil ones... */
for (i = 0; i < NUM_EVILCHARS; i++)
while ((c = _tcschr (tmp, evilchars[i])) != 0)
*c = '_';
while ((c = _tcschr (tmp, '.')) != 0)
*c = '_';
while ((c = _tcschr (tmp, ' ')) != 0)
*c = '_';
for (;;) {
TCHAR *p = build_nname (base->nname, tmp);
if (access (p, R_OK) < 0 && errno == ENOENT) {
write_log (_T("unique name: %s\n"), p);
return p;
}
xfree (p);
/* tmpnam isn't reentrant and I don't really want to hack configure
* right now to see whether tmpnam_r is available... */
for (i = 0; i < 8; i++) {
tmp[i+8] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[uaerand () % 63];
}
}
}