Exemple #1
0
/*
 * Note: we hold the dentry use count while the file is open.
 */
static u32
nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
{
	u32		nfserr;
	struct svc_fh	fh;

	/* must initialize before using! but maxsize doesn't matter */
	fh_init(&fh,0);
	fh.fh_handle.fh_size = f->size;
	memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
	fh.fh_export = NULL;

	exp_readlock();
	nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
	fh_put(&fh);
	rqstp->rq_client = NULL;
	exp_readunlock();
 	/* nlm and nfsd don't share error codes.
	 * we invent: 0 = no error
	 *            1 = stale file handle
	 *            2 = nfserr_dropit (or -EAGAIN)
	 *	          3 = other error
	 */
	switch (nfserr) {
	case nfs_ok:
		return 0;
	case nfserr_stale:
		return 1;
	case nfserr_dropit:
		return 2;
	default:
		return 3;
	}
}
Exemple #2
0
/*
 * Note: we hold the dentry use count while the file is open.
 */
static __be32
nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
{
	__be32		nfserr;
	struct svc_fh	fh;

	/* must initialize before using! but maxsize doesn't matter */
	fh_init(&fh,0);
	fh.fh_handle.fh_size = f->size;
	memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
	fh.fh_export = NULL;

	exp_readlock();
	nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
	fh_put(&fh);
	exp_readunlock();
 	/* We return nlm error codes as nlm doesn't know
	 * about nfsd, but nfsd does know about nlm..
	 */
	switch (nfserr) {
	case nfs_ok:
		return 0;
	case nfserr_dropit:
		return nlm_drop_reply;
	case nfserr_stale:
		return nlm_stale_fh;
	default:
		return nlm_failed;
	}
}
Exemple #3
0
/*
 * XDR functions for basic NFS types
 */
static __be32 *
decode_fh(__be32 *p, struct svc_fh *fhp)
{
	fh_init(fhp, NFS_FHSIZE);
	memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
	fhp->fh_handle.fh_size = NFS_FHSIZE;

	return p + (NFS_FHSIZE >> 2);
}
Exemple #4
0
/*
 * XDR functions for basic NFS types
 */
static __be32 *
decode_fh(__be32 *p, struct svc_fh *fhp)
{
	fh_init(fhp, NFS_FHSIZE);
	memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
	fhp->fh_handle.fh_size = NFS_FHSIZE;

	/* FIXME: Look up export pointer here and verify
	 * Sun Secure RPC if requested */
	return p + (NFS_FHSIZE >> 2);
}
Exemple #5
0
static inline u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
	int size;
	fh_init(fhp, NFS3_FHSIZE);
	size = ntohl(*p++);
	if (size > NFS3_FHSIZE)
		return NULL;

	memcpy(&fhp->fh_handle.fh_base, p, size);
	fhp->fh_handle.fh_size = size;
	return p + XDR_QUADLEN(size);
}
Exemple #6
0
static void test_nfsfh(void){
	dev_t dev=0;
	u32 unfs=0, u32ptr[2];
	ino_t ino=0;
	struct svc_fh A1;
	int i=20;

	u32_to_dev_t((__u32)unfs);
	ino_t_to_u32(ino);
	u32_to_ino_t((__u32)unfs);
	mk_fsid_v0(u32ptr, dev, ino);
	mk_fsid_v1(u32ptr, unfs);
	SVCFH_fmt(&A1);
	fh_init(&A1,i);
	fh_lock(&A1);
	fh_unlock(&A1);
	printk("finished nfsfh test\n");
}
Exemple #7
0
static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen, u64 ino)
{
	struct svc_fh	*fh = &cd->scratch;
	__be32 err;

	fh_init(fh, NFS3_FHSIZE);
	err = compose_entry_fh(cd, fh, name, namlen, ino);
	if (err) {
		*p++ = 0;
		*p++ = 0;
		goto out;
	}
	p = encode_post_op_attr(cd->rqstp, p, fh);
	*p++ = xdr_one;			/* yes, a file handle follows */
	p = encode_fh(p, fh);
out:
	fh_put(fh);
	return p;
}
Exemple #8
0
/*
 * With NFSv3, CREATE processing is a lot easier than with NFSv2.
 * At least in theory; we'll see how it fares in practice when the
 * first reports about SunOS compatibility problems start to pour in...
 * N.B. After this call _both_ resp->dirfh and resp->fh need an fh_put
 */
static int
nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
					  struct nfsd3_createres  *resp)
{
	svc_fh		*dirfhp, *newfhp = NULL;
	struct iattr	*attr;
	int		mode;
	u32		nfserr;

	dprintk("nfsd: CREATE   %x/%ld %s\n",
				SVCFH_DEV(&argp->fh),
				SVCFH_INO(&argp->fh),
				argp->name);

	dirfhp = fh_copy(&resp->dirfh, &argp->fh);
	newfhp = fh_init(&resp->fh);
	attr   = &argp->attrs;

	/* Get the directory inode */
	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE);
	if (nfserr)
		RETURN(nfserr);

	/* Unfudge the mode bits */
	attr->ia_mode &= ~S_IFMT;
	if (!(attr->ia_valid & ATTR_MODE)) { 
		attr->ia_valid |= ATTR_MODE;
		attr->ia_mode = S_IFREG;
	}
	mode = attr->ia_mode & ~S_IFMT;

	/* Now create the file and set attributes */
	nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
				attr, S_IFREG, 0, newfhp);

	RETURN(nfserr);
}
Exemple #9
0
int
holding_file_get_dumpfile(
    char *	fname,
    dumpfile_t *file)
{
    char buffer[DISK_BLOCK_BYTES];
    int fd;

    memset(buffer, 0, sizeof(buffer));

    fh_init(file);
    file->type = F_UNKNOWN;
    if((fd = robust_open(fname, O_RDONLY, 0)) == -1)
        return 0;

    if(read_fully(fd, buffer, sizeof(buffer), NULL) != sizeof(buffer)) {
        aclose(fd);
        return 0;
    }
    aclose(fd);

    parse_file_header(buffer, file, sizeof(buffer));
    return 1;
}
Exemple #10
0
static int
encode_entry(struct readdir_cd *cd, const char *name,
	     int namlen, off_t offset, ino_t ino, unsigned int d_type, int plus)
{
	u32		*p = cd->buffer;
	int		buflen, slen, elen;

	if (cd->offset)
		xdr_encode_hyper(cd->offset, (u64) offset);

	/* nfsd_readdir calls us with name == 0 when it wants us to
	 * set the last offset entry. */
	if (name == 0)
		return 0;

	/*
	dprintk("encode_entry(%.*s @%ld%s)\n",
		namlen, name, (long) offset, plus? " plus" : "");
	 */

	/* truncate filename if too long */
	if (namlen > NFS3_MAXNAMLEN)
		namlen = NFS3_MAXNAMLEN;

	slen = XDR_QUADLEN(namlen);
	elen = slen + NFS3_ENTRY_BAGGAGE
		+ (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
	if ((buflen = cd->buflen - elen) < 0) {
		cd->eob = 1;
		return -EINVAL;
	}
	*p++ = xdr_one;				 /* mark entry present */
	p    = xdr_encode_hyper(p, ino);	 /* file id */
	p    = xdr_encode_array(p, name, namlen);/* name length & name */

	cd->offset = p;			/* remember pointer */
	p = xdr_encode_hyper(p, NFS_OFFSET_MAX);	/* offset of next entry */

	/* throw in readdirplus baggage */
	if (plus) {
		struct svc_fh	fh;
		struct svc_export	*exp;
		struct dentry		*dparent, *dchild;

		dparent = cd->dirfh->fh_dentry;
		exp  = cd->dirfh->fh_export;

		fh_init(&fh, NFS3_FHSIZE);
		if (isdotent(name, namlen)) {
			dchild = dparent;
			if (namlen == 2)
				dchild = dchild->d_parent;
			dchild = dget(dchild);
		} else
			dchild = lookup_one_len(name, dparent,namlen);
		if (IS_ERR(dchild))
			goto noexec;
		if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode)
			goto noexec;
		p = encode_post_op_attr(cd->rqstp, p, &fh);
		*p++ = xdr_one; /* yes, a file handle follows */
		p = encode_fh(p, &fh);
		fh_put(&fh);
	}

out:
	cd->buflen = buflen;
	cd->buffer = p;
	return 0;

noexec:
	*p++ = 0;
	*p++ = 0;
	goto out;
}
Exemple #11
0
void
parse_file_header(
    const char *buffer,
    dumpfile_t *file,
    size_t	buflen)
{
    char *buf, *line, *tok, *line1;
    size_t lsize;
    char *uqname;
    int in_quotes;
    char *saveptr = NULL;

    /* put the buffer into a writable chunk of memory and nul-term it */
    buf = alloc(buflen + 1);
    memcpy(buf, buffer, buflen);
    buf[buflen] = '\0';
    fh_init(file); 

    /* extract the first unquoted line */
    in_quotes = 0;
    for (line = buf, lsize = 0; lsize < buflen; line++) {
	if ((*line == '\n') && !in_quotes)
	    break;

	if (*line == '"') {
	    in_quotes = !in_quotes;
	} else if ((*line == '\\') && (*(line + 1) == '"')) {
	    line++;
	    lsize++;
	}
	lsize++;
    }
    *line = '\0';
    line1 = alloc(lsize + 1);
    strncpy(line1, buf, lsize);
    line1[lsize] = '\0';
    *line = '\n';

    tok = strtok_r(line1, " ", &saveptr);
    if (tok == NULL) {
        g_fprintf(stderr, _("%s: Empty amanda header: buflen=%zu lsize=%zu\n"), get_pname(),
	    buflen, 
	    lsize);
	hexdump(buffer, lsize);
	strange_header(file, buffer, buflen, _("<Non-empty line>"), tok);
	goto out;
    }

    if (strcmp(tok, "NETDUMP:") != 0 && strcmp(tok, "AMANDA:") != 0) {
	amfree(buf);
	file->type = F_UNKNOWN;
	amfree(line1);
	return;
    }

    tok = strtok_r(NULL, " ", &saveptr);
    if (tok == NULL) {
	strange_header(file, buffer, buflen, _("<file type>"), tok);
	goto out;
    }
    file->type = str2filetype(tok);
    
    switch (file->type) {
    case F_TAPESTART:
	tok = strtok_r(NULL, " ", &saveptr);
	if ((tok == NULL) || (strcmp(tok, "DATE") != 0)) {
	    strange_header(file, buffer, buflen, "DATE", tok);
	    goto out;
	}

	tok = strtok_r(NULL, " ", &saveptr);
	if (tok == NULL) {
	    strange_header(file, buffer, buflen, _("<date stamp>"), tok);
	    goto out;
	}
	strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1);

	tok = strtok_r(NULL, " ", &saveptr);
	if ((tok == NULL) || (strcmp(tok, "TAPE") != 0)) {
	    strange_header(file, buffer, buflen, "TAPE", tok);
	    goto out;
	}

	tok = strtok_r(NULL, " ", &saveptr);
	if (tok == NULL) {
	    strange_header(file, buffer, buflen, _("<file type>"), tok);
	    goto out;
	}
	strncpy(file->name, tok, SIZEOF(file->name) - 1);
	break;

    case F_DUMPFILE:
    case F_CONT_DUMPFILE:
    case F_SPLIT_DUMPFILE:
	tok = strtok_r(NULL, " ", &saveptr);
	if (tok == NULL) {
	    strange_header(file, buffer, buflen, _("<date stamp>"), tok);
	    goto out;
	}
	strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1);

	tok = strtok_r(NULL, " ", &saveptr);
	if (tok == NULL) {
	    strange_header(file, buffer, buflen, _("<file name>"), tok);
	    goto out;
	}
	strncpy(file->name, tok, SIZEOF(file->name) - 1);

	tok = strquotedstr(&saveptr);
	if (tok == NULL) {
	    strange_header(file, buffer, buflen, _("<disk name>"), tok);
	    goto out;
	}
	uqname = unquote_string(tok);
	strncpy(file->disk, uqname, SIZEOF(file->disk) - 1);
 	amfree(uqname);
	
	if(file->type == F_SPLIT_DUMPFILE) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL || strcmp(tok, "part") != 0) {
		strange_header(file, buffer, buflen, "part", tok);
		goto out;
	    }

	    tok = strtok_r(NULL, "/", &saveptr);
	    if ((tok == NULL) || (sscanf(tok, "%d", &file->partnum) != 1)) {
		strange_header(file, buffer, buflen, _("<part num param>"), tok);
		goto out;
	    }

	    /* If totalparts == -1, then the original dump was done in 
 	       streaming mode (no holding disk), thus we don't know how 
               many parts there are. */
	    tok = strtok_r(NULL, " ", &saveptr);
            if((tok == NULL) || (sscanf(tok, "%d", &file->totalparts) != 1)) {
		strange_header(file, buffer, buflen, _("<total parts param>"), tok);
		goto out;
	    }
	}

	tok = strtok_r(NULL, " ", &saveptr);
	if ((tok == NULL) || (strcmp(tok, "lev") != 0)) {
	    strange_header(file, buffer, buflen, "lev", tok);
	    goto out;
	}

	tok = strtok_r(NULL, " ", &saveptr);
	if ((tok == NULL) || (sscanf(tok, "%d", &file->dumplevel) != 1)) {
	    strange_header(file, buffer, buflen, _("<dump level param>"), tok);
	    goto out;
	}

	tok = strtok_r(NULL, " ", &saveptr);
	if ((tok == NULL) || (strcmp(tok, "comp") != 0)) {
	    strange_header(file, buffer, buflen, "comp", tok);
	    goto out;
	}

	tok = strtok_r(NULL, " ", &saveptr);
	if (tok == NULL) {
	    strange_header(file, buffer, buflen, _("<comp param>"), tok);
	    goto out;
	}
	strncpy(file->comp_suffix, tok, SIZEOF(file->comp_suffix) - 1);

	file->compressed = strcmp(file->comp_suffix, "N");
	/* compatibility with pre-2.2 amanda */
	if (strcmp(file->comp_suffix, "C") == 0)
	    strncpy(file->comp_suffix, ".Z", SIZEOF(file->comp_suffix) - 1);
	       
	tok = strtok_r(NULL, " ", &saveptr);
        /* "program" is optional */
        if (tok == NULL || strcmp(tok, "program") != 0) {
	    break;
	}

        tok = strtok_r(NULL, " ", &saveptr);
        if (tok == NULL) {
	    strange_header(file, buffer, buflen, _("<program name>"), tok);
	    goto out;
	}
        strncpy(file->program, tok, SIZEOF(file->program) - 1);
        if (file->program[0] == '\0')
            strncpy(file->program, "RESTORE", SIZEOF(file->program) - 1);

	if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL)
             break;          /* reached the end of the buffer */

	/* "encryption" is optional */
	if (BSTRNCMP(tok, "crypt") == 0) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL) {
		strange_header(file, buffer, buflen, _("<crypt param>"), tok);
		goto out;
	    }
	    strncpy(file->encrypt_suffix, tok,
		    SIZEOF(file->encrypt_suffix) - 1);
	    file->encrypted = BSTRNCMP(file->encrypt_suffix, "N");
	    if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL)
		break;
	}

	/* "srvcompprog" is optional */
	if (BSTRNCMP(tok, "server_custom_compress") == 0) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL) {
		strange_header(file, buffer, buflen,
				_("<server custom compress param>"), tok);
		goto out;
	    }
	    strncpy(file->srvcompprog, tok, SIZEOF(file->srvcompprog) - 1);
	    if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL)
		break;      
	}

	/* "clntcompprog" is optional */
	if (BSTRNCMP(tok, "client_custom_compress") == 0) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL) {
		strange_header(file, buffer, buflen,
				_("<client custom compress param>"), tok);
		goto out;
	    }
	    strncpy(file->clntcompprog, tok, SIZEOF(file->clntcompprog) - 1);
	    if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL)
		break;
	}

	/* "srv_encrypt" is optional */
	if (BSTRNCMP(tok, "server_encrypt") == 0) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL) {
		strange_header(file, buffer, buflen,
				_("<server encrypt param>"), tok);
		goto out;
	    }
	    strncpy(file->srv_encrypt, tok, SIZEOF(file->srv_encrypt) - 1);
	    if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL) 
		break;
	}

	/* "clnt_encrypt" is optional */
	if (BSTRNCMP(tok, "client_encrypt") == 0) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL) {
		strange_header(file, buffer, buflen,
				_("<client encrypt param>"), tok);
		goto out;
	    }
	    strncpy(file->clnt_encrypt, tok, SIZEOF(file->clnt_encrypt) - 1);
	    if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL) 
		break;
	}

	/* "srv_decrypt_opt" is optional */
	if (BSTRNCMP(tok, "server_decrypt_option") == 0) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL) {
		strange_header(file, buffer, buflen,
				_("<server decrypt param>"), tok);
		goto out;
	    }
	    strncpy(file->srv_decrypt_opt, tok,
		    SIZEOF(file->srv_decrypt_opt) - 1);
	    if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL) 
		break;
	}

	/* "clnt_decrypt_opt" is optional */
	if (BSTRNCMP(tok, "client_decrypt_option") == 0) {
	    tok = strtok_r(NULL, " ", &saveptr);
	    if (tok == NULL) {
		strange_header(file, buffer, buflen,
				_("<client decrypt param>"), tok);
		goto out;
	    }
	    strncpy(file->clnt_decrypt_opt, tok,
		    SIZEOF(file->clnt_decrypt_opt) - 1);
	    if ((tok = strtok_r(NULL, " ", &saveptr)) == NULL) 
		break;
	}
      break;
      

    case F_TAPEEND:
	tok = strtok_r(NULL, " ", &saveptr);
	/* DATE is optional */
	if (tok != NULL) {
	    if (strcmp(tok, "DATE") == 0) {
		tok = strtok_r(NULL, " ", &saveptr);
		if(tok == NULL)
		    file->datestamp[0] = '\0';
		else
		    strncpy(file->datestamp, tok, SIZEOF(file->datestamp) - 1);
	    } else {
		strange_header(file, buffer, buflen, _("<DATE>"), tok);
	   }
	} else {
	    file->datestamp[0] = '\0';
	}
	break;

    case F_NOOP:
	/* nothing follows */
	break;

    default:
	strange_header(file, buffer, buflen,
		_("TAPESTART|DUMPFILE|CONT_DUMPFILE|SPLIT_DUMPFILE|TAPEEND|NOOP"), tok);
	goto out;
    }

    (void)strtok_r(buf, "\n", &saveptr); /* this is the first line */
    /* iterate through the rest of the lines */
    while ((line = strtok_r(NULL, "\n", &saveptr)) != NULL) {
#define SC "CONT_FILENAME="
	if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
	    line += SIZEOF(SC) - 1;
	    strncpy(file->cont_filename, line,
		    SIZEOF(file->cont_filename) - 1);
	    continue;
	}
#undef SC

#define SC "PARTIAL="
	if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
	    line += SIZEOF(SC) - 1;
	    file->is_partial = !strcasecmp(line, "yes");
	    continue;
	}
#undef SC
#define SC "APPLICATION="
	if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
	    line += SIZEOF(SC) - 1;
	    strncpy(file->application, line,
		    SIZEOF(file->application) - 1);
	    continue;
	}
#undef SC

#define SC "DLE="
	if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
	    line += SIZEOF(SC) - 1;
	    file->dle_str = parse_heredoc(line, &saveptr);
	}
#undef SC

#define SC _("To restore, position tape at start of file and run:")
	if (strncmp(line, SC, SIZEOF(SC) - 1) == 0)
	    continue;
#undef SC

#define SC "\tdd if=<tape> "
	if (strncmp(line, SC, SIZEOF(SC) - 1) == 0) {
	    char *cmd1, *cmd2, *cmd3=NULL;

	    /* skip over dd command */
	    if ((cmd1 = strchr(line, '|')) == NULL) {

	        strncpy(file->recover_cmd, "BUG",
		        SIZEOF(file->recover_cmd) - 1);
	        continue;
	    }
	    *cmd1++ = '\0';

	    /* block out first pipeline command */
	    if ((cmd2 = strchr(cmd1, '|')) != NULL) {
	      *cmd2++ = '\0';
	      if ((cmd3 = strchr(cmd2, '|')) != NULL)
		*cmd3++ = '\0';
	    }
	   
	    /* clean up some extra spaces in various fields */
	    chomp(cmd1);
	    chomp(cmd2);
	    chomp(cmd3);

	    /* three cmds: decrypt    | uncompress | recover
	     * two   cmds: uncompress | recover
	     * XXX note that if there are two cmds, the first one 
	     * XXX could be either uncompress or decrypt. Since no
	     * XXX code actually call uncompress_cmd/decrypt_cmd, it's ok
	     * XXX for header information.
	     * one   cmds: recover
	     */

	    if ( cmd3 == NULL) {
	      if (cmd2 == NULL) {
		strncpy(file->recover_cmd, cmd1,
			SIZEOF(file->recover_cmd) - 1);
	      } else {
		g_snprintf(file->uncompress_cmd,
			 SIZEOF(file->uncompress_cmd), "%s |", cmd1);
		strncpy(file->recover_cmd, cmd2,
			SIZEOF(file->recover_cmd) - 1);
	      }
	    } else {    /* cmd3 presents:  decrypt | uncompress | recover */
	      g_snprintf(file->decrypt_cmd,
		       SIZEOF(file->decrypt_cmd), "%s |", cmd1);
	      g_snprintf(file->uncompress_cmd,
		       SIZEOF(file->uncompress_cmd), "%s |", cmd2);
	      strncpy(file->recover_cmd, cmd3,
		      SIZEOF(file->recover_cmd) - 1);
	    }
	    continue;
	}
#undef SC
	/* XXX complain about weird lines? */
    }

out:
    amfree(buf);
    amfree(line1);
}