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

📄 potemkin.c

📁 Coda分布式文件系统源代码。其特色在于可以支持离线文件操作以及在线后的自动更新
💻 C
📖 第 1 页 / 共 4 页
字号:
    path = fid_fullname(fep);    /* Step 1: find the child */    if (!child_exists(path,name)) {	printf("RMDIR: child didn't exist!\n");	out->oh.result = ENOENT;	goto exit;    }    /* Do we know about the child yet? */    iter = ds_list_iter_create(fep->kids);    while ((victimFep = ds_list_iter_next(iter)) != NULL) {	if (!strcmp(victimFep->name, name)) {	    break;	}    }    ds_list_iter_destroy(iter);        if (!victimFep) {	/* 	 * We're going to create a victimFep as a temporary; this is	 * only to make the code simpler.  I know that it isn't	 * that efficient, but...	 */	victimFep = fid_create(name, fep);	created = TRUE;    }    /*      * Get the path for the rmdir call.  Ensure it is a regular file.     * We are *not* allowed to unlink anything else here.     */    path = fid_fullname(victimFep);    if (lstat(path,&sbuf)) {	out->oh.result = errno;	goto exit;    }    switch(sbuf.st_mode & S_IFMT) {    case S_IFREG:	printf("RMDIR: trying to remove a file!\n");	out->oh.result = EINVAL;	goto exit;	break;    case S_IFDIR:	/* OK */	break;#ifndef DJGPP    case S_IFLNK:	printf("RMDIR: trying to remove a symlink!\n");	out->oh.result = EINVAL;	goto exit;	break;    case S_IFSOCK:               /* Can't be any of these */    case S_IFIFO:    case S_IFCHR:    case S_IFBLK:	printf("RMDIR: trying to remove an esoteric!\n");	out->oh.result = EINVAL;	goto exit;	break;#endif    default:	CODA_ASSERT(0);	break;    }    /* Do the rmdir. */    suid = getuid();    sgid = getgid();    CODA_ASSERT(!setgid(cred->cr_groupid));    CODA_ASSERT(!seteuid(cred->cr_uid));    if (rmdir(path)) {	out->oh.result = errno;	CODA_ASSERT(!seteuid(suid));	CODA_ASSERT(!setgid(sgid));	goto exit;    }        /* reset our effictive credentials */    CODA_ASSERT(!seteuid(suid));    CODA_ASSERT(!setgid(sgid));    /* We are now doomed to succeed */    /* If the victimFep was already known, remove it */    if (created == FALSE) {	ds_list_remove(fep->kids, victimFep);	ds_hash_remove(FidTab, victimFep);    }    out->oh.result = 0;     exit:    if (!out->oh.result) {	/* If we succeeded, reclaim this fid */	if (victimFep) free(victimFep);    }    if (path) free(path);    *reply = VC_OUT_NO_DATA;    return;}/* Phase 3 - esoterics */voidDoReadlink(union inputArgs *in, union outputArgs *out, int *reply){    ViceFid            *fp;    fid_ent_t          *fep;    fid_ent_t           dummy;    struct coda_cred       *cred;    char               *path;    int                *count;    uid_t               suid;    gid_t               sgid;    fp = &(in->coda_readlink.VFid);    count = &(out->coda_readlink.count);    cred = &(in->ih.cred);    if (verbose) {	printf("Doing readlink for fid (%x.%x.%x)\n",	       fp->Volume, fp->Vnode, fp->Unique);    }        /* Grab the fid to readlink */    dummy.fid = *fp;    CODA_ASSERT((fep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL);    if (fep->type != C_VLNK) {	printf("Ack!  Trying to readlink something not a symlink!\n");	out->oh.result = ENOTDIR;	goto exit;    }    /* Get the full pathname */    path = fid_fullname(fep);    /* Do the readlink */    suid = getuid();    sgid = getgid();    CODA_ASSERT(!setgid(cred->cr_groupid));    CODA_ASSERT(!seteuid(cred->cr_uid));    out->coda_readlink.data = (char*)VC_OUTSIZE(coda_readlink_out);#ifndef DJGPP    *count = readlink(path,		      (char*)out+(int)out->coda_readlink.data,		      VC_MAXDATASIZE-1);#endif    CODA_ASSERT(!seteuid(suid));    CODA_ASSERT(!setgid(sgid));    if (*count < 0) {	printf("READLINK: readlink of %s failed (%s)\n",	       path, strerror(errno));	out->oh.result = errno;	*count = 0;	goto exit;    }    /* We're done. */    out->oh.result = 0; exit:    if (path) free(path);    *reply = VC_OUTSIZE(coda_readlink_out) + *count;    return;}voidDoIoctl(union inputArgs *in, union outputArgs *out, int *reply){    out->oh.result = EOPNOTSUPP;    return;}voidDoLink(union inputArgs *in, union outputArgs *out, int *reply){    ViceFid         *dfp;    fid_ent_t       *dfep;    ViceFid         *tfp;    fid_ent_t       *tfep;    fid_ent_t        dummy;    fid_ent_t       *lfep=NULL;    struct coda_cred    *cred;    char            *name;    char            *lpath=NULL;    char            *tpath=NULL;    uid_t            suid;    gid_t            sgid;    dfp = &(in->coda_link.destFid);    tfp = &(in->coda_link.sourceFid);    cred = &(in->ih.cred);    CODA_ASSERT((int)in->coda_link.tname == VC_INSIZE(coda_link_in));    name = (char*)in + (int)in->coda_link.tname;        if (verbose) {	printf("Doing hard link to fid (%x.%x.%x) in fid (%x.%x.%x)",	       tfp->Volume, tfp->Vnode, tfp->Unique,	       dfp->Volume, dfp->Vnode, dfp->Unique);	printf(" with name %s\n", name);    }    /*      * For the moment, we'll place the same restrictions on links in     * potemkin as we do in real Coda; hard links can only be to     * things in the same directory.  This is more restrictive than is     * strictly necessary, but so what?  Plus, Coda allows no hard     * links to directories by anyone, so just in case the person     * running the process making this request is root, don't let root     * do that!      */    /* Get the two fep's */    dummy.fid = *tfp;    CODA_ASSERT((tfep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL);    dummy.fid = *dfp;    CODA_ASSERT((dfep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL);    /* Is dfp a directory? */    if (dfep->type != C_VDIR) {	printf("Ack!  Trying to hardlink in a non-directory!\n");	out->oh.result = ENOTDIR;	goto exit;    }    /* Is tfp *not* a directory? */    if (tfep->type == C_VDIR) {	printf("Ack!  Trying to hardlink to a directory!\n");	out->oh.result = EPERM;	goto exit;    }    /* Is tfp a child of dfp? */    if (tfep->parent != dfep) {	printf("Ack!  Cross directory hardlink!\n");	out->oh.result = EXDEV;	goto exit;    }	        /* Don't allow any creation of '.', '..', ''; they already must exist. */    if ((!strcmp(name, ".")) 	|| (!strcmp(name, ".."))	|| (!strcmp(name, "")))    {	printf("CREATE: create of '.', '..' or ''\n");	out->oh.result = EINVAL;	goto exit;    }        /* Don't allow names of the form @XXXXXXXX.XXXXXXXX.XXXXXXXX */    if ((strlen(name) == 27) 	&& (name[0] == '@') 	&& (name[9] == '.') 	&& (name[18] == '.'))    {	out->oh.result = EINVAL;	goto exit;    }    /* Okay: create a new fid entry for the link, and get it's path */    lfep = fid_create(name, dfep);    lpath = fid_fullname(lfep);    tpath = fid_fullname(tfep);    /* Do the link */    suid = getuid();    sgid = getgid();    CODA_ASSERT(!setgid(cred->cr_groupid));    CODA_ASSERT(!seteuid(cred->cr_uid));    if (link(tpath,lpath)) {	out->oh.result = errno;	CODA_ASSERT(!seteuid(suid));	CODA_ASSERT(!setgid(sgid));	goto exit;    }    CODA_ASSERT(!seteuid(suid));    CODA_ASSERT(!setgid(sgid));    /* Link created.  We're in good shape */    /* Touch the file.  Ignore failure */    utimes(lpath,NULL);    /*      * Question: should we represent this as an inc'ed count?  I don't     * think so.  At least, not for now, and I don't think it'll     * matter      */    out->oh.result = 0;    lfep->type = tfep->type;  /* Whatever we linked to. */    CODA_ASSERT(ds_hash_insert(FidTab, lfep));    CODA_ASSERT(ds_list_insert(dfep->kids, lfep));     exit:    /* If the link failed, and we created a fid entry for the link */    if (out->oh.result) {	if (lfep) free(lfep);    }    if (lpath) free(lpath);    if (tpath) free(tpath);    *reply = VC_OUT_NO_DATA;    return;}voidDoSymlink(union inputArgs *in, union outputArgs *out, int *reply){    ViceFid        *fp;    fid_ent_t      *fep;    fid_ent_t      *newFep;    fid_ent_t       dummy;    struct coda_vattr   *attr;    struct coda_cred   *cred;    char           *name;    char           *path=NULL;    char           *contents;    uid_t           suid;    gid_t           sgid;    fp = &(in->coda_symlink.VFid);    attr = &(in->coda_symlink.attr);    contents = (char*)in + (int)(in->coda_symlink.srcname);    name = (char*)in + (int)(in->coda_symlink.tname);    cred = &(in->ih.cred);    if (verbose) {	printf("Trying to create symlink %s in (%x.%x.%x) to %s\n",	       name, fp->Volume, fp->Vnode, fp->Unique, contents);    }	    dummy.fid = *fp;    CODA_ASSERT((fep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL);    if (fep->type != C_VDIR) {	printf("Ack!  Trying to symlink in a non-directory!\n");	out->oh.result = ENOTDIR;	goto exit;    }    /* Don't allow any creation of '.', '..', ''; they already must exist. */    if ((!strcmp(name, ".")) 	|| (!strcmp(name, ".."))	|| (!strcmp(name, "")))    {	printf("CREATE: create of '.', '..' or ''\n");	out->oh.result = EINVAL;	goto exit;    }        /* Don't allow names of the form @XXXXXXXX.XXXXXXXX.XXXXXXXX */    if ((strlen(name) == 27) 	&& (name[0] == '@') 	&& (name[9] == '.') 	&& (name[18] == '.'))    {	out->oh.result = EINVAL;	goto exit;    }    /* Create a temporary fid for this entry. */    /*      * We won't look to see if one exists already, since if it does     * the symlink will fail, and we won't enter it.     */    newFep = fid_create(name, fep);    path = fid_fullname(newFep);        /* Set up credentials */    suid = getuid();    sgid = getgid();    CODA_ASSERT(!setgid(cred->cr_groupid));    CODA_ASSERT(!seteuid(cred->cr_uid));    if (symlink(contents, path)) {	out->oh.result = errno;	CODA_ASSERT(!seteuid(suid));	CODA_ASSERT(!setgid(sgid));	goto exit;    }	        CODA_ASSERT(!seteuid(suid));    CODA_ASSERT(!setgid(sgid));    /* We know it's a symlink */    newFep->type = C_VLNK;    /* We're going to succeed.  Enter the fid, and set return value */    out->oh.result = 0;    CODA_ASSERT(ds_hash_insert(FidTab, newFep));    CODA_ASSERT(ds_list_insert(fep->kids, newFep)); exit:    /* Toast the new vnode if we have an error */    if (out->oh.result && newFep) free(newFep);    if (path) free(path);    *reply = VC_OUT_NO_DATA;    return;}voidDoFsync(union inputArgs *in, union outputArgs *out, int *reply){    ViceFid  *fp;        fp = &(in->coda_fsync.VFid);    /* Fsync always succeeds, for now */    if (verbose) {	printf("Trival fsync for fid (%x.%x.%x)\n", fp->Volume,	       fp->Vnode, fp->Unique);	fflush(stdout);    }    out->oh.result = 0;    *reply = VC_OUT_NO_DATA;    return;}voidDoVget(union inputArgs *in, union outputArgs *out, int *reply){    out->oh.result = EOPNOTSUPP;    return;}/*************************************************** Dispatch */intDispatch(union inputArgs *in, union outputArgs *out, int *reply) {    out->oh.opcode = in->ih.opcode;    out->oh.unique = in->ih.unique;    if (verbose) {	fprintf(stdout,"Opcode %d\tUniqe %d\n", in->ih.opcode, in->ih.unique);    }    fflush(stdout);    switch(in->ih.opcode) {    case CODA_ROOT:	DoRoot(in,out,reply);	break;    case CODA_OPEN:	DoOpen(in,out,reply);	break;    case CODA_CLOSE:	DoClose(in,out,reply);	break;    case CODA_ACCESS:	DoAccess(in,out,reply);	break;    case CODA_LOOKUP:	DoLookup(in,out,reply);	break;    case CODA_GETATTR:	DoGetattr(in,out,reply);	break;    case CODA_CREATE:	DoCreate(in,out,reply);	break;    case CODA_REMOVE:	DoRemove(in,out,reply);	break;    case CODA_SETATTR:	DoSetattr(in,out,reply);	break;    case CODA_MKDIR:	DoMkdir(in,out,reply);	break;    case CODA_RMDIR:	DoRmdir(in,out,reply);	break;    case CODA_READLINK:	DoReadlink(in,out,reply);	break;    case CODA_SYMLINK:	DoSymlink(in,out,reply);	break;    case CODA_LINK:	DoLink(in,out,reply);	break;    case CODA_RENAME:	DoRename(in,out,reply);	break;    case CODA_FSYNC:	DoFsync(in,out,reply);	break;    case CODA_OPEN_BY_PATH:	DoOpenByPath(in,out,reply);	break;    default:	out->oh.result = EOPNOTSUPP;	fprintf(stderr,"** Not Supported **");	fflush(stderr);	*reply = VC_OUT_NO_DATA;	break;    }    return out->oh.result;}/*************************************************** Service */voidService(){    struct timeval     to;    fd_set             readfds;    fd_set             writefds;    fd_set             exceptfds;    int                nfds;    int                rc;    int                reply_size;    char               inbuf[VC_MAXMSGSIZE];    char               outbuf[VC_MAXMSGSIZE];    union inputArgs  *in;    union outputArgs *out;    in = (union inputArgs *) inbuf;    out = (union outputArgs *) outbuf;        while (1) {        /* Set up arguments for the selects */        nfds = KernFD+1;	to.tv_sec = Interval;	to.tv_usec = 0;	/* Select on the kernel fid.  Wait at most Interval secs */	FD_ZERO(&readfds);	FD_SET(KernFD, &readfds);	FD_ZERO(&writefds);	FD_ZERO(&exceptfds);	rc = select(nfds, &readfds, &writefds, &exceptfds, &to);	if (rc == 0) {	    fprintf(stderr,"Interval - no message\n");	    fflush(stderr);	    continue;	} else if (rc < 0) {	    if (errno == EINTR) {		/* I think EINTR won't come back if we are ctrl-c'd.. */#if 0		fprintf(stderr,"We were interrupted\n");		fflush(stderr);		break;#else		continue;#endif	    } else {		perror("select'ing");		exit(-1);	    }	}	/* Read what we can... */	rc = MsgRead(inbuf);	CODA_ASSERT(rc >= 0);	if (rc < VC_IN_NO_DATA) {	    fprintf(stderr,"Message fragment: size %d --",rc);	    perror(NULL);	    continue;	}	/* Dispatch the request */	reply_size = VC_OUT_NO_DATA;	rc = Dispatch(in, out, &reply_size);	if (verbose) {	    if (rc != 0) {		errno = rc;		perror("Dispatch returns error");	    }	}	/* Write out the result */	CODA_ASSERT((rc = MsgWrite(outbuf, reply_size)) >= 0);	if (rc < reply_size) {	    fprintf(stderr,"Wrote fragment %d/%d --", rc, reply_size);	    perror(NULL);	    continue;	}    }}/*************************************************** main */intmain(int argc, char *argv[]){    printf("User id is: %d\n",getuid());    ParseArgs(argc, argv);    Setup();    Service();    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -