Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

vfs.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      vfs.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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  *      class LocalFs
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         /* FIXME: backslash & slash */
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         // FIXME
00075         return ENOSYS;
00076 }
00077 
00078 int LocalFs::deleteFile(const char *filename)
00079 {
00080         /* filename must be absolute */
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 //      return mkdir(dirname, S_IWUSR);
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  *      class RegNodeFile
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  *      class RegistryFs
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);           /* FIXME: possible buffer overflow !!! only 32 bytes... */
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 

Generated on Fri May 7 21:15:45 2004 by doxygen 1.3.5