/* Copyright (c) 1983 Regents of the University of California */
static char sccsid
[] = "@(#)symtab.c 3.6 (Berkeley) 83/03/08";
static struct entry
*freelist
= NIL
;
static struct entry
**entry
;
static long entrytblsize
;
/* used to scale maxino to get inode hash table size */
* Look up an entry by inode number
register struct entry
*ep
;
if (inum
< ROOTINO
|| inum
>= maxino
)
for (ep
= entry
[inum
% entrytblsize
]; ep
!= NIL
; ep
= ep
->e_next
)
* Add an entry into the entry table
if (inum
< ROOTINO
|| inum
>= maxino
)
panic("addino: out of range %d\n", inum
);
epp
= &entry
[inum
% entrytblsize
];
for (np
= np
->e_next
; np
!= NIL
; np
= np
->e_next
)
badentry(np
, "duplicate inum");
* Delete an entry from the entry table
register struct entry
*next
;
if (inum
< ROOTINO
|| inum
>= maxino
)
panic("deleteino: out of range %d\n", inum
);
prev
= &entry
[inum
% entrytblsize
];
for (next
= *prev
; next
!= NIL
; next
= next
->e_next
) {
if (next
->e_ino
== inum
) {
panic("deleteino: %d not found\n", inum
);
* Look up an entry by name
register struct entry
*ep
;
for (ep
= lookupino(ROOTINO
); ep
!= NIL
; ep
= ep
->e_entries
) {
for (np
= buf
; *cp
!= '/' && *cp
!= '\0'; )
for ( ; ep
!= NIL
; ep
= ep
->e_sibling
)
if (strcmp(ep
->e_name
, buf
) == 0)
* Look up the parent of a pathname
tailindex
= rindex(name
, '/');
panic("%s is not a directory\n", name
);
* Determine the current pathname of a node or leaf
register struct entry
*ep
;
static char namebuf
[BUFSIZ
];
for (cp
= &namebuf
[BUFSIZ
- 2]; cp
> &namebuf
[ep
->e_namlen
]; ) {
bcopy(ep
->e_name
, cp
, (long)ep
->e_namlen
);
if (ep
== lookupino(ROOTINO
))
panic("%s: pathname too long\n", cp
);
* add an entry to the symbol table
addentry(name
, inum
, type
)
register struct entry
*np
, *ep
;
bzero((char *)np
, (long)sizeof(struct entry
));
np
= (struct entry
*)calloc(1, sizeof(struct entry
));
np
->e_type
= type
& ~LINK
;
if (inum
!= ROOTINO
|| lookupino(ROOTINO
) != NIL
)
panic("bad name to addentry %s\n", name
);
np
->e_name
= savename(name
);
np
->e_namlen
= strlen(name
);
np
->e_name
= savename(rindex(name
, '/') + 1);
np
->e_namlen
= strlen(np
->e_name
);
np
->e_sibling
= ep
->e_entries
;
panic("link to non-existant name\n");
np
->e_links
= ep
->e_links
;
if (lookupino(inum
) != NIL
)
panic("duplicate entry\n");
* delete an entry from the symbol table
register struct entry
*ep
;
register struct entry
*np
;
if (ep
->e_flags
!= REMOVED
)
badentry(ep
, "not marked REMOVED");
if (ep
->e_type
== NODE
) {
badentry(ep
, "freeing referenced directory");
if (ep
->e_entries
!= NIL
)
badentry(ep
, "freeing non-empty directory");
np
= lookupino(ep
->e_ino
);
badentry(ep
, "lookupino failed");
addino(ep
->e_ino
, ep
->e_links
);
for (; np
!= NIL
; np
= np
->e_links
) {
np
->e_links
= ep
->e_links
;
badentry(ep
, "link not found");
* Relocate an entry in the tree structure
register struct entry
*ep
;
np
= lookupparent(newname
);
badentry(ep
, "cannot move ROOT");
if (np
!= ep
->e_parent
) {
ep
->e_sibling
= np
->e_entries
;
cp
= rindex(newname
, '/') + 1;
if (ep
->e_flags
& TMPNAME
)
if (ep
->e_namlen
>= len
) {
ep
->e_name
= savename(cp
);
if (cp
[len
- 1] == TMPCHAR
)
* Remove an entry in the tree structure
register struct entry
*ep
;
register struct entry
*np
;
if (np
->e_entries
== ep
) {
np
->e_entries
= ep
->e_sibling
;
for (np
= np
->e_entries
; np
!= NIL
; np
= np
->e_sibling
) {
if (np
->e_sibling
== ep
) {
np
->e_sibling
= ep
->e_sibling
;
badentry(ep
, "cannot find entry in parent list");
* allocate space for a name
len
= (len
+ sizeof(int) - 1) & ~(sizeof(int) - 1);
cp
= malloc((unsigned)len
);
* dump a snapshot of the symbol table
dumpsymtable(filename
, checkpt
)
register struct entry
*ep
, *tep
;
struct entry temp
, *tentry
;
long mynum
= 1, stroff
= 0;
struct symtableheader hdr
;
vprintf(stdout
, "Check pointing the restore\n");
if ((fd
= fopen(filename
, "w")) == NULL
) {
panic("cannot create save file %s for symbol table\n",
* Assign indicies to each entry
* Write out the string entries
for (i
= ROOTINO
; i
< maxino
; i
++) {
for (ep
= lookupino(i
); ep
!= NIL
; ep
= ep
->e_links
) {
fwrite(ep
->e_name
, sizeof(char), ep
->e_namlen
+ 2, fd
);
stroff
+= ep
->e_namlen
+ 2;
* start entries on aligned boundry
fseek(fd
, ((stroff
+ 3) & ~3), 0);
* Convert pointers to indexes, and output
for (i
= ROOTINO
; i
< maxino
; i
++) {
for (ep
= lookupino(i
); ep
!= NIL
; ep
= ep
->e_links
) {
bcopy((char *)ep
, (char *)tep
, sizeof(struct entry
));
tep
->e_name
= (char *)stroff
;
stroff
+= ep
->e_namlen
+ 2;
tep
->e_parent
= (struct entry
*)ep
->e_parent
->e_index
;
(struct entry
*)ep
->e_links
->e_index
;
if (ep
->e_sibling
!= NIL
)
(struct entry
*)ep
->e_sibling
->e_index
;
if (ep
->e_entries
!= NIL
)
(struct entry
*)ep
->e_entries
->e_index
;
(struct entry
*)ep
->e_next
->e_index
;
fwrite((char *)tep
, sizeof(struct entry
), 1, fd
);
* Convert entry pointers to indexes, and output
for (i
= 0; i
< entrytblsize
; i
++) {
tentry
= (struct entry
*)entry
[i
]->e_index
;
fwrite((char *)&tentry
, sizeof(struct entry
*), 1, fd
);
hdr
.entrytblsize
= entrytblsize
;
hdr
.stringsize
= (stroff
+ 3) & ~3;
fwrite((char *)&hdr
, sizeof(struct symtableheader
), 1, fd
);
panic("output error to file %s writing symbol table\n",
* Initialize a symbol table from a file
register struct entry
*ep
;
struct entry
*baseep
, *lep
;
struct symtableheader hdr
;
vprintf(stdout
, "Initialize symbol table.\n");
entrytblsize
= maxino
/ HASHFACTOR
;
entry
= (struct entry
**)
calloc((unsigned)entrytblsize
, sizeof(struct entry
*));
if (entry
== (struct entry
**)NIL
)
panic("no memory for entry table\n");
(void)addentry(".", ROOTINO
, NODE
);
if ((fd
= open(filename
, 0)) < 0) {
panic("cannot open symbol table file %s\n", filename
);
if (fstat(fd
, &stbuf
) < 0) {
panic("cannot stat symbol table file %s\n", filename
);
tblsize
= stbuf
.st_size
- sizeof(struct symtableheader
);
base
= calloc(sizeof(char *), (unsigned)tblsize
);
panic("cannot allocate space for symbol table\n");
if (read(fd
, base
, (int)tblsize
) < 0 ||
read(fd
, (char *)&hdr
, sizeof(struct symtableheader
)) < 0) {
panic("cannot read symbol table file %s\n", filename
);
* For normal continuation, insure that we are using
* the next incremental tape
if (hdr
.dumpdate
!= dumptime
) {
if (hdr
.dumpdate
< dumptime
)
fprintf(stderr
, "Incremental tape too low\n");
fprintf(stderr
, "Incremental tape too high\n");
* For restart, insure that we are using the same tape
panic("initsymtable called from command %c\n", command
);
entrytblsize
= hdr
.entrytblsize
;
entry
= (struct entry
**)
(base
+ tblsize
- (entrytblsize
* sizeof(struct entry
*)));
baseep
= (struct entry
*)(base
+ hdr
.stringsize
- sizeof(struct entry
));
lep
= (struct entry
*)entry
;
for (i
= 0; i
< entrytblsize
; i
++) {
entry
[i
] = &baseep
[(long)entry
[i
]];
for (ep
= &baseep
[1]; ep
< lep
; ep
++) {
ep
->e_name
= base
+ (long)ep
->e_name
;
ep
->e_parent
= &baseep
[(long)ep
->e_parent
];
if (ep
->e_sibling
!= NIL
)
ep
->e_sibling
= &baseep
[(long)ep
->e_sibling
];
ep
->e_links
= &baseep
[(long)ep
->e_links
];
if (ep
->e_entries
!= NIL
)
ep
->e_entries
= &baseep
[(long)ep
->e_entries
];
ep
->e_next
= &baseep
[(long)ep
->e_next
];