📄 potemkin.c
字号:
victimFep = fid_create(name, fep); created = TRUE; } /* * Get the path for the unlink 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: break; case S_IFDIR: printf("REMOVE: trying to remove a directory!\n"); out->oh.result = EINVAL; goto exit; break;#ifndef DJGPP case S_IFLNK: /* This might not be okay for symlinks. */ break; case S_IFSOCK: /* Can't be any of these */ case S_IFIFO: case S_IFCHR: case S_IFBLK: printf("REMOVE: trying to remove an esoteric!\n"); out->oh.result = EINVAL; goto exit; break;#endif default: CODA_ASSERT(0); break; } /* Do the unlink. Need to try it as the user calling us */ suid = getuid(); sgid = getgid(); CODA_ASSERT(!setgid(cred->cr_groupid)); CODA_ASSERT(!seteuid(cred->cr_uid)); if (unlink(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 & destroy 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 successful, reclaim this fid entry */ if (victimFep) free(victimFep); } else { /* reclaim it if we *weren't* successful, but created the fid */ if (created == TRUE && victimFep) free(victimFep); } if (path) free(path); /* There is no extra info to return */ *reply = VC_OUT_NO_DATA; return;}voidDoSetattr(union inputArgs *in, union outputArgs *out, int *reply){ ViceFid *fp; struct coda_cred *cred; struct coda_vattr *vap; fid_ent_t *fep; fid_ent_t dummy; char *path=NULL; uid_t suid; gid_t sgid; struct timeval times[2]; fp = &(in->coda_setattr.VFid); cred = &(in->ih.cred); vap = &(in->coda_setattr.attr); if (verbose) { printf("Doing setattr for fid (%x.%x.%x)\n", fp->Volume, fp->Vnode, fp->Unique); } /* * Check to see that we aren't changing anything we aren't * supposed to. This list came from Venus (vproc_vfscalls.c) */ /* * I ignore the following fields, since I'm not sure what to do * about them: va_filerev va_vaflags */ /* * One exception: we silently allow va_flags to be "set", even * though we can do nothing about them, since they don't make * sense to us. Hopefully, no one will ever notice, though I'm * suspicious. We only return silently if this is the *only* * thing of interest which we are setattr'ing. */ if ((vap->va_flags != (unsigned long)-1) && (vap->va_mode == (u_short)-1) && (vap->va_uid == (uid_t)-1) && (vap->va_gid == (gid_t)-1) && (vap->va_size == (size_t)-1) && (vap->va_atime.tv_sec == (long)-1) && (vap->va_mtime.tv_sec == (long)-1) && (vap->va_ctime.tv_sec == (long)-1)) { out->oh.result = 0; goto earlyexit; } if ((vap->va_type != C_VNON) || (vap->va_fileid != -1) || (vap->va_gen != -1) || (vap->va_bytes != -1) || (vap->va_nlink != -1) || (vap->va_blocksize != -1) || (vap->va_rdev != -1)) { out->oh.result = EINVAL; goto earlyexit; } /* * Check to make sure at least something we care about is set. */ if ((vap->va_mode == (u_short)-1) && (vap->va_uid == (uid_t)-1) && (vap->va_gid == (gid_t)-1) && (vap->va_size == (off_t)-1) && (vap->va_atime.tv_sec == (long)-1) && (vap->va_mtime.tv_sec == (long)-1) && (vap->va_ctime.tv_sec == (long)-1)) { out->oh.result = EINVAL; printf("SETATTR: nothing set!\n"); goto earlyexit; } /* Get the object to setattr */ dummy.fid = *fp; CODA_ASSERT((fep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL); path = fid_fullname(fep); /* * Not sure how I want to handle authentication. For now, let's * just use the standard UNIX rules about root being the only one * to do certain things, and owner being the only other one to do * others. WARNING: if somethings fail, but others succeed, then * perhaps only part of the setattr will happen...this is bad, but * we can live with it for the purposes of potemkin. */ suid = getuid(); sgid = getgid(); CODA_ASSERT(!setgid(cred->cr_groupid)); CODA_ASSERT(!seteuid(cred->cr_uid)); /* Are we truncating the file? */ if ((u_long)vap->va_size != (u_long)-1) { /* Is it either a directory or a symlink? */ if (fep->type != C_VREG) { printf("SETATTR: Setting length of something not C_VREG\n"); out->oh.result = (fep->type == C_VDIR) ? EISDIR : EINVAL; goto exit; } /* Try to do the truncate */ if (truncate(path, vap->va_size)) { out->oh.result = errno; printf("SETATTR: Truncate of (%s) failed\n",path); goto exit; } } /* Are we setting owner/group? */ if ((vap->va_uid != (uid_t)-1) || (vap->va_gid != (gid_t)-1)) { /* As long as it's not a symlink. */ if (fep->type == C_VLNK) { printf("SETATTR: chown(2) of a symlink\n"); out->oh.result = EINVAL; goto exit; } if (chown(path,vap->va_uid,vap->va_gid)) { printf("SETATTR: chown failed\n"); out->oh.result = errno; goto exit; } } /* Are we setting the mode bits? */ if (vap->va_mode != (u_short)-1) { if (chmod(path,vap->va_mode)) { printf("SETATTR: chmod failed\n"); out->oh.result = errno; goto exit; } } /* Are we setting the mtime/atime? */ if ((vap->va_atime.tv_sec != -1) || (vap->va_mtime.tv_sec != -1)) { times[0].tv_sec = vap->va_atime.tv_sec; times[0].tv_usec = vap->va_atime.tv_nsec/1000; times[1].tv_sec = vap->va_mtime.tv_sec; times[1].tv_usec = vap->va_mtime.tv_nsec/1000; if (utimes(path, times)) { printf("SETATTR: chmod failed\n"); out->oh.result = errno; goto exit; } } /* We are now going to succeed */ out->oh.result = 0; exit: CODA_ASSERT(!seteuid(suid)); CODA_ASSERT(!setgid(sgid)); earlyexit: if (path) free(path); *reply = VC_OUT_NO_DATA; return;}voidDoRename(union inputArgs *in, union outputArgs *out, int *reply){ ViceFid *sdfp; fid_ent_t *sdfep; ViceFid *tdfp; fid_ent_t *tdfep; fid_ent_t dummy; char *sname; char *spath=NULL; char *tname; char *tpath=NULL; fid_ent_t *sfep=NULL; bool screated=FALSE; fid_ent_t *tfep=NULL; bool tcreated=FALSE; struct coda_cred *cred; ds_list_iter_t *iter; struct stat sbuf; uid_t suid; gid_t sgid; sdfp = &(in->coda_rename.sourceFid); tdfp = &(in->coda_rename.destFid); cred = &(in->ih.cred); sname = (char*)in + (int)in->coda_rename.srcname; tname = (char*)in + (int)in->coda_rename.destname; if (verbose) { printf("Rename: moving %s from (%x.%x.%x) to %s in (%x.%x.%x)\n", sname, sdfp->Volume, sdfp->Vnode, sdfp->Unique, tname, tdfp->Volume, tdfp->Vnode, tdfp->Unique); } /* Grab source directory, make sure it's a directory. */ dummy.fid = *sdfp; CODA_ASSERT((sdfep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL); if (sdfep->type != C_VDIR) { printf("Ack! Trying to rename something from a non-directory!\n"); out->oh.result = ENOTDIR; goto exit; } /* Grab target directory, make sure it's a directory. */ dummy.fid = *tdfp; CODA_ASSERT((tdfep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL); if (tdfep->type != C_VDIR) { printf("Ack! Trying to rename something from a non-directory!\n"); out->oh.result = ENOTDIR; goto exit; } /* Step 0: Is the name-to-be-created okay? */ /* Don't allow any creation of '.', '..', ''; they already must exist. */ if ((!strcmp(tname, ".")) || (!strcmp(tname, "..")) || (!strcmp(tname, ""))) { printf("CREATE: create of '.', '..' or ''\n"); out->oh.result = EINVAL; goto exit; } /* Don't allow names of the form @XXXXXXXX.XXXXXXXX.XXXXXXXX */ if ((strlen(tname) == 27) && (tname[0] == '@') && (tname[9] == '.') && (tname[18] == '.')) { out->oh.result = EINVAL; goto exit; } /* Step 1: does the target exist, and do we know about it */ /* If so, we'll remove it at the end on success */ iter = ds_list_iter_create(tdfep->kids); while ((tfep = ds_list_iter_next(iter)) != NULL) { if (!strcmp(tfep->name, tname)) { break; } } ds_list_iter_destroy(iter); if (!tfep) { tfep = fid_create(tname, tdfep); tcreated = TRUE; } tpath = fid_fullname(tfep); /* Step 2: do we have record of the source fid yet? */ iter = ds_list_iter_create(sdfep->kids); while ((sfep = ds_list_iter_next(iter)) != NULL) { if (!strcmp(sfep->name, sname)) { break; } } ds_list_iter_destroy(iter); if (!sfep) { sfep = fid_create(sname, sdfep); screated = TRUE; } spath = fid_fullname(sfep); /* * Step 3a: stat the source file for it's type. Must happen * *before* we try to do the rename, 'cause if the stat fails, * we're hosed */ if (stat(spath,&sbuf)) { printf("RENAME: stat of source failed (%s)\n",strerror(errno)); out->oh.result = errno; goto exit; } /* Step 3: try to do the rename. */ suid = getuid(); sgid = getgid(); CODA_ASSERT(!setgid(cred->cr_groupid)); CODA_ASSERT(!seteuid(cred->cr_uid)); if (rename(spath,tpath)) { CODA_ASSERT(!seteuid(suid)); CODA_ASSERT(!setgid(sgid)); out->oh.result = errno; printf("RENAME: rename failed %s\n",strerror(errno)); goto exit; } CODA_ASSERT(!seteuid(suid)); CODA_ASSERT(!setgid(sgid)); /* We will now succeed */ out->oh.result = 0; /* If we didn't create the tfep, we must remove it */ if (tcreated == FALSE) { ds_list_remove(tdfep->kids, tfep); ds_hash_remove(FidTab, tfep); } /* If we didn't create the the sfep, we must remove it from sdfep's list */ if (screated == FALSE) { ds_list_remove(sdfep->kids, sfep); } else { /* We need to fill in a type for the new fid. */ fid_assign_type(sfep,&sbuf); /* And enter it into the fid tab */ ds_hash_insert(FidTab,sfep); } /* Change sfep's name, and insert the sfep into the tdfep directory */ strcpy(sfep->name,tname); sfep->parent = tdfep; ds_list_insert(tdfep->kids, sfep); exit: /* If we succeeded, we must toast the tfep */ if (!out->oh.result) { free(tfep); } else { /* * If we failed, then we must remove tfep and sfep if they * were created as side effects of this operation */ if (tcreated == TRUE && tfep) free(tfep); if (screated == TRUE && sfep) free(sfep); } if (spath) free(spath); if (tpath) free(tpath); *reply = VC_OUT_NO_DATA; return;}voidDoMkdir(union inputArgs *in, union outputArgs *out, int *reply){ ViceFid *fp; fid_ent_t *fep; ViceFid *newFp; fid_ent_t *newFep=NULL; fid_ent_t dummy; struct coda_vattr *attr; struct coda_vattr *newAttr; struct coda_cred *cred; int mode; char *name=NULL; char *path=NULL; struct stat sbuf; uid_t suid; gid_t sgid; fp = &(in->coda_mkdir.VFid); attr = &(in->coda_mkdir.attr); cred = &(in->ih.cred); CODA_ASSERT((int)in->coda_mkdir.name == VC_INSIZE(coda_mkdir_in)); name = (char*)in + (int)in->coda_mkdir.name; newFp = &(out->coda_mkdir.VFid); newAttr = &(out->coda_mkdir.attr); mode = attr->va_mode & 07777; /* XXX, but probably not */ if (verbose) { printf("Doing mkdir of (%s) in fid (%x.%x.%x)\n", name, fp->Volume, fp->Vnode, fp->Unique); } /* Where are we creating this? */ dummy.fid = *fp; CODA_ASSERT((fep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL); if (fep->type != C_VDIR) { printf("Ack! Trying to mkdir in a non-directory!\n"); out->oh.result = ENOTDIR; goto exit; } /* Step 0: Is the name-to-be-created okay? */ /* Don't allow any creation of '.', '..', ''; they already must exist. */ if ((!strcmp(name, ".")) || (!strcmp(name, "..")) || (!strcmp(name, ""))) { printf("MKDIR: 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] == '.')) { printf("MKDIR: create of fakified-like name\n"); out->oh.result = EINVAL; goto exit; } /* Step 1: does this child already exist? For mkdir, it cannot */ path = fid_fullname(fep); if (child_exists(path, name)) { printf("MKDIR: child exists\n"); out->oh.result = EEXIST; goto exit; } /* Go ahead and create it, but don't enter yet. */ newFep = fid_create(name, fep); /* New path for the directory-to-be-created */ if (path) free (path); path = fid_fullname(newFep); /* Set the creator for this file */ suid = getuid(); sgid = getgid(); CODA_ASSERT(!setgid(cred->cr_groupid)); CODA_ASSERT(!seteuid(cred->cr_uid)); /* Do the mkdir */ if (mkdir(path,mode)) { printf("MKDIR: mkdir failed (%s)\n",strerror(errno)); out->oh.result = errno; CODA_ASSERT(!seteuid(suid)); CODA_ASSERT(!setgid(sgid)); goto exit; } /* Reset our effective uid/gid */ CODA_ASSERT(!seteuid(suid)); CODA_ASSERT(!setgid(sgid)); /* Stat it so we can set type, return coda_vattr correctly */ if (lstat(path,&sbuf)) { printf("MKDIR: couldn't lstat %s: (%s)\n", path,strerror(errno)); out->oh.result = errno; goto exit; } if (fid_assign_type(newFep, &sbuf)) { out->oh.result = ENOENT; goto exit; } /* We are now doomed to succeed :-) */ /* Record this fid, and finish off */ out->oh.result = 0; CODA_ASSERT(ds_hash_insert(FidTab, newFep)); CODA_ASSERT(ds_list_insert(fep->kids, newFep)); /* Set the return values for the create call */ *newFp = newFep->fid; fill_vattr(&sbuf, newFep, newAttr); exit: if (out->oh.result && newFep) free(newFep); if (path) free (path); *reply = VC_OUTSIZE(coda_mkdir_out); return;}voidDoRmdir(union inputArgs *in, union outputArgs *out, int *reply){ ViceFid *fp; fid_ent_t *fep; fid_ent_t *victimFep = NULL; bool created=FALSE; struct coda_cred *cred; fid_ent_t dummy; char *name=NULL; char *path=NULL; ds_list_iter_t *iter; struct stat sbuf; uid_t suid; gid_t sgid; fp = &(in->coda_rmdir.VFid); cred = &(in->ih.cred); CODA_ASSERT((int)in->coda_rmdir.name == VC_INSIZE(coda_rmdir_in)); name = (char*)in + (int)in->coda_rmdir.name; if (verbose) { printf("Doing rmdir of (%s) in fid (%x.%x.%x)\n", name, fp->Volume, fp->Vnode, fp->Unique); } /* Get the directory from which we are removing */ dummy.fid = *fp; CODA_ASSERT((fep = (fid_ent_t *) ds_hash_member(FidTab, &dummy)) != NULL); if (fep->type != C_VDIR) { printf("RMDIR: parent not directory!\n"); out->oh.result = ENOTDIR; goto exit; } /* Step 0: Check to ensure that removes don't happen to '.', '..', or '' */ if ((!strcmp(name, ".")) || (!strcmp(name, "..")) || (!strcmp(name, ""))) { printf("RMDIR: remove 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -