1
0
Files
2022-09-29 17:59:04 +03:00

313 lines
6.3 KiB
C

#ident "$Id: fsr.c,v 1.1 1999/03/05 23:44:05 cwf Exp $"
/*
* Front-end program for file-system specific fsr's.
* Just figure out which program to execute and exec it. The flags
* are all EFS and the XFS version ignores the one's it doesn't
* support (except for -s).
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <bstring.h>
#include <ctype.h>
#include <mntent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <paths.h>
#include <wait.h>
#include <errno.h>
static void fixpath( void);
static int chkexec( char *);
static void doexec( char *, int, char **);
static void dosystem( char *, int, char **);
static void mallocargv( int, int, char **, int *, char ***);
static void printargv(char *, int, char **); /* DEBUG */
static char *efs_leftofffile = "/var/tmp/.fsrlast";
static char *xfs_leftofffile = "/var/tmp/.fsrlast_xfs";
#define DEBUG 1
#ifdef DEBUG
# define PATHSTR ".:"_PATH_ROOTPATH
#else
# define PATHSTR _PATH_ROOTPATH
#endif /* !DEBUG */
int vflag;
static char *cmd;
int
main(int argc, char **argv)
{
int i;
char *argname;
int optc = 1;
static char efsname[] = MNTTYPE_EFS;
static char xfsname[] = MNTTYPE_XFS;
int xfsargc = 0, efsargc = 0;
char **xfsargv, **efsargv;
struct stat sb;
cmd = argv[0];
fixpath();
/*
* See if both fsr's are there.
* If only one is present then we just run that one.
*/
if (!chkexec(efsname))
doexec(xfsname, argc, argv);
if (!chkexec(xfsname))
doexec(efsname, argc, argv);
/*
* Save the option flags. They need to be passed
* to either fsr_efs or fsr_xfs for each files/dirs/FS's
* on the command line.
*/
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
char *optchar;
optc++;
optchar = &argv[i][1];
while (*optchar != '\0') {
switch (*optchar) {
case 'v':
++vflag;
break;
/*
* Valid EFS options with no optarg's
*/
case 'M':
case 'g':
case 'n':
case 'd':
case 's':
break;
/*
* Valid EFS options with optarg's
*/
case 't':
case 'f':
case 'm':
case 'b':
case 'p':
optc++;
break;
default:
fprintf(stderr,
"usage: %s [-snvg] [-t mins] [-f leftf] [-m mtab]\n",
argv[0]);
fprintf(stderr,
"usage: %s [-snvg] [efsdev | efsdir | efsfile] ...\n",
argv[0]);
fprintf(stderr,
"usage: %s [-v] [xfsmntpt | xfsfile] ...\n", argv[0]);
exit(1);
}
optchar++;
}
}
}
/*
* Loop through the targets and create new arg lists
* for the different fsr commands.
*/
for (i = optc; i < argc; i++) {
argname = argv[i];
if (lstat(argname, &sb) < 0) {
fprintf(stderr, "could not stat: %s: %s\n",
argname, strerror(errno));
continue;
}
if (strcmp(sb.st_fstype,"xfs") == 0) {
if (xfsargc == 0)
mallocargv(optc, argc, argv, &xfsargc, &xfsargv);
xfsargv[xfsargc++] = argname;
} else {
if (efsargc == 0)
mallocargv(optc, argc, argv, &efsargc, &efsargv);
efsargv[efsargc++] = argname;
}
}
if (xfsargc && efsargc) {
dosystem(xfsname, xfsargc, xfsargv);
doexec(efsname, efsargc, efsargv);
} else if (xfsargc) {
doexec(xfsname, xfsargc, xfsargv);
} else if (efsargc) {
doexec(efsname, efsargc, efsargv);
} else {
/*
* full mtab defrag. Choose the exec order by
* inspecting which one was most recently in
* progress and picking the other.
*/
struct stat sb, sb2;
if (lstat(xfs_leftofffile, &sb) < 0) {
dosystem(xfsname, argc, argv);
doexec(efsname, argc, argv);
} else if (lstat(efs_leftofffile, &sb2) < 0) {
dosystem(efsname, argc, argv);
doexec(xfsname, argc, argv);
} else if (sb.st_mtim.tv_sec < sb2.st_mtim.tv_sec) {
dosystem(xfsname, argc, argv);
doexec(efsname, argc, argv);
} else {
dosystem(efsname, argc, argv);
doexec(xfsname, argc, argv);
}
}
return(0);
}
/*
* Make sure that /sbin is in the
* path before execing user supplied mkfs program.
* We set the path to _PATH_ROOTPATH so no security problems can creep in.
*/
void
fixpath(void)
{
char *newpath;
static char prefix[] = "PATH=";
/*
* Allocate enough space for the path and the trailing null.
*/
newpath = malloc(strlen(prefix) + strlen(PATHSTR) + 1);
strcpy(newpath, prefix);
strcat(newpath, PATHSTR);
putenv(newpath);
}
/*
* Malloc a new argv and copy specified args into it.
*/
void
mallocargv(
int copyargs,
int argc,
char **argv,
int *nargc,
char ***nargv)
{
if ((*nargv = malloc(argc * sizeof(*nargv))) == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
bcopy(argv, *nargv, copyargs * sizeof(*argv));
*nargc = copyargs;
}
/*
* Check to see if the executable is there.
*/
int
chkexec(char *fstype)
{
char *dir;
char *name;
int nstrlen;
char *p;
char *path;
char *pn;
int rval = 0;
nstrlen = strlen(fstype) + 5;
name = malloc(nstrlen + 1);
sprintf(name, "fsr_%s", fstype);
p = path = strdup(PATHSTR);
while (dir = strtok(p, ":")) {
pn = malloc(strlen(dir) + nstrlen + 2);
sprintf(pn, "%s/%s", dir, name);
if (access(pn, EX_OK) == 0) {
free(pn);
rval = 1;
break;
}
free(pn);
p = NULL;
}
free(name);
free(path);
return rval;
}
/*
* Construct the name of the program, and exec it.
* If it fails complain and exit.
*/
void
doexec(char *fstype, int argc, char **argv)
{
char *name;
name = malloc(strlen(fstype) + 6);
sprintf(name, "fsr_%s", fstype);
argv[0] = name;
argv[argc] = NULL;
if (vflag)
printargv("doexec", argc, argv);
execvp(name, argv);
perror(name);
exit(1);
}
/*
* Construct the name of the program, fork/exec it,
* and wait for it to return.
*/
void
dosystem(char *fstype, int argc, char **argv)
{
char *name;
int pid;
int error = 0;
#define SMALLBUF 128
char buf[SMALLBUF];
name = malloc(strlen(fstype) + 6);
sprintf(name, "fsr_%s", fstype);
argv[0] = name;
argv[argc] = NULL;
if (vflag)
printargv("dosystem", argc, argv);
pid = fork();
if (pid < 0) {
sprintf(buf, "%s: failed to fork", cmd);
perror(buf);
} else if (pid == 0) {
execvp(name, argv);
sprintf(buf, "%s: %s: failed to exec", cmd, name);
perror(buf);
exit(1);
} else {
wait(&error);
if (WEXITSTATUS(error)) {
exit(1);
}
}
}
void
printargv(char *str, int argc, char **argv)
{
int i;
printf("%s: %s (%d): ", cmd, str, argc);
for (i=0; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
}