Annotation of uae/src/fsdb.c, revision 1.1.1.9

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.