⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 potemkin.c

📁 Coda分布式文件系统源代码。其特色在于可以支持离线文件操作以及在线后的自动更新
💻 C
📖 第 1 页 / 共 4 页
字号:
/* 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 + -