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

📄 potemkin.c

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