--- a/usr/src/cmd/rad/mod/files/mod_files.c Wed Dec 16 14:25:49 2009 -0500
+++ b/usr/src/cmd/rad/mod/files/mod_files.c Wed Dec 16 19:06:12 2009 -0800
@@ -24,6 +24,17 @@
* Use is subject to license terms.
*/
+/*
+ * Unfortunately, the behavior this module has inherited is not one
+ * of "get me information about file X or directory Y", but "tell me
+ * what calling 'new File(X)' would do in Java". This includes
+ * nonsense like manufacturing correct fake data for nonexistent
+ * files.
+ *
+ * This sorely needs to be ripped out and replaced with a sane
+ * interface.
+ */
+
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
@@ -33,6 +44,7 @@
#include <time.h>
#include <dirent.h>
#include <libgen.h>
+#include <limits.h>
#include "rad_adr.h"
#include "rad_object.h"
@@ -41,47 +53,72 @@
#include "api_file.h"
static data_t *
-read_file(const char *path)
+empty_file(data_t *data, const char *apath, const char *cpath)
{
- char foo[1000];
- char bar[1000] = { 0 };
+ struct_set(data, "absolutePath", data_new_string(apath, lt_copy));
+ struct_set(data, "canonicalPath", data_new_string(cpath, lt_copy));
+ struct_set(data, "canonical", data_new_boolean(B_TRUE));
+ struct_set(data, "baseName", data_new_string("", lt_copy));
+ struct_set(data, "exists", data_new_boolean(B_FALSE));
+ struct_set(data, "readable", data_new_boolean(B_FALSE));
+ struct_set(data, "writable", data_new_boolean(B_FALSE));
+ struct_set(data, "hidden", data_new_boolean(B_FALSE));
+ struct_set(data, "directory", data_new_boolean(B_FALSE));
+ struct_set(data, "file", data_new_boolean(B_FALSE));
+ struct_set(data, "lastModified", data_new_time(0));
+ struct_set(data, "length", data_new_long(0));
+ struct_set(data, "freeSpace", data_new_long(0));
+ struct_set(data, "totalSpace", data_new_long(0));
+ struct_set(data, "usableSpace", data_new_long(0));
+ return (data_purify(data));
+}
- data_t *root = data_new_struct(&t__FileSnapshot);
- struct_set(root, "path", data_new_string(path, lt_copy));
+static data_t *
+read_file(const char *path, const char *file)
+{
+ struct stat64 st;
+ char apath[PATH_MAX] = "";
+ char cpath[PATH_MAX] = "";
+ const char *name = file != NULL ? file : path;
+
+ data_t *data = data_new_struct(&t__FileSnapshot);
+ struct_set(data, "path", data_new_string(name, lt_copy));
+ struct_set(data, "absolute", data_new_boolean(name[0] == '/'));
if (path[0] != '/') {
- getcwd(foo, 1000);
- strlcat(foo, "/", 1000);
- strlcat(foo, path, 1000);
+ if (getcwd(apath, PATH_MAX) == NULL) {
+ data_free(data);
+ return (NULL);
+ }
+ if (apath[1] != '\0')
+ strlcat(apath, "/", PATH_MAX);
+ strlcat(apath, path, PATH_MAX);
} else {
- strlcpy(foo, path, 1000);
- }
- struct_set(root, "absolutePath", data_new_string(foo, lt_copy));
- struct_set(root, "baseName", data_new_string(basename(foo), lt_copy));
-
- resolvepath(foo, bar, 1000);
- struct_set(root, "canonicalPath", data_new_string(bar, lt_copy));
- struct_set(root, "absolute", data_new_boolean(B_TRUE));
- struct_set(root, "canonical", data_new_boolean(strcmp(foo, bar) == 0));
- struct_set(root, "exists", data_new_boolean(B_TRUE));
- struct_set(root, "readable", data_new_boolean(access(path, R_OK) == 0));
- struct_set(root, "writable", data_new_boolean(access(path, W_OK) == 0));
- struct_set(root, "directory", data_new_boolean(B_TRUE));
- struct_set(root, "file", data_new_boolean(B_FALSE));
- struct_set(root, "hidden", data_new_boolean(B_FALSE));
- struct stat st;
- if (stat(path, &st) == -1) {
- data_free(root);
- return (NULL);
+ strlcpy(apath, path, PATH_MAX);
}
- struct_set(root, "lastModified", data_new_time(st.st_mtime));
+ if (resolvepath(apath, cpath, PATH_MAX) == -1 ||
+ stat64(path, &st) == -1)
+ return (empty_file(data, apath, apath));
+
+ struct_set(data, "absolutePath", data_new_string(apath, lt_copy));
+ struct_set(data, "canonicalPath", data_new_string(cpath, lt_copy));
+ struct_set(data, "canonical",
+ data_new_boolean(strcmp(apath, cpath) == 0));
+ struct_set(data, "baseName", data_new_string(basename(apath), lt_copy));
+ struct_set(data, "exists", data_new_boolean(B_TRUE));
+ struct_set(data, "readable", data_new_boolean(access(path, R_OK) == 0));
+ struct_set(data, "writable", data_new_boolean(access(path, W_OK) == 0));
+ struct_set(data, "hidden", data_new_boolean(B_FALSE));
+ struct_set(data, "directory", data_new_boolean(S_ISDIR(st.st_mode)));
+ struct_set(data, "file", data_new_boolean(S_ISREG(st.st_mode)));
+ struct_set(data, "lastModified", data_new_time(st.st_mtime));
/* XXX: 64-bitify */
- struct_set(root, "length", data_new_integer(st.st_size));
- struct_set(root, "freeSpace", data_new_integer(0));
- struct_set(root, "totalSpace", data_new_integer(0));
- struct_set(root, "usableSpace", data_new_integer(0));
- return (root);
+ struct_set(data, "length", data_new_long(st.st_size));
+ struct_set(data, "freeSpace", data_new_long(0));
+ struct_set(data, "totalSpace", data_new_long(0));
+ struct_set(data, "usableSpace", data_new_long(0));
+ return (data_purify(data));
}
/* ARGSUSED */
@@ -90,8 +127,8 @@
data_t **data, data_t **error)
{
data_t *result = data_new_array(&t_array__FileSnapshot, 1);
- array_add(result, read_file("/"));
- *data = result;
+ array_add(result, read_file("/", NULL));
+ *data = data_purify(result);
return (ce_ok);
}
@@ -100,7 +137,7 @@
api_fileBrowser_invoke_getFile(struct instance *inst, struct method *meth,
data_t **ret, data_t **args, int count, data_t **error)
{
- *ret = read_file(args[0]->d_data.string);
+ *ret = read_file(args[0]->d_data.string, NULL);
return (ce_ok);
}
@@ -119,20 +156,20 @@
result = data_new_array(&t_array__FileSnapshot, 1);
while ((ent = readdir(d)) != NULL) {
- char buf[1000];
+ char buf[PATH_MAX];
if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0)
continue;
int len = strlen(path);
while (len > 0 && path[len - 1] == '/')
len--;
- snprintf(buf, 1000, "%.*s/%s", len, path, ent->d_name);
- data_t *file = read_file(buf);
+ snprintf(buf, PATH_MAX, "%.*s/%s", len, path, ent->d_name);
+ data_t *file = read_file(buf, NULL);
if (file != NULL)
array_add(result, file);
}
- closedir(d);
- *ret = result;
+ (void) closedir(d);
+ *ret = data_purify(result);
return (ce_ok);
}