static void statusrec_fini(struct statusrec *sr) { fattr_free(sr->sr_serverattr); fattr_free(sr->sr_clientattr); free(sr->sr_file); }
static int statusrec_cook(struct statusrec *sr, char *line) { char *clientattr, *serverattr; switch (sr->sr_type) { case SR_FILEDEAD: case SR_FILELIVE: clientattr = proto_get_ascii(&line); if (clientattr == NULL || line != NULL) return (-1); sr->sr_clientattr = fattr_decode(clientattr); if (sr->sr_clientattr == NULL) return (-1); break; case SR_DIRDOWN: /* Nothing to do. */ if (line != NULL) return (-1); break; case SR_CHECKOUTLIVE: sr->sr_tag = proto_get_ascii(&line); sr->sr_date = proto_get_ascii(&line); serverattr = proto_get_ascii(&line); sr->sr_revnum = proto_get_ascii(&line); sr->sr_revdate = proto_get_ascii(&line); clientattr = proto_get_ascii(&line); if (clientattr == NULL || line != NULL) return (-1); sr->sr_serverattr = fattr_decode(serverattr); if (sr->sr_serverattr == NULL) return (-1); sr->sr_clientattr = fattr_decode(clientattr); if (sr->sr_clientattr == NULL) { fattr_free(sr->sr_serverattr); return (-1); } break; case SR_CHECKOUTDEAD: sr->sr_tag = proto_get_ascii(&line); sr->sr_date = proto_get_ascii(&line); serverattr = proto_get_ascii(&line); if (serverattr == NULL || line != NULL) return (-1); sr->sr_serverattr = fattr_decode(serverattr); if (sr->sr_serverattr == NULL) return (-1); break; case SR_DIRUP: clientattr = proto_get_ascii(&line); if (clientattr == NULL || line != NULL) return (-1); sr->sr_clientattr = fattr_decode(clientattr); if (sr->sr_clientattr == NULL) return (-1); break; default: return (-1); } return (0); }
/* * Open the status file. If scantime is not -1, the file is opened * for updating, otherwise, it is opened read-only. If the status file * couldn't be opened, NULL is returned and errmsg is set to the error * message. */ struct status * status_open(struct coll *coll, time_t scantime, char **errmsg) { struct status *st; struct stream *file; struct fattr *fa; char *destpath, *path; int error, rv; path = coll_statuspath(coll); file = stream_open_file(path, O_RDONLY); if (file == NULL) { if (errno != ENOENT) { xasprintf(errmsg, "Could not open \"%s\": %s\n", path, strerror(errno)); free(path); return (NULL); } st = status_fromnull(path); } else { st = status_fromrd(path, file); if (st == NULL) { xasprintf(errmsg, "Error in \"%s\": Bad header line", path); free(path); return (NULL); } } if (scantime != -1) { /* Open for writing too. */ xasprintf(&destpath, "%s/%s/%s/", coll->co_base, coll->co_colldir, coll->co_name); st->tempfile = tempname(destpath); if (mkdirhier(destpath, coll->co_umask) != 0) { xasprintf(errmsg, "Cannot create directories leading " "to \"%s\": %s", destpath, strerror(errno)); free(destpath); status_free(st); return (NULL); } free(destpath); st->wr = stream_open_file(st->tempfile, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (st->wr == NULL) { xasprintf(errmsg, "Cannot create \"%s\": %s", st->tempfile, strerror(errno)); status_free(st); return (NULL); } fa = fattr_new(FT_FILE, -1); fattr_mergedefault(fa); fattr_umask(fa, coll->co_umask); rv = fattr_install(fa, st->tempfile, NULL); fattr_free(fa); if (rv == -1) { xasprintf(errmsg, "Cannot set attributes for \"%s\": %s", st->tempfile, strerror(errno)); status_free(st); return (NULL); } if (scantime != st->scantime) st->dirty = 1; error = proto_printf(st->wr, "F %d %t\n", STATUS_VERSION, scantime); if (error) { st->error = STATUS_ERR_WRITE; st->suberror = errno; *errmsg = status_errmsg(st); status_free(st); return (NULL); } } return (st); }
static bool readdir_iter(DB_TXN *txn, const struct fsdb_de_key *key, size_t key_len, nfsino_t dirent, struct readdir_info *ri) { uint64_t bitmap_out = 0; uint32_t dirlen, maxlen; struct nfs_fattr_set attr; struct nfs_inode *ino = NULL; struct list_head *writes = ri->writes; struct rpc_write **wr = ri->wr; size_t name_len; struct nfs_buf de_name; if (ri->stop) return true; if (!ri->cookie_found) { if (ri->cookie && (ri->dir_pos <= ri->cookie)) { ri->dir_pos++; return false; } ri->cookie_found = true; } ino = inode_getdec(txn, dirent, 0); if (!ino) { applog(LOG_WARNING, " WARNING: inode %016llX not found", (unsigned long long) dirent); /* FIXME: return via rdattr-error */ ri->stop = true; ri->status = NFS4ERR_NOENT; return true; } memset(&attr, 0, sizeof(attr)); fattr_fill(ino, &attr); name_len = key_len - sizeof(*key); dirlen = 8 + 4 + (XDR_QUADLEN(name_len) * 4); if (dirlen > ri->dircount) { ri->hit_limit = true; ri->stop = true; if (debugging > 1) applog(LOG_DEBUG, " iter: hit dir limit"); goto out; } maxlen = 8 + 4 + (XDR_QUADLEN(name_len) * 4) + 16 + fattr_size(&attr) + 4; if (maxlen > ri->maxcount) { ri->hit_limit = true; ri->stop = true; if (debugging > 1) applog(LOG_DEBUG, " iter: hit max limit"); goto out; } if (ri->first_time) { ri->first_time = false; /* FIXME: server verifier isn't the best for dir verf */ WRMEM(&srv.instance_verf, sizeof(verifier4)); /* cookieverf */ ri->val_follows = WRSKIP(4); } ri->dircount -= dirlen; ri->maxcount -= maxlen; /* write value to previous entry4.nextentry */ *ri->val_follows = htonl(1); ri->val_follows = NULL; WR64(ri->dir_pos); /* entry4.cookie */ de_name.len = name_len; de_name.val = (void *) key->name; /* cast is ok: RO data is copied */ WRBUF(&de_name); /* entry4.name */ /* entry4.attrs */ attr.bitmap = ri->attr_request; ri->status = wr_fattr(&attr, &bitmap_out, writes, wr); if (ri->status != NFS4_OK) ri->stop = true; if (debugging) applog(LOG_DEBUG, " READDIR ent: '%.*s' (INO:%016llX MAP:%Lx WRLEN:%u)", (int) name_len, key->name, (unsigned long long) dirent, (unsigned long long) bitmap_out, (*wr)->len); ri->val_follows = WRSKIP(4); /* entry4.nextentry */ ri->n_results++; ri->dir_pos++; out: inode_free(ino); fattr_free(&attr); if (ri->stop) return true; return false; }