|
|
1.1 root 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: *
7: * Copyright 1999 Bernd Schmidt
8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include "config.h"
14: #include "threaddep/penguin.h"
15: #include "options.h"
16: #include "uae.h"
17: #include "memory.h"
18: #include "custom.h"
19: #include "readcpu.h"
20: #include "newcpu.h"
21: #include "filesys.h"
22: #include "autoconf.h"
23: #include "compiler.h"
24: #include "fsusage.h"
25: #include "native2amiga.h"
26: #include "scsidev.h"
27: #include "fsdb.h"
28:
29: /* The on-disk format is as follows:
30: * Offset 0, 1 byte, valid
31: * Offset 1, 4 bytes, mode
32: * Offset 5, 257 bytes, aname
33: * Offset 263, 257 bytes, nname
34: * Offset 518, 81 bytes, comment
35: */
36:
37: char *nname_begin (char *nname)
38: {
39: char *p = strrchr (nname, FSDB_DIR_SEPARATOR);
40: if (p)
41: return p + 1;
42: return nname;
43: }
44:
45: /* Find the name REL in directory DIRNAME. If we find a file that
46: * has exactly the same name, return REL. If we find a file that
47: * has the same name when compared case-insensitively, return a
48: * malloced string that contains the name we found. If no file
49: * exists that compares equal to REL, return 0. */
50: char *fsdb_search_dir (const char *dirname, char *rel)
51: {
52: char *p = 0;
53: struct dirent *de;
54: DIR *dir = opendir (dirname);
55:
56: /* This really shouldn't happen... */
57: if (! dir)
58: return 0;
59:
60: while (p == 0 && (de = readdir (dir)) != 0) {
61: if (strcmp (de->d_name, rel) == 0)
62: p = rel;
63: else if (strcasecmp (de->d_name, rel) == 0)
64: p = my_strdup (de->d_name);
65: }
66: closedir (dir);
67: return p;
68: }
69:
70: static FILE *get_fsdb (a_inode *dir, const char *mode)
71: {
72: char *n = build_nname (dir->nname, FSDB_FILE);
73: FILE *f = fopen (n, mode);
74: free (n);
75: return f;
76: }
77:
78: /* Prune the db file the first time this directory is opened in a session. */
79: void fsdb_clean_dir (a_inode *dir)
80: {
81: char buf[1 + 4 + 257 + 257 + 81];
82: char *n = build_nname (dir->nname, FSDB_FILE);
83: FILE *f = fopen (n, "r+b");
84: off_t pos1 = 0, pos2 = 0;
85:
86: if (f == 0)
87: return;
88: for (;; pos2 += sizeof buf) {
89: if (fread (buf, 1, sizeof buf, f) < sizeof buf)
90: break;
91: if (buf[0] == 0)
92: continue;
93: if (pos1 != pos2) {
94: fseek (f, pos1, SEEK_SET);
95: fwrite (buf, 1, sizeof buf, f);
96: fseek (f, pos2 + sizeof buf, SEEK_SET);
97: }
98: pos1 += sizeof buf;
99: }
100: fclose (f);
101: truncate (n, pos1);
102: free (n);
103: }
104:
105: static a_inode *aino_from_buf (a_inode *base, char *buf)
106: {
107: uae_u32 mode;
108: a_inode *aino = (a_inode *) xmalloc (sizeof (a_inode));
109:
110: mode = do_get_mem_long ((uae_u32 *)(buf + 1));
111: buf += 5;
112: aino->aname = my_strdup (buf);
113: buf += 257;
114: aino->nname = build_nname (base->nname, buf);
115: buf += 257;
116: aino->comment = *buf != '\0' ? my_strdup (buf) : 0;
117: fsdb_fill_file_attrs (aino);
118: aino->amigaos_mode = mode;
119: aino->has_dbentry = 1;
120: aino->dirty = 0;
121: return aino;
122: }
123:
124: a_inode *fsdb_lookup_aino_aname (a_inode *base, const char *aname)
125: {
126: FILE *f = get_fsdb (base, "rb");
127: if (f == 0)
128: return 0;
129: for (;;) {
130: char buf[1 + 4 + 257 + 257 + 81];
131: if (fread (buf, 1, sizeof buf, f) < sizeof buf)
1.1.1.2 ! root 132: break;
1.1 root 133: if (buf[0] == 0)
134: continue;
135: if (same_aname (buf + 5, aname)) {
136: fclose (f);
137: return aino_from_buf (base, buf);
138: }
139: }
140: fclose (f);
141: return 0;
142: }
143:
144: a_inode *fsdb_lookup_aino_nname (a_inode *base, const char *nname)
145: {
146: char buf[1 + 4 + 257 + 257 + 81];
147: FILE *f = get_fsdb (base, "rb");
148: if (f == 0)
149: return 0;
150: for (;;) {
151: if (fread (buf, 1, sizeof buf, f) < sizeof buf)
1.1.1.2 ! root 152: break;
1.1 root 153: if (buf[0] == 0)
154: continue;
155: if (strcmp (buf + 5 + 257, nname) == 0) {
156: fclose (f);
157: return aino_from_buf (base, buf);
158: }
159: }
160: fclose (f);
161: return 0;
162: }
163:
164: int fsdb_used_as_nname (a_inode *base, const char *nname)
165: {
166: char buf[1 + 4 + 257 + 257 + 81];
167: FILE *f = get_fsdb (base, "rb");
168: if (f == 0)
169: return 0;
170: for (;;) {
171: if (fread (buf, 1, sizeof buf, f) < sizeof buf)
1.1.1.2 ! root 172: break;
1.1 root 173: if (buf[0] == 0)
174: continue;
175: if (strcmp (buf + 5 + 257, nname) == 0) {
176: fclose (f);
177: return 1;
178: }
179: }
180: fclose (f);
181: return 0;
182: }
183:
184: static int needs_dbentry (a_inode *aino)
185: {
186: const char *an_begin, *nn_begin;
187:
188: if (aino->deleted)
189: return 0;
190:
191: if (! fsdb_mode_representable_p (aino) || aino->comment != 0)
192: return 1;
193:
194: nn_begin = nname_begin (aino->nname);
195: return strcmp (nn_begin, aino->aname) != 0;
196: }
197:
198: static void write_aino (FILE *f, a_inode *aino)
199: {
200: char buf[1 + 4 + 257 + 257 + 81];
201: buf[0] = aino->needs_dbentry;
202: do_put_mem_long ((uae_u32 *)(buf + 1), aino->amigaos_mode);
203: strncpy (buf + 5, aino->aname, 256);
204: buf[5 + 256] = '\0';
205: strncpy (buf + 5 + 257, nname_begin (aino->nname), 256);
206: buf[5 + 257 + 256] = '\0';
207: strncpy (buf + 5 + 2*257, aino->comment ? aino->comment : "", 80);
208: buf[5 + 2 * 257 + 80] = '\0';
209: fwrite (buf, 1, sizeof buf, f);
210: aino->has_dbentry = aino->needs_dbentry;
211: }
212:
213: void fsdb_dir_writeback (a_inode *dir)
214: {
215: FILE *f;
216: int changes_needed = 0;
217: a_inode *aino;
218:
219: /* First pass: clear dirty bits where unnecessary, and see if any work
220: * needs to be done. */
221: for (aino = dir->child; aino; aino = aino->sibling) {
222: if (! aino->dirty)
223: continue;
224: aino->needs_dbentry = needs_dbentry (aino);
1.1.1.2 ! root 225: if (! aino->needs_dbentry)
1.1 root 226: aino->dirty = 0;
1.1.1.2 ! root 227: else
! 228: changes_needed = 1;
1.1 root 229: }
230: if (! changes_needed)
231: return;
232:
233: f = get_fsdb (dir, "r+b");
234: if (f == 0) {
235: f = get_fsdb (dir, "w+b");
236: if (f == 0)
237: /* This shouldn't happen... */
238: return;
239: }
240:
241: for (aino = dir->child; aino; aino = aino->sibling) {
242: off_t pos;
243:
244: if (! aino->dirty)
245: continue;
246: aino->dirty = 0;
247: if (! aino->has_dbentry) {
248: fseek (f, 0, SEEK_END);
249: write_aino (f, aino);
250: continue;
251: }
252:
253: fseek (f, 0, SEEK_SET);
254: pos = 0;
255: for (;;) {
256: char buf[1 + 4 + 257 + 257 + 81];
257: if (fread (buf, 1, sizeof buf, f) < sizeof buf)
258: /* Can't happen... */
259: break;
260: if (strcmp (buf + 5, aino->aname) == 0) {
261: fseek (f, pos, SEEK_SET);
262: write_aino (f, aino);
263: break;
264: }
265: pos += sizeof buf;
266: }
267: }
268: fclose (f);
269: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.