/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1996,1998,2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* These routines maintain the symbol table which tracks the state
* of the file system being restored. They provide lookup by either
* name or inode number. They also provide for creation, deletion,
* and renaming of entries. Because of the dynamic nature of pathnames,
* names should not be saved, but always constructed just before they
* are needed, by calling "myname".
*/
#include "restore.h"
#include <limits.h>
/*
* The following variables define the inode symbol table.
* The primary hash table is dynamically allocated based on
* the number of inodes in the file system (maxino), scaled by
* HASHFACTOR. The variable "entry" points to the hash table;
* the variable "entrytblsize" indicates its size (in entries).
*/
#ifdef __STDC__
static struct entry *lookupparent(char *);
static void removeentry(struct entry *);
#else
static void addino();
static struct entry *lookupparent();
static void removeentry();
#endif
/*
* Look up an entry by inode number
*/
struct entry *
{
return (NIL);
return (ep);
return (NIL);
}
/*
* We now ignore inodes that are out of range. This
* allows us to attempt to proceed in the face of
* a corrupted archive, albeit with future complaints
* about failed inode lookups. We only complain once
* about range problems, to avoid irritating the user
* without providing any useful information. Failed
* lookups have the bogus name, which is useful, so
* they always happen.
*/
static int complained_about_range = 0;
/*
* Add an entry into the entry table
*/
static void
{
if (!complained_about_range) {
"addino", inum);
}
return;
}
if (dflag)
}
/*
* Delete an entry from the entry table. We assume our caller
* arranges for the necessary memory reclamation, if needed.
*/
void
{
if (!complained_about_range) {
"deleteino", inum);
}
return;
}
return;
}
}
}
/*
* Look up an entry by name.
* NOTE: this function handles "complex" pathnames (as returned
* by myname()) for extended file attributes. The name string
* provided to this function should be terminated with *two*
* NULL characters.
*/
struct entry *
char *name;
{
"lookupname");
return (NIL);
}
*np = '\0';
break;
if (*cp++ == '\0') {
if (*cp != '\0') {
/*
* skip over the "./" prefix on all
* extended attribute paths
*/
cp += 2;
}
if (*cp == '\0')
return (ep);
}
break;
}
return (NIL);
}
/*
* Look up the parent of a pathname. This routine accepts complex
* names so the provided name argument must terminate with two NULLs.
*/
static struct entry *
char *name;
{
int xattrparent = 0;
/* find the last component of the complex name */
if (tailindex == 0) {
return (NIL);
/*
* tailindex normaly points to the '/' character
* dividing the path, but in the case of an extended
* attribute transition it will point to the NULL
* separator in front of the attribute path.
*/
xattrparent = 1;
} else {
*tailindex = '\0';
}
return (ep);
}
/*
* Determine the current pathname of a node or leaf.
* The returned pathname will be multiple strings with NULL separators:
*
* ./<path>/entry\0<path>/attrentry\0<path>/...\0\0
* ^ ^ ^ ^
* return pntr entry attr recursive attr terminator
*
* Guaranteed to return a name that fits within MAXCOMPLEXLEN and is
* terminated with two NULLs.
*/
char *
{
char *cp;
return (cp);
*(--cp) = '\0';
else
*(--cp) = '/';
}
return (cp);
}
/*
* Unused symbol table entries are linked together on a freelist
* headed by the following pointer.
*/
/*
* add an entry to the symbol table
*/
struct entry *
char *name;
int type;
{
char *cp;
} else {
gettext("no memory to extend symbol table\n"));
done(1);
}
}
if (inattrspace)
assert(0);
done(1);
}
/* LINTED: savename guarantees that strlen fits in e_namlen */
return (np);
}
/*
* skip to the last part of the complex string: it
* containes the extended attribute file name.
*/
}
else
cp++;
/* LINTED: savename guarantees that strlen will fit */
/*
* Extended attribute root directories must be linked to their
* "parents" via the e_xattrs field. Other entries are simply
* added to their parent directories e_entries list.
*/
/* link this extended attribute root dir to its "parent" */
} else {
/* add this entry to the entry list of the parent dir */
}
/* XXX just bail on this one and continue? */
gettext("link to non-existent name\n"));
done(1);
}
} else if (inum != 0) {
else
}
return (np);
}
/*
* delete an entry from the symbol table
*/
void
{
}
} else {
break;
}
}
}
}
}
/*
* Relocate an entry in the tree structure
*/
void
char *newname;
{
char *cp;
}
/* find the last component of the complex name */
if (cp == (char *)1)
/* LINTED: savename guarantees that strlen will fit */
/* LINTED: result fits in a short */
} else {
/* LINTED: result fits in a short */
}
}
/*
* Remove an entry in the tree structure
*/
static void
{
else
"parent does not reference this xattr tree"));
} else {
break;
}
}
"cannot find entry in parent list"));
}
}
/*
* Table of unused string entries, sorted by length.
*
* Entries are allocated in STRTBLINCR sized pieces so that names
* of similar lengths can use the same entry. The value of STRTBLINCR
* is chosen so that every entry has at least enough space to hold
* a "struct strtbl" header. Thus every entry can be linked onto an
* apprpriate free list.
*
* NB. The macro "allocsize" below assumes that "struct strhdr"
* has a size that is a power of two. Also, an extra byte is
* allocated for the string to provide space for the two NULL
* string terminator required for extended attribute paths.
*/
struct strhdr {
};
/*
* Allocate space for a name. It first looks to see if it already
* has an appropriate sized entry, and if not allocates a new one.
*/
char *
char *name;
{
char *cp;
done(1);
}
if (len > MAXPATHLEN) {
done(1);
}
} else {
/* Note that allocsize() adds 2 for the trailing \0s */
gettext("no space for string table\n"));
done(1);
}
}
/* add an extra null for complex (attribute) name support */
return (cp);
}
/*
* Free space for a name. The resulting entry is linked onto the
* appropriate free list.
*/
void
char *name;
{
/* NULL case should never happen, but might as well be careful */
/*LINTED [name points to at least sizeof (struct strhdr)]*/
}
}
/*
* Useful quantities placed at the end of a dumped symbol table.
*/
struct symtableheader {
int volno;
};
/*
* dump a snapshot of the symbol table
*/
void
char *filename;
int checkpt;
{
ino_t i;
perror("fopen");
gettext("cannot create save file %s for symbol table\n"),
filename);
done(1);
}
/*
* Assign an index to each entry
* Write out the string entries
*/
}
}
/*
* Convert e_name pointers to offsets, other pointers
* to indices, and output
*/
stroff = 0;
/* LINTED: type pun ok */
}
}
/*
* Convert entry pointers to indices, and output
*/
else
}
/* Ought to have a checksum or magic number */
}
perror("fwrite");
filename);
}
}
/*
* Initialize a symbol table from a file
*/
void
char *filename;
{
char *base;
uint_t i;
int fd;
gettext("file system too large\n"));
done(1);
}
/* LINTED: result fits in entrytblsize */
/* LINTED entrytblsize fits in a size_t */
gettext("no memory for entry table\n"));
done(1);
}
/* LINTED: result fits in a short */
return;
}
perror("open");
done(1);
}
perror("stat");
done(1);
}
/*
* The symbol table file is too small so say we can't read it.
*/
done(1);
}
gettext("symbol table file too large\n"));
done(1);
}
/* LINTED tblsize fits in a size_t */
gettext("cannot allocate space for symbol table\n"));
done(1);
}
/* LINTED tblsize fits in a size_t */
perror("read");
done(1);
}
switch (command) {
case 'r':
case 'M':
/*
* For normal continuation, insure that we are using
* the next incremental tape
*/
"Incremental volume too low\n"));
else
"Incremental volume too high\n"));
done(1);
}
break;
case 'R':
/*
* For restart, insure that we are using the same tape
*/
if (!bflag)
break;
default:
gettext("initsymtable called from command %c\n"),
done(1);
/*NOTREACHED*/
}
/*LINTED [pointer cast alignment]*/
gettext("Symbol table file corrupted\n"));
done(1);
}
/*LINTED [rvalue % 4 == 0] */
gettext("Symbol table file corrupted\n"));
done(1);
}
for (i = 0; i < entrytblsize; i++) {
continue;
}
}
}