Ejemplo n.º 1
0
Archivo: nfs.c Proyecto: UIKit0/unfs3
LOOKUP3res *nfsproc3_lookup_3_svc(LOOKUP3args * argp, struct svc_req * rqstp)
{
    static LOOKUP3res result;
    unfs3_fh_t *fh;
    char *path;
    char obj[NFS_MAXPATHLEN];
    backend_statstruct buf;
    int res;
    uint32 gen;

    PREP(path, argp->what.dir);
    result.status = cat_name(path, argp->what.name, obj);

    cluster_lookup(obj, rqstp, &result.status);

    if (result.status == NFS3_OK) {
	res = backend_lstat(obj, &buf);
	if (res == -1)
	    result.status = lookup_err();
	else {
	    if (strcmp(argp->what.name, ".") == 0 ||
		strcmp(argp->what.name, "..") == 0) {
		fh = fh_comp_ptr(obj, rqstp, 0);
	    } else {
		gen = backend_get_gen(buf, FD_NONE, obj);
		fh = fh_extend(argp->what.dir, buf.st_dev, buf.st_ino, gen);
		fh_cache_add(buf.st_dev, buf.st_ino, obj);
	    }

	    if (fh) {
		result.LOOKUP3res_u.resok.object.data.data_len =
		    fh_length(fh);
		result.LOOKUP3res_u.resok.object.data.data_val = (char *) fh;
		result.LOOKUP3res_u.resok.obj_attributes =
		    get_post_buf(buf, rqstp);
	    } else {
		/* path was too long */
		result.status = NFS3ERR_NAMETOOLONG;
	    }
	}
    }

    /* overlaps with resfail */
    result.LOOKUP3res_u.resok.dir_attributes = get_post_stat(path, rqstp);

    return &result;
}
Ejemplo n.º 2
0
/*
 * locate file given prefix, device, and inode number
 */
static int locate_pfx(const char *pfx, uint32 dev, uint64 ino, char *result)
{
    char path[NFS_MAXPATHLEN];
    backend_dirstream *search;
    struct dirent *ent;
    backend_statstruct buf;
    int res;

    search = opendir(pfx);
    if (!search)
	return FALSE;

    while ((ent = readdir(search))) {
	if (strlen(pfx) + strlen(ent->d_name) + 2 >= NFS_MAXPATHLEN)
	    continue;

	sprintf(path, "%s/%s", pfx, ent->d_name);

	res = backend_lstat(path, &buf);
	if (res != 0)
	    continue;

	/* check for matching object */
	if (buf.st_dev == dev && buf.st_ino == ino) {
	    strcpy(result, path);
	    st_cache = buf;
	    st_cache_valid = TRUE;
	    closedir(search);
	    return TRUE;
	}

	/* descend into directories with same dev */
	if (buf.st_dev == dev && S_ISDIR(buf.st_mode) &&
	    strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) {
	    res = locate_pfx(path, dev, ino, result);
	    if (res == TRUE) {
		closedir(search);
		return TRUE;
	    }
	}
    }

    closedir(search);
    return FALSE;
}
Ejemplo n.º 3
0
Archivo: attr.c Proyecto: modcs/NFSRODS
/*
 * lowlevel routine for getting post-operation attributes
 */
static post_op_attr get_post_ll(const char *path, uint32 dev, uint64 ino,
                                struct svc_req *req)
{
    backend_statstruct buf;
    int res;

    if (!path)
        return error_attr;

    res = backend_lstat(path, &buf);
    if (res == -1)
        return error_attr;

    /* protect against local fs race */
    if (dev != buf.st_dev || ino != buf.st_ino)
        return error_attr;

    return get_post_buf(buf, req);
}
Ejemplo n.º 4
0
Archivo: attr.c Proyecto: modcs/NFSRODS
/*
 * compute post-operation attributes given a stat buffer
 */
