00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <ctype.h>
00022 #include <errno.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <sys/stat.h>
00026
00027 #include "htctrl.h"
00028 #include "htiobox.h"
00029 #include "htkeyb.h"
00030 #include "htreg.h"
00031 #include "htsys.h"
00032 #include "httag.h"
00033 #include "htstring.h"
00034 #include "snprintf.h"
00035 #include "store.h"
00036 #include "tools.h"
00037 #include "vfs.h"
00038
00039 static bool unix_is_path_delim(char c)
00040 {
00041 return c == '/';
00042 }
00043
00044
00045
00046
00047
00048 void LocalFs::init()
00049 {
00050 Vfs::init();
00051 }
00052
00053 void LocalFs::done()
00054 {
00055 Vfs::done();
00056 }
00057
00058 int LocalFs::canonicalize(char *result, const char *filename, const char *cwd)
00059 {
00060 sys_common_canonicalize(result, filename, cwd, sys_is_path_delim);
00061 return 0;
00062 }
00063
00064 int LocalFs::compareFilenames(const char *a, const char *b)
00065 {
00066
00067 if (strcmp(a, "..")==0) return -1;
00068 if (strcmp(b, "..")==0) return 1;
00069 return ht_stricmp(a, b);
00070 }
00071
00072 int LocalFs::createFile(const char *filename, UINT createtype)
00073 {
00074
00075 return ENOSYS;
00076 }
00077
00078 int LocalFs::deleteFile(const char *filename)
00079 {
00080
00081 if ((filename[0] != '/') && (filename[0] != '\\') &&
00082 ((filename[1]!=':') && (filename[2]!='/') && (filename[2]!='\\')))
00083 return ENOENT;
00084 return remove(filename);
00085 }
00086
00087 void *LocalFs::enumFiletype(UINT *type, char **name, void *handle)
00088 {
00089 *type = 0;
00090 *name = "file";
00091 return NULL;
00092 }
00093
00094 bool LocalFs::findFirst(const char *dirname, pfind_t *f)
00095 {
00096 return (sys_findfirst(dirname, f)==0);
00097 }
00098
00099 bool LocalFs::findNext(pfind_t *f)
00100 {
00101 return (sys_findnext(f)==0);
00102 }
00103
00104 bool LocalFs::findClose(pfind_t *f)
00105 {
00106 return (sys_findclose(f)==0);
00107 }
00108
00109 int LocalFs::getCaps()
00110 {
00111 return VFSCAP_WRITABLE;
00112 }
00113
00114 const char *LocalFs::getProtoName()
00115 {
00116 return "local";
00117 }
00118
00119 is_path_delim LocalFs::isPathDelim()
00120 {
00121 return sys_is_path_delim;
00122 }
00123
00124 int LocalFs::makeDir(const char *dirname)
00125 {
00126 return ENOSYS;
00127
00128 }
00129
00130 int LocalFs::open(const char *filename, bool edit)
00131 {
00132 return ENOSYS;
00133 }
00134
00135 int LocalFs::pstat(pstat_t *s, const char *filename)
00136 {
00137 return sys_pstat(s, filename);
00138 }
00139
00140 int LocalFs::renameFile(const char *filename, const char *newname)
00141 {
00142 return rename(filename, newname);
00143 }
00144
00145 int LocalFs::fileClose(ht_streamfile *f)
00146 {
00147 f->done();
00148 int e=f->get_error();
00149 delete f;
00150 return e;
00151 }
00152
00153 int LocalFs::fileOpen(const char *filename, UINT access_mode, UINT open_mode, ht_streamfile **f)
00154 {
00155 ht_file *file=new ht_file();
00156 file->init(filename, access_mode, open_mode);
00157 int e=file->get_error();
00158 if (e) {
00159 file->done();
00160 delete file;
00161 return e;
00162 }
00163 *f=file;
00164 return 0;
00165 }
00166
00167
00168
00169
00170
00171 #define REGNODE_FILE_MAGIC "HTRG"
00172
00173 void RegNodeFile::init(const char *nn, UINT am, UINT om)
00174 {
00175 access_mode0 = am;
00176 ht_mem_file::init(0, 1024, am);
00177 open_mode = om;
00178 nodename = ht_strdup(nn);
00179 if ((access_mode & FAM_READ) && (access_mode & FAM_WRITE)) {
00180 set_error(EINVAL);
00181 return;
00182 }
00183
00184 ht_registry_node_type type;
00185 ht_registry_data *data;
00186 if (!(open_mode & FOM_CREATE)) {
00187 if (!registry->find_data_entry(nodename, &data, &type, false)) {
00188 set_error(ENOENT);
00189 return;
00190 }
00191 }
00192 if (access_mode & FAM_READ) {
00193 if (open_mode & FOM_CREATE) {
00194 set_error(EINVAL);
00195 return;
00196 }
00197 ht_object_stream_bin *o = new ht_object_stream_bin();
00198 o->init(this);
00199
00200 store_node(o, type, data);
00201
00202 o->done();
00203 delete o;
00204
00205 seek(0);
00206 }
00207 }
00208
00209 void RegNodeFile::done()
00210 {
00211 if (access_mode & FAM_WRITE) {
00212 ht_registry_node_type type;
00213 ht_registry_data *data;
00214
00215 seek(0);
00216
00217 ht_object_stream_bin *o=new ht_object_stream_bin();
00218 o->init(this);
00219
00220 int e=load_node(o, &type, &data);
00221
00222 if (e==0) {
00223 if (open_mode & FOM_CREATE) {
00224 if ((e = registry->create_node(nodename, type))) {
00225 set_error(e);
00226 }
00227 }
00228 registry->set_node(nodename, type, data);
00229
00230 htmsg m;
00231 m.msg = msg_config_changed;
00232 m.type = mt_broadcast;
00233 app->sendmsg(&m);
00234 } else set_error(e);
00235
00236 o->done();
00237 delete o;
00238 }
00239 free(nodename);
00240 ht_mem_file::done();
00241 }
00242
00243 int RegNodeFile::load_node(ht_object_stream *s, ht_registry_node_type *type, ht_registry_data **data)
00244 {
00245 byte magic[4];
00246 int n = s->read(magic, sizeof magic);
00247 if ((n != sizeof magic) || memcmp(magic, REGNODE_FILE_MAGIC, 4)==0) {
00248 *type = s->getIntDec(4, NULL);
00249 *data = (ht_registry_data*)s->getObject(NULL);
00250 return s->get_error();
00251 }
00252
00253 ht_mem_file *g = new ht_mem_file();
00254 g->init();
00255 g->write(magic, n);
00256 s->copy_to(g);
00257 ht_registry_data_raw *d = new ht_registry_data_raw(g->bufptr(), g->get_size());
00258 g->done();
00259 delete g;
00260
00261 *type=RNT_RAW;
00262 *data=d;
00263 return s->get_error();
00264 }
00265
00266 void RegNodeFile::store_node(ht_object_stream *s, ht_registry_node_type type, ht_registry_data *data)
00267 {
00268 if (type==RNT_RAW) {
00269 ht_registry_data_raw *d=(ht_registry_data_raw*)data;
00270 s->write(d->value, d->size);
00271 } else {
00272 s->write((void*)REGNODE_FILE_MAGIC, 4);
00273 s->putIntDec(type, 4, NULL);
00274 s->putObject(data, NULL);
00275 }
00276 }
00277
00278 bool RegNodeFile::set_access_mode(UINT am)
00279 {
00280 access_mode = access_mode0;
00281 return (am == access_mode0);
00282 }
00283
00284
00285
00286
00287
00288 void RegistryFs::init()
00289 {
00290 Vfs::init();
00291 enum_last = NULL;
00292 enum_dir = NULL;
00293 }
00294
00295 void RegistryFs::done()
00296 {
00297 Vfs::done();
00298 }
00299
00300 int RegistryFs::canonicalize(char *result, const char *filename, const char *cwd)
00301 {
00302 ht_registry_data *data;
00303 ht_registry_node_type type;
00304
00305 sys_common_canonicalize(result, filename, cwd, unix_is_path_delim);
00306 return registry->find_data_entry(result, &data, &type, 0);
00307 }
00308
00309 void RegistryFs::create_pfind_t(pfind_t *f, const char *key, ht_registry_data *data, ht_registry_node_type type)
00310 {
00311 f->name = key;
00312 f->stat.caps = pstat_mode_type | pstat_desc;
00313 create_pstat_t(&f->stat, data, type);
00314 data->strvalue(f->stat.desc);
00315 }
00316
00317 void RegistryFs::create_pstat_t(pstat_t *s, ht_registry_data *data, ht_registry_node_type type)
00318 {
00319 s->caps = pstat_mode_type | pstat_desc;
00320 s->mode = 0;
00321 switch (type) {
00322 case RNT_SUBDIR:
00323 s->mode |= HT_S_IFDIR;
00324 break;
00325 case RNT_SYMLINK:
00326 s->mode |= HT_S_IFLNK;
00327 break;
00328 case RNT_RAW:
00329 s->caps |= pstat_size;
00330 s->size = ((ht_registry_data_raw *)data)->size;
00331 default:
00332 s->mode |= HT_S_IFREG;
00333 }
00334 }
00335
00336 int RegistryFs::createFile(const char *filename, UINT createtype)
00337 {
00338 int e=registry->create_node(filename, createtype);
00339 htmsg m;
00340 m.msg=msg_config_changed;
00341 m.type=mt_broadcast;
00342 app->sendmsg(&m);
00343 return e;
00344 }
00345
00346 int RegistryFs::deleteFile(const char *filename)
00347 {
00348 int e=registry->delete_node(filename);
00349 htmsg m;
00350 m.msg=msg_config_changed;
00351 m.type=mt_broadcast;
00352 app->sendmsg(&m);
00353 return e;
00354 }
00355
00356 void *RegistryFs::enumFiletype(UINT *type, char **name, void *handle)
00357 {
00358 ht_data_string *key = (ht_data_string*)handle;
00359 ht_registry_node_type_desc *value;
00360 do {
00361 key = (ht_data_string *)registry->node_types->enum_next((Object**)&value, key);
00362 } while (value && (value->type==RNT_SUBDIR));
00363 if (key && value) {
00364 *type=value->type;
00365 *name=key->value;
00366 return key;
00367 }
00368 return NULL;
00369 }
00370
00371 int RegistryFs::compareFilenames(const char *a, const char *b)
00372 {
00373 if (strcmp(a, "..")==0) return -1;
00374 if (strcmp(b, "..")==0) return 1;
00375 return strcmp(a, b);
00376 }
00377
00378 bool RegistryFs::findFirst(const char *dirname, pfind_t *f)
00379 {
00380 const char *key;
00381 ht_registry_data *data;
00382 ht_registry_node_type type;
00383
00384 if (enum_last) free(enum_last);
00385 enum_last = NULL;
00386 if (enum_dir) free(enum_dir);
00387 enum_dir = NULL;
00388 if ((strcmp(dirname, "/")==0) || (strcmp(dirname, "")==0)){
00389 if ((key = registry->enum_next(&data, &type, dirname, NULL))) {
00390 enum_last = strdup(key);
00391 enum_dir = strdup(dirname);
00392 create_pfind_t(f, key, data, type);
00393 return true;
00394 }
00395 } else {
00396 enum_dir = strdup(dirname);
00397 f->name="..";
00398 f->stat.caps=pstat_mode_type;
00399 f->stat.mode=HT_S_IFDIR;
00400 return true;
00401 }
00402 return false;
00403 }
00404
00405 bool RegistryFs::findNext(pfind_t *f)
00406 {
00407 const char *key;
00408 ht_registry_data *data;
00409 ht_registry_node_type type;
00410
00411 if ((key = registry->enum_next(&data, &type, enum_dir, enum_last))) {
00412 if (enum_last) free(enum_last);
00413 enum_last = strdup(key);
00414 create_pfind_t(f, key, data, type);
00415 return true;
00416 }
00417 return false;
00418 }
00419
00420 bool RegistryFs::findClose(pfind_t *f)
00421 {
00422 return true;
00423 }
00424
00425 int RegistryFs::getCaps()
00426 {
00427 return VFSCAP_WRITABLE;
00428 }
00429
00430 const char *RegistryFs::getProtoName()
00431 {
00432 return "reg";
00433 }
00434
00435 is_path_delim RegistryFs::isPathDelim()
00436 {
00437 return unix_is_path_delim;
00438 }
00439
00440 int RegistryFs::makeDir(const char *dirname)
00441 {
00442 return registry->create_subdir(dirname);
00443 }
00444
00445 int RegistryFs::open(const char *filename, bool edit)
00446 {
00447 ht_registry_data *data;
00448 ht_registry_node_type type;
00449
00450 if (registry->find_data_entry(filename, &data, &type, false)) {
00451 if (data->editdialog(filename)) {
00452 htmsg m;
00453 m.msg=msg_config_changed;
00454 m.type=mt_broadcast;
00455 app->sendmsg(&m);
00456 }
00457 return 0;
00458 }
00459 return ENOSYS;
00460 }
00461
00462 int RegistryFs::pstat(pstat_t *s, const char *filename)
00463 {
00464 ht_registry_data *data;
00465 ht_registry_node_type type;
00466
00467 char key[VFS_DIR_MAX];
00468 ht_snprintf(key, sizeof key, "%s", filename);
00469 int l = strlen(key)-1;
00470 if ((l>=0) && (key[l] == '/')) key[l]=0;
00471 if (registry->find_any_entry(key, &data, &type)) {
00472 create_pstat_t(s, data, type);
00473 return 0;
00474 }
00475 return EINVAL;
00476 }
00477
00478 int RegistryFs::renameFile(const char *filename, const char *newname)
00479 {
00480 return EXDEV;
00481 }
00482
00483 int RegistryFs::fileClose(ht_streamfile *f)
00484 {
00485 f->done();
00486 int e=f->get_error();
00487 delete f;
00488 return e;
00489 }
00490
00491 int RegistryFs::fileOpen(const char *filename, UINT access_mode, UINT open_mode, ht_streamfile **f)
00492 {
00493 RegNodeFile *file=new RegNodeFile();
00494 file->init(filename, access_mode, open_mode);
00495 int e=file->get_error();
00496 if (e) {
00497 file->done();
00498 delete file;
00499 return e;
00500 }
00501 *f=file;
00502 return 0;
00503 }
00504