/* Copyright (c) 1983 Regents of the University of California */
static char sccsid
[] = "@(#)utilities.c 3.13 (Berkeley) 83/05/19";
* Insure that all the components of a pathname exist.
start
= index(name
, '/');
for (cp
= start
; *cp
!= '\0'; cp
++) {
ep
= addentry(name
, psearch(name
), NODE
);
* Change a name to a unique temporary name.
register struct entry
*ep
;
char oldname
[MAXPATHLEN
];
if (ep
->e_flags
& TMPNAME
)
badentry(ep
, "mktempname: called with TMPNAME");
(void) strcpy(oldname
, myname(ep
));
ep
->e_name
= savename(gentempname(ep
));
ep
->e_namlen
= strlen(ep
->e_name
);
renameit(oldname
, myname(ep
));
* Generate a temporary name for an entry.
static char name
[MAXPATHLEN
];
for (np
= lookupino(ep
->e_ino
); np
!= NIL
&& np
!= ep
; np
= np
->e_links
)
badentry(ep
, "not on ino list");
(void) sprintf(name
, "%s%d%d", TMPHDR
, i
, ep
->e_ino
);
* Rename a file or directory.
if (rename(from
, to
) < 0) {
fprintf(stderr
, "Warning: cannot rename %s to %s", from
, to
);
vprintf(stdout
, "rename %s to %s\n", from
, to
);
* Create a new node (directory).
badentry(np
, "newnode: not a node");
if (mkdir(cp
, 0777) < 0) {
fprintf(stderr
, "Warning: ");
vprintf(stdout
, "Make node %s\n", cp
);
* Remove an old node (directory).
register struct entry
*ep
;
badentry(ep
, "removenode: not a node");
if (ep
->e_entries
!= NIL
)
badentry(ep
, "removenode: non-empty directory");
fprintf(stderr
, "Warning: ");
vprintf(stdout
, "Remove node %s\n", cp
);
register struct entry
*ep
;
badentry(ep
, "removeleaf: not a leaf");
fprintf(stderr
, "Warning: ");
vprintf(stdout
, "Remove leaf %s\n", cp
);
linkit(existing
, new, type
)
if (symlink(existing
, new) < 0) {
"Warning: cannot create symbolic link %s->%s",
} else if (type
== HARDLINK
) {
if (link(existing
, new) < 0) {
"Warning: cannot create hard link %s->%s",
panic("linkit: unknown type %d\n", type
);
vprintf(stdout
, "Create %s link %s->%s\n",
type
== SYMLINK
? "symbolic" : "hard", new, existing
);
* find lowest number file (above "start") that needs to be extracted
register struct entry
*ep
;
for ( ; start
< maxino
; start
++) {
if (ep
== NIL
|| ep
->e_type
== NODE
)
if (ep
->e_flags
& (NEW
|EXTRACT
))
* find highest number file (below "start") that needs to be extracted
register struct entry
*ep
;
for ( ; start
> ROOTINO
; start
--) {
if (ep
== NIL
|| ep
->e_type
== NODE
)
if (ep
->e_flags
& (NEW
|EXTRACT
))
* report on a badly formed entry
register struct entry
*ep
;
fprintf(stderr
, "bad entry: %s\n", msg
);
fprintf(stderr
, "name: %s\n", myname(ep
));
fprintf(stderr
, "parent name %s\n", myname(ep
->e_parent
));
if (ep
->e_sibling
!= NIL
)
fprintf(stderr
, "sibling name: %s\n", myname(ep
->e_sibling
));
if (ep
->e_entries
!= NIL
)
fprintf(stderr
, "next entry name: %s\n", myname(ep
->e_entries
));
fprintf(stderr
, "next link name: %s\n", myname(ep
->e_links
));
fprintf(stderr
, "next hashchain name: %s\n", myname(ep
->e_next
));
fprintf(stderr
, "entry type: %s\n",
ep
->e_type
== NODE
? "NODE" : "LEAF");
fprintf(stderr
, "inode number: %ld\n", ep
->e_ino
);
panic("flags: %s\n", flagvalues(ep
));
* Construct a string indicating the active flag bits of an entry.
register struct entry
*ep
;
static char flagbuf
[BUFSIZ
];
(void) strcpy(flagbuf
, "|NIL");
if (ep
->e_flags
& REMOVED
)
(void) strcat(flagbuf
, "|REMOVED");
if (ep
->e_flags
& TMPNAME
)
(void) strcat(flagbuf
, "|TMPNAME");
if (ep
->e_flags
& EXTRACT
)
(void) strcat(flagbuf
, "|EXTRACT");
(void) strcat(flagbuf
, "|NEW");
(void) strcat(flagbuf
, "|KEEP");
* Check to see if a name is on a dump tape.
if (ino
== 0 || BIT(ino
, dumpmap
) == 0)
fprintf(stderr
, "%s is not on tape\n", name
);
* Canonicalize file names to always start with ``./'' and
* remove any imbedded ".." components.
canon(rawname
, canonname
)
char *rawname
, *canonname
;
if (strcmp(rawname
, ".") == 0 || strncmp(rawname
, "./", 2) == 0)
(void) strcpy(canonname
, "");
else if (rawname
[0] == '/')
(void) strcpy(canonname
, ".");
(void) strcpy(canonname
, "./");
(void) strcat(canonname
, rawname
);
len
= strlen(canonname
) - 1;
if (canonname
[len
] == '/')
* Eliminate extraneous ".." from pathnames.
for (np
= canonname
; *np
!= '\0'; ) {
while (*np
!= '/' && *np
!= '\0')
if (np
- cp
== 2 && strncmp(cp
, "..", 2) == 0) {
while (cp
> &canonname
[1] && *--cp
!= '/')
/* find beginning of name */;
fprintf(stderr
, "%s? ", question
);
fprintf(stderr
, "[yn] ");
while (c
!= '\n' && getc(terminal
) != '\n')
} while (c
!= 'y' && c
!= 'n');
* Read and parse an interactive command.
* The first word on the line is assigned to "cmd". If
* there are no arguments on the command line, then "curdir"
* is returned as the argument. If there are arguments
* on the line they are returned one at a time on each
* successive call to getcmd. Each argument is first assigned
* to "name". If it does not start with "/" the pathname in
* "curdir" is prepended to it. Finally "canon" is called to
* eliminate any embedded ".." components.
getcmd(curdir
, cmd
, name
)
char *curdir
, *cmd
, *name
;
static char input
[BUFSIZ
];
static char *nextarg
= NULL
;
* Check to see if still processing arguments.
* Read a command line and trim off trailing white space.
fprintf(stderr
, "restore > ");
(void) fgets(input
, BUFSIZ
, terminal
);
} while (!feof(terminal
) && input
[0] == '\n');
(void) strcpy(cmd
, "quit");
for (cp
= &input
[strlen(input
) - 2]; *cp
== ' ' || *cp
== '\t'; cp
--)
/* trim off trailing white space and newline */;
* Copy the command into "cmd".
for (cp
= input
; *cp
== ' ' || *cp
== '\t'; cp
++)
for (bp
= cmd
; *cp
!= ' ' && *cp
!= '\t' && *cp
!= '\0'; )
* If no argument, use curdir as the default.
(void) strcpy(name
, curdir
);
* Find the next argument.
for (cp
= nextarg
+ 1; *cp
== ' ' || *cp
== '\t'; cp
++)
for (bp
= cp
; *cp
!= ' ' && *cp
!= '\t' && *cp
!= '\0'; cp
++)
/* skip to end of argument */;
* If it an absolute pathname, canonicalize it and return it.
* For relative pathnames, prepend the current directory to
* it then canonicalize and return it.
(void) strcpy(output
, curdir
);
(void) strcat(output
, "/");
(void) strcat(output
, bp
);
if (reply("restore interrupted, continue") == FAIL
)
if (signal(SIGINT
, onintr
) == SIG_IGN
)
(void) signal(SIGINT
, SIG_IGN
);
if (signal(SIGTERM
, onintr
) == SIG_IGN
)
(void) signal(SIGTERM
, SIG_IGN
);
* handle unexpected inconsistencies
fprintf(stderr
, msg
, d1
, d2
);
if (reply("abort") == GOOD
) {
if (reply("dump core") == GOOD
)