/* * 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; } }
/* * 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; } }
/* * 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); }
/* * 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); }
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); }
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"); }
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; }
/* * 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); }
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; }
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; }
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); }