|
|
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) ! 132: return 0; ! 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) ! 152: return 0; ! 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) ! 172: return 0; ! 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); ! 225: if (aino->needs_dbentry != aino->has_dbentry) ! 226: changes_needed = 1; ! 227: else if (! aino->needs_dbentry) ! 228: aino->dirty = 0; ! 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.