diff options
-rw-r--r-- | utils/nfsdcld/nfsdcld.c | 35 | ||||
-rw-r--r-- | utils/nfsdcld/sqlite.c | 73 | ||||
-rw-r--r-- | utils/nfsdcld/sqlite.h | 1 |
3 files changed, 109 insertions, 0 deletions
diff --git a/utils/nfsdcld/nfsdcld.c b/utils/nfsdcld/nfsdcld.c index a6c5239..2dfd7ec 100644 --- a/utils/nfsdcld/nfsdcld.c +++ b/utils/nfsdcld/nfsdcld.c @@ -200,6 +200,38 @@ cld_remove(struct cld_client *clnt) } static void +cld_check(struct cld_client *clnt) +{ + int ret; + ssize_t bsize, wsize; + struct cld_msg *cmsg = &clnt->cl_msg; + + xlog(D_GENERAL, "%s: check client record", __func__); + + ret = sqlite_check_client(cmsg->cm_u.cm_name.cn_id, + cmsg->cm_u.cm_name.cn_len); + + /* set up reply */ + cmsg->cm_status = ret ? -EACCES : ret; + + bsize = sizeof(*cmsg); + + xlog(D_GENERAL, "%s: downcall with status %d", __func__, + cmsg->cm_status); + wsize = atomicio((void *)write, clnt->cl_fd, cmsg, bsize); + if (wsize != bsize) { + xlog(L_ERROR, "%s: problem writing to cld pipe (%ld): %m", + __func__, wsize); + ret = cld_pipe_open(clnt); + if (ret) { + xlog(L_FATAL, "%s: unable to reopen pipe: %d", + __func__, ret); + exit(ret); + } + } +} + +static void cldcb(int UNUSED(fd), short which, void *data) { ssize_t len; @@ -230,6 +262,9 @@ cldcb(int UNUSED(fd), short which, void *data) case Cld_Remove: cld_remove(clnt); break; + case Cld_Check: + cld_check(clnt); + break; default: xlog(L_WARNING, "%s: command %u is not yet implemented", __func__, cmsg->cm_cmd); diff --git a/utils/nfsdcld/sqlite.c b/utils/nfsdcld/sqlite.c index a198c34..01bba1a 100644 --- a/utils/nfsdcld/sqlite.c +++ b/utils/nfsdcld/sqlite.c @@ -287,3 +287,76 @@ out_err: sqlite3_finalize(stmt); return ret; } + +/* + * Is the given clname in the clients table? If so, then update its timestamp + * and return success. If the record isn't present, or the update fails, then + * return an error. + */ +int +sqlite_check_client(const unsigned char *clname, const size_t namelen) +{ + int ret; + sqlite3_stmt *stmt = NULL; + + ret = sqlite3_prepare_v2(dbh, "SELECT count(*) FROM clients WHERE " + "id==?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + xlog(L_ERROR, "%s: unable to prepare update statement: %s", + __func__, sqlite3_errmsg(dbh)); + goto out_err; + } + + ret = sqlite3_bind_blob(stmt, 1, (const void *)clname, namelen, + SQLITE_STATIC); + if (ret != SQLITE_OK) { + xlog(L_ERROR, "%s: bind blob failed: %s", + __func__, sqlite3_errmsg(dbh)); + goto out_err; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + xlog(L_ERROR, "%s: unexpected return code from select: %d", + __func__, ret); + goto out_err; + } + + ret = sqlite3_column_int(stmt, 0); + xlog(D_GENERAL, "%s: select returned %d rows", ret); + if (ret != 1) { + ret = -EACCES; + goto out_err; + } + + sqlite3_finalize(stmt); + stmt = NULL; + ret = sqlite3_prepare_v2(dbh, "UPDATE OR FAIL clients SET " + "time=strftime('%s', 'now') WHERE id==?", + -1, &stmt, NULL); + if (ret != SQLITE_OK) { + xlog(L_ERROR, "%s: unable to prepare update statement: %s", + __func__, sqlite3_errmsg(dbh)); + goto out_err; + } + + ret = sqlite3_bind_blob(stmt, 1, (const void *)clname, namelen, + SQLITE_STATIC); + if (ret != SQLITE_OK) { + xlog(L_ERROR, "%s: bind blob failed: %s", + __func__, sqlite3_errmsg(dbh)); + goto out_err; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_DONE) + ret = SQLITE_OK; + else + xlog(L_ERROR, "%s: unexpected return code from update: %s", + __func__, sqlite3_errmsg(dbh)); + +out_err: + xlog(D_GENERAL, "%s: returning %d", __func__, ret); + sqlite3_finalize(stmt); + return ret; +} diff --git a/utils/nfsdcld/sqlite.h b/utils/nfsdcld/sqlite.h index 425f5ba..59ebd72 100644 --- a/utils/nfsdcld/sqlite.h +++ b/utils/nfsdcld/sqlite.h @@ -23,5 +23,6 @@ int sqlite_maindb_init(char *topdir); int sqlite_insert_client(const unsigned char *clname, const size_t namelen); int sqlite_remove_client(const unsigned char *clname, const size_t namelen); +int sqlite_check_client(const unsigned char *clname, const size_t namelen); #endif /* _SQLITE_H */ |