📄 potemkin.c
字号:
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 + -