components/visual-panels/core/src/cmd/rad/mod/files/mod_files.c
changeset 827 0944d8c0158b
child 901 19b502ccabc8
equal deleted inserted replaced
826:c6aad84d2493 827:0944d8c0158b
       
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 /*
       
    27  * Unfortunately, the behavior this module has inherited is not one
       
    28  * of "get me information about file X or directory Y", but "tell me
       
    29  * what calling 'new File(X)' would do in Java".  This includes
       
    30  * nonsense like manufacturing correct fake data for nonexistent
       
    31  * files.
       
    32  *
       
    33  * This sorely needs to be ripped out and replaced with a sane
       
    34  * api.
       
    35  */
       
    36 
       
    37 #include <sys/stat.h>
       
    38 #include <sys/types.h>
       
    39 #include <string.h>
       
    40 #include <stdio.h>
       
    41 #include <stdlib.h>
       
    42 #include <unistd.h>
       
    43 #include <time.h>
       
    44 #include <dirent.h>
       
    45 #include <libgen.h>
       
    46 #include <limits.h>
       
    47 
       
    48 #include <rad/adr.h>
       
    49 #include <rad/rad_modapi.h>
       
    50 
       
    51 #include "api_file.h"
       
    52 
       
    53 static data_t *
       
    54 empty_file(data_t *data, const char *apath, const char *cpath)
       
    55 {
       
    56 	struct_set(data, "absolutePath", data_new_string(apath, lt_copy));
       
    57 	struct_set(data, "canonicalPath", data_new_string(cpath, lt_copy));
       
    58 	struct_set(data, "canonical", data_new_boolean(B_TRUE));
       
    59 	struct_set(data, "baseName", data_new_string("", lt_copy));
       
    60 	struct_set(data, "exists", data_new_boolean(B_FALSE));
       
    61 	struct_set(data, "readable", data_new_boolean(B_FALSE));
       
    62 	struct_set(data, "writable", data_new_boolean(B_FALSE));
       
    63 	struct_set(data, "hidden", data_new_boolean(B_FALSE));
       
    64 	struct_set(data, "directory", data_new_boolean(B_FALSE));
       
    65 	struct_set(data, "file", data_new_boolean(B_FALSE));
       
    66 	struct_set(data, "lastModified", data_new_time(0, 0));
       
    67 	struct_set(data, "length", data_new_long(0));
       
    68 	struct_set(data, "freeSpace", data_new_long(0));
       
    69 	struct_set(data, "totalSpace", data_new_long(0));
       
    70 	struct_set(data, "usableSpace", data_new_long(0));
       
    71 	return (data_purify(data));
       
    72 }
       
    73 
       
    74 static data_t *
       
    75 read_file(const char *path, const char *file)
       
    76 {
       
    77 	struct stat64 st;
       
    78 	char apath[PATH_MAX] = "";
       
    79 	char cpath[PATH_MAX] = "";
       
    80 	const char *name = file != NULL ? file : path;
       
    81 
       
    82 	data_t *data = data_new_struct(&t__FileSnapshot);
       
    83 	struct_set(data, "path", data_new_string(name, lt_copy));
       
    84 	struct_set(data, "absolute", data_new_boolean(name[0] == '/'));
       
    85 
       
    86 	if (path[0] != '/') {
       
    87 		if (getcwd(apath, PATH_MAX) == NULL) {
       
    88 			data_free(data);
       
    89 			return (NULL);
       
    90 		}
       
    91 		if (apath[1] != '\0')
       
    92 			(void) strlcat(apath, "/", PATH_MAX);
       
    93 		(void) strlcat(apath, path, PATH_MAX);
       
    94 	} else {
       
    95 		(void) strlcpy(apath, path, PATH_MAX);
       
    96 	}
       
    97 
       
    98 	if (resolvepath(apath, cpath, PATH_MAX) == -1 ||
       
    99 	    stat64(path, &st) == -1)
       
   100 		return (empty_file(data, apath, apath));
       
   101 
       
   102 	struct_set(data, "absolutePath", data_new_string(apath, lt_copy));
       
   103 	struct_set(data, "canonicalPath", data_new_string(cpath, lt_copy));
       
   104 	struct_set(data, "canonical",
       
   105 	    data_new_boolean(strcmp(apath, cpath) == 0));
       
   106 	struct_set(data, "baseName", data_new_string(basename(apath), lt_copy));
       
   107 	struct_set(data, "exists", data_new_boolean(B_TRUE));
       
   108 	struct_set(data, "readable", data_new_boolean(access(path, R_OK) == 0));
       
   109 	struct_set(data, "writable", data_new_boolean(access(path, W_OK) == 0));
       
   110 	struct_set(data, "hidden", data_new_boolean(B_FALSE));
       
   111 	struct_set(data, "directory", data_new_boolean(S_ISDIR(st.st_mode)));
       
   112 	struct_set(data, "file", data_new_boolean(S_ISREG(st.st_mode)));
       
   113 	struct_set(data, "lastModified", data_new_time_ts(&st.st_mtim));
       
   114 	/* XXX: 64-bitify */
       
   115 	struct_set(data, "length", data_new_long(st.st_size));
       
   116 	struct_set(data, "freeSpace", data_new_long(0));
       
   117 	struct_set(data, "totalSpace", data_new_long(0));
       
   118 	struct_set(data, "usableSpace", data_new_long(0));
       
   119 	return (data_purify(data));
       
   120 }
       
   121 
       
   122 /* ARGSUSED */
       
   123 conerr_t
       
   124 interface_FileBrowser_read_roots(rad_instance_t *inst, adr_attribute_t *attr,
       
   125     data_t **data, data_t **error)
       
   126 {
       
   127 	data_t *result = data_new_array(&t_array__FileSnapshot, 1);
       
   128 	(void) array_add(result, read_file("/", NULL));
       
   129 	*data = data_purify(result);
       
   130 	return (ce_ok);
       
   131 }
       
   132 
       
   133 /* ARGSUSED */
       
   134 conerr_t
       
   135 interface_FileBrowser_invoke_getFile(rad_instance_t *inst, adr_method_t *meth,
       
   136     data_t **ret, data_t **args, int count, data_t **error)
       
   137 {
       
   138 	*ret = read_file(data_to_string(args[0]), NULL);
       
   139 	return (ce_ok);
       
   140 }
       
   141 
       
   142 /* ARGSUSED */
       
   143 conerr_t
       
   144 interface_FileBrowser_invoke_getFiles(rad_instance_t *inst, adr_method_t *meth,
       
   145     data_t **ret, data_t **args, int count, data_t **error)
       
   146 {
       
   147 	const char *path = data_to_string(args[0]);
       
   148 	DIR *d = opendir(path);
       
   149 	struct dirent *ent;
       
   150 	data_t *result;
       
   151 
       
   152 	if (d == NULL)
       
   153 		return (ce_object);
       
   154 
       
   155 	result = data_new_array(&t_array__FileSnapshot, 1);
       
   156 	while ((ent = readdir(d)) != NULL) {
       
   157 		char buf[PATH_MAX];
       
   158 		if (strcmp(ent->d_name, ".") == 0 ||
       
   159 		    strcmp(ent->d_name, "..") == 0)
       
   160 			continue;
       
   161 		int len = strlen(path);
       
   162 		while (len > 0 && path[len - 1] == '/')
       
   163 			len--;
       
   164 		(void) snprintf(buf, PATH_MAX, "%.*s/%s", len, path,
       
   165 		    ent->d_name);
       
   166 		data_t *file = read_file(buf, NULL);
       
   167 		if (file != NULL)
       
   168 			(void) array_add(result, file);
       
   169 	}
       
   170 	(void) closedir(d);
       
   171 	*ret = data_purify(result);
       
   172 
       
   173 	return (ce_ok);
       
   174 }
       
   175 
       
   176 static rad_modinfo_t modinfo = { "files", "File Browser module" };
       
   177 
       
   178 int
       
   179 _rad_init(void *handle)
       
   180 {
       
   181 	if (rad_module_register(handle, RAD_MODVERSION, &modinfo) == -1)
       
   182 		return (-1);
       
   183 
       
   184 	if (rad_isproxy)
       
   185 		return (0);
       
   186 
       
   187 	(void) cont_insert_singleton(rad_container, adr_name_fromstr(
       
   188 	    "com.oracle.solaris.vp.panel.common.api.file:type=FileBrowser"),
       
   189 	    &interface_FileBrowser_svr);
       
   190 
       
   191 	return (0);
       
   192 }