LOOKUP operation.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Sun, 23 Aug 2009 16:01:13 +0000 (09:01 -0700)
committerMichael Vrable <mvrable@turin.ucsd.edu>
Sun, 23 Aug 2009 16:01:13 +0000 (09:01 -0700)
nfs3/nfs3.c

index 25552a7..242875f 100644 (file)
@@ -12,6 +12,24 @@ extern BlueSkyFS *fs;
 static int null_int;
 static void *null_result = (void *)&null_int;
 
+/* Check that a string is a valid file name.  We require that it be valid
+ * UTF-8, that it not be empty, and that it not contain embedded forward
+ * slashes.  Also checks that the length of the string is not more than the
+ * maximum allowed length.  This function does allow the names "." and "..".
+ * Returns TRUE if te string is allowed as a filename. */
+gboolean validate_filename(const char *filename)
+{
+    if (filename == NULL || filename[0] == '\0')
+        return FALSE;
+    if (strlen(filename) > 255)
+        return FALSE;
+    if (!g_utf8_validate(filename, -1, NULL))
+        return FALSE;
+    if (strchr(filename, '/') != NULL)
+        return FALSE;
+    return TRUE;
+}
+
 /* Look up a BlueSkyInode given an NFS filehandle.  Returns NULL if the
  * filehandle is invalid. */
 BlueSkyInode *lookup_fh(nfs_fh3 *fh)
@@ -84,7 +102,44 @@ nfsproc3_lookup_3_svc(diropargs3 *argp, struct svc_req *rqstp)
 {
     static lookup3res result;
 
-    result.status = NFS3ERR_NOTSUPP;
+    BlueSkyInode *dir = lookup_fh(&argp->dir);
+    if (dir == NULL) {
+        result.status = NFS3ERR_STALE;
+        result.lookup3res_u.resfail.present = FALSE;
+        return &result;
+    }
+
+    result.lookup3res_u.resfail.present = TRUE;
+    encode_fattr3(&result.lookup3res_u.resfail.post_op_attr_u.attributes, dir);
+    if (!validate_filename(argp->name)) {
+        if (strlen(argp->name) > 255)
+            result.status = NFS3ERR_NAMETOOLONG;
+        else
+            result.status = NFS3ERR_NOENT;
+        return &result;
+    }
+
+    /* TODO: Special-case "." and "..". */
+    uint64_t inum = bluesky_directory_lookup(dir, argp->name);
+    if (inum == 0) {
+        result.status = NFS3ERR_NOENT;
+        return &result;
+    }
+    BlueSkyInode *inode = bluesky_get_inode(fs, inum);
+    if (inode == NULL) {
+        result.status = NFS3ERR_NOENT;
+        return &result;
+    }
+
+    result.lookup3res_u.resok.dir_attributes.present = TRUE;
+    encode_fattr3(&result.lookup3res_u.resok.dir_attributes.post_op_attr_u.attributes, dir);
+    result.lookup3res_u.resok.obj_attributes.present = TRUE;
+    encode_fattr3(&result.lookup3res_u.resok.obj_attributes.post_op_attr_u.attributes, inode);
+
+    static uint64_t fh_bytes;
+    fh_bytes = GUINT64_TO_BE(inum);
+    result.lookup3res_u.resok.object.data.data_len = 8;
+    result.lookup3res_u.resok.object.data.data_val = (char *)&fh_bytes;
 
     return &result;
 }