/* Copyright (c) 1983 Regents of the University of California */
static char sccsid
[] = "@(#)symtab.c 3.4 (Berkeley) 83/02/28";
struct entry
*freelist
= NIL
;
* Look up an entry by inode number
* Add an entry into the entry table
* Delete an entry from the entry table
* 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
;
freelist
= np
->e_sibling
;
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
;
np
= lookupino(ep
->e_ino
);
badentry(ep
, "lookupino failed");
if (ep
->e_flags
!= REMOVED
)
badentry(ep
, "not marked REMOVED");
if (np
->e_type
== NODE
) {
if (np
== ep
&& np
->e_links
!= NIL
)
badentry(ep
, "freeing referenced directory");
if (ep
->e_entries
!= NIL
)
badentry(ep
, "freeing non-empty directory");
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");
if (ep
->e_newname
!= NULL
)
ep
->e_sibling
= freelist
;
* change the number associated with an entry
register struct entry
*np
;
if (lookupino(newinum
) != NIL
)
badentry(ep
, "renumber to active inum");
np
= lookupino(ep
->e_ino
);
badentry(ep
, "lookupino failed");
for (; np
!= NIL
; np
= np
->e_links
)
* 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
cp
= (char *)malloc((unsigned)len
);
* dump a snapshot of the symbol table
dumpsymtable(filename
, checkpt
)
register struct entry
*ep
;
long mynum
= 0, 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
) {
ep
->e_newname
= (char *)mynum
++;
fwrite(ep
->e_name
, sizeof(char), (int)ep
->e_namlen
, fd
);
ep
->e_name
= (char *)stroff
;
* Convert entry pointers to indexes, and output
for (i
= 0; i
< maxino
; i
++) {
entry
[i
] = (struct entry
*)entry
[i
]->e_newname
;
fwrite((char *)entry
, sizeof(struct entry
*), (int)maxino
, fd
);
* Convert pointers to indexes, and output
for (i
= ROOTINO
; i
< maxino
; i
++) {
for (ep
= lookupino(i
); ep
!= NIL
; ep
= next
) {
ep
->e_parent
= (struct entry
*)ep
->e_parent
->e_newname
;
ep
->e_links
= (struct entry
*)ep
->e_links
->e_newname
;
(struct entry
*)ep
->e_sibling
->e_newname
;
(struct entry
*)ep
->e_entries
->e_newname
;
fwrite((char *)ep
, sizeof(struct entry
), 1, fd
);
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");
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
= (char *)malloc((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
.dumptime
!= dumpdate
) {
if (hdr
.dumptime
< dumpdate
)
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
);
entry
= (struct entry
**)(base
+ hdr
.stringsize
);
baseep
= (struct entry
*)(&entry
[maxino
]);
lep
= (struct entry
*)(base
+ tblsize
);
for (i
= 0; i
< maxino
; i
++) {
entry
[i
] = &baseep
[(long)entry
[i
]];
for (ep
= baseep
; ep
< lep
; ep
++) {
ep
->e_name
= base
+ (long)ep
->e_name
;
ep
->e_parent
= &baseep
[(long)ep
->e_parent
];
ep
->e_sibling
= &baseep
[(long)ep
->e_sibling
];
ep
->e_links
= &baseep
[(long)ep
->e_links
];
ep
->e_entries
= &baseep
[(long)ep
->e_entries
];