post_op_attr get_post_buf(backend_statstruct buf, struct svc_req * req)
{
    post_op_attr result;

    debug("get_post_buf STAT","");
    result.attributes_follow = TRUE;

    if (S_ISDIR(buf.st_mode))
        result.post_op_attr_u.attributes.type = NF3DIR;
    else if (S_ISBLK(buf.st_mode))
        result.post_op_attr_u.attributes.type = NF3BLK;
    else if (S_ISCHR(buf.st_mode))
        result.post_op_attr_u.attributes.type = NF3CHR;
#ifdef S_ISLNK
    else if (S_ISLNK(buf.st_mode))
        result.post_op_attr_u.attributes.type = NF3LNK;
#endif				       /* S_ISLNK */
#ifdef S_ISSOCK
    else if (S_ISSOCK(buf.st_mode))
        result.post_op_attr_u.attributes.type = NF3SOCK;
#endif				       /* S_ISSOCK */
    else if (S_ISFIFO(buf.st_mode))
        result.post_op_attr_u.attributes.type = NF3FIFO;
    else
        result.post_op_attr_u.attributes.type = NF3REG;

    /* adapt permissions for executable files */
    if (opt_readable_executables && S_ISREG(buf.st_mode)) {
        if (buf.st_mode & S_IXUSR)
            buf.st_mode |= S_IRUSR;
        if (buf.st_mode & S_IXGRP)
            buf.st_mode |= S_IRGRP;
        if (buf.st_mode & S_IXOTH)
            buf.st_mode |= S_IROTH;
    }

    result.post_op_attr_u.attributes.mode = buf.st_mode & 0xFFFF;
    result.post_op_attr_u.attributes.nlink = buf.st_nlink;

    /* If -s, translate uids */
    if (opt_singleuser) {
        unsigned int req_uid = 0;
        unsigned int req_gid = 0;
        struct authunix_parms *auth = (void *) req->rq_clntcred;
        uid_t ruid = backend_getuid();

        if (req->rq_cred.oa_flavor == AUTH_UNIX) {
            req_uid = auth->aup_uid;
            req_gid = auth->aup_gid;
        }

        if ((buf.st_uid == ruid) || (ruid == 0))
            result.post_op_attr_u.attributes.uid = req_uid;
        else
            result.post_op_attr_u.attributes.uid = 0;

        if ((buf.st_gid == backend_getgid()) || (ruid == 0))
            result.post_op_attr_u.attributes.gid = req_gid;
        else
            result.post_op_attr_u.attributes.gid = 0;
    } else {
        /* Normal case */
        result.post_op_attr_u.attributes.uid = buf.st_uid;
        result.post_op_attr_u.attributes.gid = buf.st_gid;
    }

    result.post_op_attr_u.attributes.size = buf.st_size;
    result.post_op_attr_u.attributes.used = buf.st_blocks * 512;
    result.post_op_attr_u.attributes.rdev.specdata1 =
            (buf.st_rdev >> 8) & 0xFF;
    result.post_op_attr_u.attributes.rdev.specdata2 = buf.st_rdev & 0xFF;
    result.post_op_attr_u.attributes.fsid = buf.st_dev;

    /* If this is a removable export point, we should return the preset fsid
       for all objects which resides in the same file system as the exported
       directory */
    if (exports_opts & OPT_REMOVABLE) {
        backend_statstruct epbuf;

        if (backend_lstat(export_path, &epbuf) != -1 &&
                buf.st_dev == epbuf.st_dev) {
            result.post_op_attr_u.attributes.fsid = export_fsid;
        }
    }
#ifdef WIN32
    /* Recent Linux kernels (2.6.24 and newer) exposes large fileids even to
       non-LFS 32-bit applications, unless kernel parameter
       nfs.enable_ino64=0. This means that applications will fail with
       EOVERFLOW. On Windows, we always have large st_ino:s. To avoid
       trouble, we truncate to 32 bits */
    result.post_op_attr_u.attributes.fileid =
            (buf.st_ino >> 32) ^ (buf.st_ino & 0xffffffff);
#else
    result.post_op_attr_u.attributes.fileid = buf.st_ino;
#endif
    result.post_op_attr_u.attributes.atime.seconds = buf.st_atime;
    result.post_op_attr_u.attributes.atime.nseconds = 0;
    result.post_op_attr_u.attributes.mtime.seconds = buf.st_mtime;
    result.post_op_attr_u.attributes.mtime.nseconds = 0;
    result.post_op_attr_u.attributes.ctime.seconds = buf.st_ctime;
    result.post_op_attr_u.attributes.ctime.nseconds = 0;

    //debug("get_post_buf filei %d",result.post_op_attr_u.attributes.fsid);

    return result;
}