1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * Library of functions to make emulated filesystem as independent as
5   * possible of the host filesystem's capabilities.
6   * This is the Unix version.
7   *
8   * Copyright 1999 Bernd Schmidt
9   */
10 
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13 
14 #include "fsdb.h"
15 
16 /* Return nonzero for any name we can't create on the native filesystem.  */
fsdb_name_invalid(const char * n)17 int fsdb_name_invalid (const char *n)
18 {
19     if (strcmp (n, FSDB_FILE) == 0)
20 	return 1;
21     if (n[0] != '.')
22 	return 0;
23     if (n[1] == '\0')
24 	return 1;
25     return n[1] == '.' && n[2] == '\0';
26 }
27 
28 /* For an a_inode we have newly created based on a filename we found on the
29  * native fs, fill in information about this file/directory.  */
fsdb_fill_file_attrs(a_inode * aino)30 void fsdb_fill_file_attrs (a_inode *aino)
31 {
32     struct stat statbuf;
33     /* This really shouldn't happen...  */
34     if (stat (aino->nname, &statbuf) == -1)
35 	return;
36     aino->dir = S_ISDIR (statbuf.st_mode) ? 1 : 0;
37     aino->amigaos_mode = ((S_IXUSR & statbuf.st_mode ? 0 : A_FIBF_EXECUTE)
38 			  | (S_IWUSR & statbuf.st_mode ? 0 : A_FIBF_WRITE)
39 			  | (S_IRUSR & statbuf.st_mode ? 0 : A_FIBF_READ));
40 }
41 
fsdb_set_file_attrs(a_inode * aino,int mask)42 int fsdb_set_file_attrs (a_inode *aino, int mask)
43 {
44     struct stat statbuf;
45     int mode;
46 
47     if (stat (aino->nname, &statbuf) == -1)
48 	return ERROR_OBJECT_NOT_AROUND;
49 
50     mode = statbuf.st_mode;
51     /* Unix dirs behave differently than AmigaOS ones.  */
52     if (! aino->dir) {
53 	if (mask & A_FIBF_READ)
54 	    mode &= ~S_IRUSR;
55 	else
56 	    mode |= S_IRUSR;
57 
58 	if (mask & A_FIBF_WRITE)
59 	    mode &= ~S_IWUSR;
60 	else
61 	    mode |= S_IWUSR;
62 
63 	if (mask & A_FIBF_EXECUTE)
64 	    mode &= ~S_IXUSR;
65 	else
66 	    mode |= S_IXUSR;
67 
68 	chmod (aino->nname, mode);
69     }
70 
71     aino->amigaos_mode = mask;
72     aino->dirty = 1;
73     return 0;
74 }
75 
76 /* Return nonzero if we can represent the amigaos_mode of AINO within the
77  * native FS.  Return zero if that is not possible.  */
fsdb_mode_representable_p(const a_inode * aino)78 int fsdb_mode_representable_p (const a_inode *aino)
79 {
80     if (aino->dir)
81 	return aino->amigaos_mode == 0;
82     return (aino->amigaos_mode & (A_FIBF_DELETE | A_FIBF_SCRIPT | A_FIBF_PURE)) == 0;
83 }
84 
fsdb_create_unique_nname(a_inode * base,const char * suggestion)85 char *fsdb_create_unique_nname (a_inode *base, const char *suggestion)
86 {
87     char tmp[256] = "__uae___";
88     strncat (tmp, suggestion, 240);
89     for (;;) {
90 	int i;
91 	char *p = build_nname (base->nname, tmp);
92 	if (access (p, R_OK) < 0 && errno == ENOENT) {
93 	    printf ("unique name: %s\n", p);
94 	    return p;
95 	}
96 	free (p);
97 
98 	/* tmpnam isn't reentrant and I don't really want to hack configure
99 	 * right now to see whether tmpnam_r is available...  */
100 	for (i = 0; i < 8; i++) {
101 	    tmp[i] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[random () % 63];
102 	}
103     }
104 }
105