📄 potemkin.c
字号:
/* BLURB gpl Coda File System Release 6 Copyright (c) 1987-2003 Carnegie Mellon University Additional copyrights listed belowThis code is distributed "AS IS" without warranty of any kind underthe terms of the GNU General Public Licence Version 2, as shown in thefile LICENSE. The technical and financial contributors to Coda arelisted in the file CREDITS. Additional copyrights none currently#*/#ifdef HAVE_CONFIG_H#include <config.h>#endif#define _SCALAR_T_#include <stdlib.h>#include <stdio.h>#include "coda_string.h"#include <unistd.h>#include <errno.h>#include <signal.h>#include <sys/types.h>#include <sys/file.h>#include <sys/time.h>#include <sys/stat.h>#include <dirent.h>#include <fcntl.h>#ifdef sun#include <sys/mount.h>#include <sys/mnttab.h>#include <sys/mntent.h>#endif#if defined(DJGPP) || defined(__CYGWIN32__) || defined(__linux__)#include <sys/socket.h>#include <netinet/in.h>#define lstat stat#define seteuid setuid#endif#ifdef __linux__#define KERNEL y#define __KERNEL__ y#define __kernel_fsid_t int#define umode_t int#undef KERNEL#undef __KERNEL__#include <linux/fs.h>#include <mntent.h>#else /* __linux__ */#include <sys/file.h>#include <sys/uio.h>#endif /* __linux__ */#include <ds_list.h>#include <ds_hash.h>#include "vcrcommon.h"#include <cfs/coda.h>/* #include <cfs/cnode.h> */#include "potemkin.h"/* FreeBSD 2.2.5 defines this in rpc/types.h, all others in netinet/in.h */#ifndef INADDR_LOOPBACK#define INADDR_LOOPBACK 0x7f000001#endif/************************************************ Argument globals */char *KernDevice = "/dev/cfs0"; /* -kd */char *RootDir = "\temp"; /* -rd */int FidTabSize = 255; /* -ts */char *MountPt = "/coda"; /* -mp */int Interval = 30; /* -i */int verbose = 0; /* -v *//************************************************ Other globals */ds_hash_t *FidTab; /* Table of known vnodes, by fid */unsigned long Uniq=2; /* Next uniqifier/vnode to assign */unsigned long Volno=1; /* Which volume to use */int KernFD=-1; /* how to contact the kernel */ViceFid *RootFid=NULL; /* Root fid */fid_ent_t *RootFep=NULL; /* Root fid-entry *//************************************************ Zombify */voidzombify(){ int living_dead = 1; unsigned int sleep_interval = 1000000; /* Doesn't matter */ fprintf(stderr,"Zombifying....\n"); fflush(stderr); fflush(stdout); while (living_dead) { sleep(sleep_interval); }} /************************************************ Fid Hash routines */longfid_hash(void *a) { fid_ent_t *f = a; return(f->fid.Unique);}longfid_comp(void *a1, void *a2) { fid_ent_t *f1 = a1; fid_ent_t *f2 = a2; return((long)f1->fid.Unique - (long)f2->fid.Unique);}fid_ent_t *fid_create(char *name, fid_ent_t *parent){ fid_ent_t *result; result = (fid_ent_t *) malloc (sizeof(fid_ent_t)); result->fid.Volume = Volno; result->fid.Vnode = result->fid.Unique = Uniq++; result->type = C_VNON; result->kids = ds_list_create(fid_comp, TRUE, FALSE); result->parent = parent; CODA_ASSERT(strlen(name) <= MAXNAMLEN); strncpy(result->name,name,MAXNAMLEN); /* Ensure that there is a null */ result->name[MAXNAMLEN] = '\0'; return result;}/* * Given a fid, construct it's full name relative to the root. * * Caller is responsible for deallocating return value. */char *fid_fullname(fid_ent_t *fep){ char *result; /* Where we put the answer */ int length=0; /* How long the pathname is so far */ int depth=0; /* How deep the requested fid is */ fid_ent_t *fidlist[MAXNAMLEN]; char *dest; /* Where to copy next component. */ char *src; /* Where to copy component from */ int i; /* * We know that we can't have more than MAXPATHLEN entries, 'cause * each entry is minimally "/" */ result = malloc(sizeof(char)*MAXNAMLEN); dest = result; do { fidlist[depth++] = fep; fep = fep->parent; CODA_ASSERT(depth <= MAXNAMLEN); } while (fep != NULL); for (i=depth-1; i>=0; --i) { if ( i != depth-1 && fidlist[i]->name[i] == '.' && strlen(fidlist[i]->name) == 1) continue; length += strlen(fidlist[i]->name)+1; /* component + '/' or '\0' */ CODA_ASSERT(length < (MAXNAMLEN-1)); src = fidlist[i]->name; while (*src) { *dest++ = *src++; /* component */ } *dest++ = '/'; /* Trailing '/' */ } *--dest = '\0'; /* blow away trailing '/', replace with '\0' */ return result;}/* * fid_assign_type * * takes a fid_ent_t * and a struct stat *, and assigns an appropriate * type to the fid_ent_t's type field based on the mode bits of the * stat buffer. Returns nonzero if the stat buffer's mode bit encode * any of the following types: * * S_IFSOCK, S_IFIFO, S_IFCHR, S_IFBLK */intfid_assign_type(fid_ent_t *fep, struct stat *sbuf) { switch (sbuf->st_mode & S_IFMT) { case S_IFDIR: fep->type = C_VDIR; break; case S_IFREG: fep->type = C_VREG; break;#ifndef DJGPP case S_IFLNK: fep->type = C_VLNK; break; case S_IFSOCK: /* Can't be any of these */ case S_IFIFO: case S_IFCHR: case S_IFBLK: fep->type = C_VBAD; return -1; break;#endif default: CODA_ASSERT(0); break; } return 0;}/* Dumping the FidTab */voidfid_print(FILE *ostr, fid_ent_t *fep){ char *typestr; ds_list_iter_t *i; fid_ent_t *childp; char *fullname; switch (fep->type) { case C_VDIR: typestr = "C_VDIR"; break; case C_VREG: typestr = "C_VREG"; break; case C_VLNK: typestr = "C_VLNK"; break; default: typestr = "????"; break; } fprintf(ostr,"(%x.%x.%x)\t%s\t%s\n", fep->fid.Volume, fep->fid.Vnode, fep->fid.Unique, fep->name, typestr); fullname = fid_fullname(fep); fprintf(ostr,"\t%s\n",fullname); free(fullname); if (fep->parent) { fprintf(ostr,"\tPARENT: (%x.%x.%x)\n", fep->parent->fid.Volume, fep->parent->fid.Vnode, fep->parent->fid.Unique); } fprintf(ostr,"\t***CHILDREN***\n"); i = ds_list_iter_create(fep->kids); while ((childp = ds_list_iter_next(i)) != NULL) { fprintf(ostr,"\t\t(%x.%x.%x)\n", childp->fid.Volume, childp->fid.Vnode, childp->fid.Unique); } ds_list_iter_destroy(i); fprintf(ostr,"\n");}voiddump_fids(int sig, int code){ ds_hash_iter_t *i; fid_ent_t *fep; i = ds_hash_iter_create(FidTab); while ((fep = ds_hash_iter_next(i)) != NULL) { fid_print(stdout,fep); } fflush(stdout);}voidfid_init() { FidTab = ds_hash_create(fid_comp, fid_hash, FidTabSize, TRUE, FALSE);}/************************************************ Argument parsing, etc. */voidusage() { fprintf(stderr,"Usage: potemkin [-kd <kern device>] [-rd <root>]\n"); fprintf(stderr," [-ts <tab size>] [-mp <mount point>]\n"); exit(-1);}voidParseArgs(int argc, char *argv[]) { int i; for (i=1; i < argc; i++) { printf("argv[%d]: %s\n", i, argv[i]); if (!strcmp(argv[i],"-kd")) { if (++i==argc) usage(); KernDevice = argv[i]; } else if (!strcmp(argv[i],"-rd")) { if (++i==argc) usage(); RootDir = argv[i]; } else if (!strcmp(argv[i],"-ts")) { if (++i==argc) usage(); FidTabSize = atoi(argv[i]); } else if (!strcmp(argv[i],"-mp")) { if (++i==argc) usage(); MountPt = argv[i]; } else if (!strcmp(argv[i],"-i")) { if (++i==argc) usage(); Interval = atoi(argv[i]); } else if (!strcmp(argv[i],"-v")) { verbose = 1; } else { usage(); } }}int MsgRead(char *m) {#if defined(DJGPP) || defined(__CYGWIN32__) struct sockaddr_in addr; int len = sizeof(addr); int cc = recvfrom(KernFD, m, (int) (VC_MAXMSGSIZE), 0, (struct sockaddr *) &addr, &len);#else int cc = read(KernFD, m, (int) (VC_MAXMSGSIZE));#endif if (cc < sizeof(struct coda_in_hdr)) return(-1); /* printf("MsgRead: returning %d\n", cc); */ return(cc);}int MsgWrite(char *buf, int size){#if defined(DJGPP) || defined(__CYGWIN32__) struct sockaddr_in addr; int cc; addr.sin_family = AF_INET; addr.sin_port = htons(8001); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); return sendto(KernFD, buf, size, 0, (struct sockaddr *) &addr, sizeof(addr));#else return write(KernFD, buf, size);#endif}/************** Initialization *//* * Setup: -- we need to do the following * * 1) change to the root directory * 2) set up the fid<->file table * 3) Test kernel * 4) Mount on MountPoint */voidSetup() { union outputArgs msg; struct sigaction sa; struct sockaddr_in addr; int rc; /* Step 1: change to root directory */ CODA_ASSERT(!(chdir(RootDir))); /* Step 2: set up the fid<->file table */ fid_init(); /* Step 3: Test the kernel */ /* * Open the kernel. * Construct a purge message and see if we can send it in... */#if defined(DJGPP) || defined(__CYGWIN32__) KernFD = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); printf("Socket KernFD is %d\n", KernFD); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(8000); rc = bind(KernFD, (struct sockaddr *)&addr, sizeof(addr)); if ( rc != 0 ) { printf("Bind returns %d\n", rc); exit(1); }#else KernFD = open(KernDevice, O_RDWR, 0);#endif CODA_ASSERT(KernFD >= 0); msg.oh.opcode = CODA_FLUSH; msg.oh.unique = 0; CODA_ASSERT (MsgWrite((char*)&msg, sizeof(struct coda_out_hdr)) == sizeof(struct coda_out_hdr));#ifdef __linux__ if ( fork() == 0 ) { int error; error = mount("coda", MountPt, "coda", MS_MGC_VAL , &KernDevice); if ( error ) { pid_t parent; perror("Killing parent, mount error:"); parent = getppid(); kill(parent, SIGKILL); exit(1); } else { FILE *fd; struct mntent ent; fd = setmntent("/etc/mtab", "a"); if ( fd > 0 ) { ent.mnt_fsname="Coda"; ent.mnt_dir=MountPt; ent.mnt_type= "coda"; ent.mnt_opts = "rw"; ent.mnt_freq = 0; ent.mnt_passno = 0; error = addmntent(fd, & ent); error = endmntent(fd); exit(0); } } }#endif#ifdef __BSD44__ CODA_ASSERT (!mount(MOUNT_CFS, MountPt, 0, KernDevice));#endif#ifdef sun CODA_ASSERT (!mount(KernDevice, MountPt, MS_DATA, "coda", NULL, 0)); /* Update the /etc mount table entry */ { int lfd, mfd; int lck; FILE *mnttab; char tm[25]; struct mnttab mt; printf ("Trying to mount.\n"); fflush(stdout); lfd = open ("/etc/.mnttab.lock", O_WRONLY|O_CREAT, 0600); CODA_ASSERT (lfd >= 0); lck = lockf(lfd, F_LOCK, 0); CODA_ASSERT (lck == 0); mnttab = fopen(MNTTAB, "a+"); CODA_ASSERT (mnttab != NULL); mt.mnt_special = "CODA"; mt.mnt_mountp = MountPt; mt.mnt_fstype = "CODA"; mt.mnt_mntopts = MNTOPT_RW; mt.mnt_time = tm; sprintf (tm, "%d", time(0)); putmntent(mnttab,&mt); fclose(mnttab); (void) lockf(lfd, F_ULOCK, 0); close(lfd); printf ("Done mounting.\n"); fflush(stdout); }#endif /* Set up a signal handler to dump the contents of the FidTab */ sa.sa_handler = dump_fids;#ifndef DJGPP sa.sa_flags = SA_RESTART;#endif sigemptyset(&sa.sa_mask); /* or -1, who knows? */ CODA_ASSERT (!sigaction(SIGUSR1, &sa, NULL)); /* Set umask to zero */ umask(0);}/*************************************************** utility *//* * child_exists: * given a path (assumed to be a directory) and a filename, returns * non-zero if that filename exists in the directory. */intchild_exists(char *path, char *name) { DIR *dirp; struct dirent *dep; int length; dirp = opendir(path); CODA_ASSERT(dirp); length = strlen(name); do { dep = readdir(dirp); if (dep #if !defined(__linux__) && !defined(sun) && (dep->d_namlen == length) #endif && (!strcmp(dep->d_name, name))) { break; } } while (dep); closedir(dirp); /* If we matched... */ if (dep) { return 1; } return 0;}/* * fill_coda_vattr * * Given a stat structure and a fid for a new vnode, fill in it's * coda_vattr structure. WARNING: fep must be completely filled. */voidfill_vattr(struct stat *sbuf, fid_ent_t *fep, struct coda_vattr *vbuf) { vbuf->va_type = fep->type; vbuf->va_mode = sbuf->st_mode; vbuf->va_nlink = sbuf->st_nlink; vbuf->va_uid = sbuf->st_uid; vbuf->va_gid = sbuf->st_gid; /* vbuf->va_fileid = fep->fid.Vnode; */ /* va_fileid has to be the vnode number of the cache file. Sorry. */ vbuf->va_fileid = sbuf->st_ino; /* vbuf->va_fileid = coda_f2i(&(fep->fid)); */ vbuf->va_size = sbuf->st_size; vbuf->va_blocksize = V_BLKSIZE;#ifndef __BSD44__ vbuf->va_atime.tv_sec = sbuf->st_atime; vbuf->va_mtime.tv_sec = sbuf->st_mtime; vbuf->va_ctime.tv_sec = sbuf->st_ctime;#else vbuf->va_atime = sbuf->st_atimespec; vbuf->va_mtime = sbuf->st_mtimespec; vbuf->va_ctime = sbuf->st_ctimespec; vbuf->va_flags = sbuf->st_flags;#endif vbuf->va_gen = fep->fid.Unique; vbuf->va_rdev = 0; /* Can't have special devices in /coda */ vbuf->va_bytes = sbuf->st_size; /* Should this depend on cache/uncache? */ vbuf->va_filerev = fep->fid.Vnode; }/*************************************************** cfs operations *//* Phase 1 - opening/closing, naming *//* * Root: * in: nothing * out: Fid of root vnode */#define VC_OUTSIZE(name) sizeof(struct name)#define VC_INSIZE(name) sizeof(struct name)#define VC_OUT_NO_DATA sizeof(struct coda_out_hdr)#define VC_IN_NO_DATA sizeof(struct coda_in_hdr)voidDoRoot(union inputArgs *in, union outputArgs *out, int *reply){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -