X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5..c61d41422afe49ea1c31bc14913452ef3b571c21:/lib/base/nconfig.cpp diff --git a/lib/base/nconfig.cpp b/lib/base/nconfig.cpp index a0e4a313..562b3503 100644 --- a/lib/base/nconfig.cpp +++ b/lib/base/nconfig.cpp @@ -1,1027 +1,34 @@ -// this is nconfig 0.92, a bit modified -#define NO_MAP_SHARED -#include -#include -#include #include +#include -#include -#include -#include -#include -#include -#include +PyObject *ePythonConfigQuery::m_queryFunc; -#include - -#include - -#ifndef PAGESIZE -#ifdef PAGE_SIZE -#define PAGESIZE PAGE_SIZE -#else -#define PAGESIZE 4096 -#endif -#endif - -#define SB ((struct nc_sb_s *) data) -#define CM(x) ((struct nc_chunk_s *) (data+(x))) -#define DE(x) ((struct nc_de_s *) (data+(x))) -#define IDE(x, y) (DE(((unsigned *) (data+(x)->offset))[(y)])) -#define CS(x) (((unsigned *) (data+(x)))[-1]) - -inline unsigned NConfig::crc(const char *d, unsigned len) -{ - unsigned ret = 0; - unsigned l = len / sizeof(unsigned); - - while (l) { - ret += *(const unsigned *)d; - ret = (ret << 3) & (ret >> 29); - l--; - d += sizeof(unsigned); - } - return ret; -} - -NConfig::NConfig(int protect) -{ - fd = -1; - cname = fname = data = NULL; - sb = NULL; - cdir = NULL; - chunks = NULL; - revision = update = lsize = omode = 0; - olck = 0; - lock = NC_L_NONE; - careful = protect; -} - -NConfig::~NConfig() -{ - close(); - free(fname); -} - -void NConfig::close() -{ - free(cname); - cname = NULL; - if (fd > -1) { -#ifdef NO_MAP_SHARED - if (data) { - int size=sb->size; - char *buffer=new char[size]; - memcpy(buffer, data, size); - munmap(data, size); - data = NULL; - ::lseek(fd, 0, SEEK_SET); - ::write(fd, buffer, size); - delete[] buffer; - } -#endif - ::close(fd); - fd = -1; - } - if (data) { - munmap(data, sb->size); - data = NULL; - } -} - -void NConfig::flush() -{ - close(); - open(omode); -} - -int NConfig::setName(const char *name) -{ - if (!name) - return NC_ERR_NVAL; - if (fd > -1) - return NC_ERR_PERM; - free(fname); - fname = strdup(name); - return NC_ERR_OK; -} - -int NConfig::createNew(unsigned resize, unsigned dirent, unsigned mchunks) -{ - if (fd > -1) - return NC_ERR_NVAL; - if (!access(fname, F_OK)) - return NC_ERR_PERM; - - int ff; - if ((ff = ::open(fname, O_WRONLY | O_CREAT, 0600)) == -1) - return NC_ERR_NFILE; - struct nc_sb_s bsb = {NC_SB_MAGIC, resize*PAGESIZE, - dirent, mchunks, resize, mchunks, - sizeof(struct nc_sb_s)+sizeof(struct nc_de_s)+2*sizeof(unsigned), - sizeof(struct nc_sb_s), 0}; - struct nc_de_s bde = {sizeof(struct nc_sb_s)+sizeof(struct nc_de_s), - NC_DIR, sizeof(struct nc_sb_s), 0, 0, 0}; - struct nc_chunk_s bcm; - - write(ff, &bsb, sizeof(bsb)); - write(ff, &bde, sizeof(bde)); - write(ff, "/", 2); - - lseek(ff, sizeof(unsigned)-2, SEEK_CUR); - unsigned cl = sizeof(nc_chunk_s)*mchunks+sizeof(unsigned); - write(ff, &cl, sizeof(unsigned)); - - bcm.offset = bsb.chunk + sizeof(struct nc_chunk_s)*mchunks; - bcm.size = bsb.size - bcm.offset; - - write(ff, &bcm, sizeof(bcm)); - - lseek(ff, bsb.size-1, SEEK_SET); - write(ff, "", 1); - ::close(ff); - return NC_ERR_OK; -} - - -int NConfig::open(int how) -{ - if (!fname) - return NC_ERR_NFILE; - if (how != NC_O_RO && how != NC_O_RW) - return NC_ERR_TYPE; - if (fd > -1) - close(); - - int ff; - if ((ff = ::open(fname, how)) == -1) - return NC_ERR_PERM; - - struct stat sbuf; - fstat(ff, &sbuf); - - if (!sbuf.st_size) - return NC_ERR_CORRUPT; - -#ifdef NO_MAP_SHARED - if ((data = (char *) mmap(NULL, sbuf.st_size, how == NC_O_RO ? PROT_READ : (PROT_READ|PROT_WRITE), MAP_PRIVATE, ff, 0)) == MAP_FAILED) { -#else - if ((data = (char *) mmap(NULL, sbuf.st_size, how == NC_O_RO ? PROT_READ : (PROT_READ|PROT_WRITE), MAP_SHARED, ff, 0)) == MAP_FAILED) { -#endif - ::close(ff); - return NC_ERR_NMEM; - } - if (memcmp(((struct nc_sb_s *) data)->magic, NC_SB_MAGIC, 4)) { - munmap(data, sbuf.st_size); - ::close(ff); - return NC_ERR_CORRUPT; - } - fd = ff; - omode = how; - sb = SB; - lsize = 0; - cname = strdup("/"); - - lockFile(NC_L_RO, TRUE); - rdir = DE(sb->root); - unLockFile(); - return NC_ERR_OK; -} - -void NConfig::expand(unsigned toadd) -{ - unsigned nsize = sb->size + toadd; - lseek(fd, nsize-1, SEEK_SET); - write(fd, "", 1); - _remap(sb->size, nsize); - sb->size = nsize; - cdir = getDirEnt(cname); - chunks = CM(sb->chunk); -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Expanded from %u to %u\n", nsize-toadd, nsize); -#endif -} - -unsigned NConfig::getChunk(unsigned s) -{ - int lst = -1; - - // Make sure we get aligned data - s = alignSize(s) + sizeof(unsigned); - -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Taking %u (total %u)\n", s, sb->chunk_ttl); -#endif - - do { - int left = 0, right = sb->chunk_ttl - 1, c; - while (left <= right) { - int diff = chunks[c = (left + right) / 2].size - s; - if (diff < 0 || diff == sizeof(unsigned)) { -#ifdef NC_DEBUG_ALLOC - if (diff > 0) - fprintf(stderr, "Rejected chunk %d (%u:%u)\n", c, chunks[c].offset, chunks[c].size); -#endif - right = c - 1; - continue; - } - lst = c; - if (!diff) - break; - left = c + 1; - } - if (lst < 0) { - unsigned ll = (s / (sb->size_inc*PAGESIZE) + 1) * PAGESIZE * sb->size_inc; - // we don't have a suitable chunk - expand(ll); - // insert new chunk into list (always succeeds) - *(unsigned *)(data+sb->size-ll) = ll; - fast_free(sb->size-ll+sizeof(unsigned)); - } - } while (lst < 0); - -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "haluz 7: off = %u size = %u\n", chunks[7].offset, chunks[7].size); - fprintf(stderr, "Got %u chunk (pos %d), taking %u\n", chunks[lst].size, lst, s); - fprintf(stderr, "chunk (%u:%u)\n", chunks[lst].offset, chunks[lst].size); -#endif - - unsigned best = chunks[lst].offset+sizeof(unsigned); - memset(data+best, 0, s-sizeof(unsigned)); - chunks[lst].size -= s; - chunks[lst].offset += s; - CS(best) = s; - - while (lst < ((signed)sb->chunk_ttl - 1) && chunks[lst].size < chunks[lst+1].size) { - unsigned b = chunks[lst].size; - unsigned i = lst + 1; - chunks[lst].size = chunks[i].size; - chunks[i].size = b; - b = chunks[lst].offset; - chunks[lst].offset = chunks[i].offset; - chunks[i].offset = b; - lst = i; - } - -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Returned %u:%u\n", best, CS(best)); -#endif - return best; -} - -void NConfig::freeChunk(unsigned where) -{ -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Free chunk: %u\n", CS(where)); -#endif - if (chunks[sb->chunk_ttl-2].size) { -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Last slot available.\n"); -#endif - unsigned n = getChunk((sb->chunk_ttl+sb->chunk_inc)*sizeof(struct nc_chunk_s)); - unsigned f = sb->chunk; - memcpy(data+n, chunks, (sb->chunk_ttl-1)*sizeof(struct nc_chunk_s)); - chunks = CM(sb->chunk = n); - sb->chunk_ttl += sb->chunk_inc; - fast_free(f); - } - fast_free(where); -} - -inline unsigned NConfig::alignSize(unsigned s) -{ - unsigned of = s % sizeof(unsigned); - return of ? s + sizeof(unsigned) - of : s; -} - -void NConfig::delKey(const char *name) -{ - _delKey(name, NULL, TRUE); -} - -void NConfig::_delKey(const char *name, struct nc_de_s *p, int tosort) -{ - if (fd < 0) - return; - lockFile(NC_L_RW); - struct nc_de_s *nd = getDirEnt(name, p); - if (nd && nd != rdir && nd != cdir) { - unsigned ndo = ((char *)nd) - data; - if (nd->type == NC_DIR) - for (unsigned i=0; ipages; i++) { - struct nc_de_s *dd = IDE(nd, i); - if (dd->type) - _delKey(data+dd->name, nd, FALSE); - nd = DE(ndo); - } - sb->modtime++; - freeChunk(nd->offset); - freeChunk(DE(ndo)->name); - nd = DE(ndo); - struct nc_de_s *parent = DE(nd->parent); - memset(nd, 0, sizeof(struct nc_de_s)); - // keep parent directory sorted - if (tosort) { - unsigned i = 0; - while (i < parent->pages && IDE(parent, i) != nd) - i++; - memmove(((unsigned *)(data+parent->offset))+i, - ((unsigned *)(data+parent->offset))+i+1, - sizeof(unsigned)*(parent->pages-i-1)); - ((unsigned *)(data+parent->offset))[parent->pages-1] = ndo; - } - } - unLockFile(); -} - -int NConfig::_setKey(const char *name, const unsigned t, const char *value, const unsigned len) -{ - if (fd < 0) - return NC_ERR_NFILE; - if (omode != NC_O_RW) - return NC_ERR_RDONLY; - lockFile(NC_L_RW); - struct nc_de_s *nd = getDirEnt(name); -#ifdef NC_DEBUG_INSERT - fprintf(stderr, "Found DE %p\n", nd); -#endif - if (!nd) { - struct nc_de_s *sd = *name == '/' ? rdir : cdir; - char *parse = canonize(name), *p = parse; - - while ((nd = getDirEnt(p, sd))) - if (nd->type == NC_DIR) { - sd = nd; - p += strlen(p)+1; - } else { - free(parse); - unLockFile(); - return NC_ERR_PERM; - } - - size_t pl = 0; - struct nc_de_s ds; - unsigned sdo = ((char *)sd) - data; - while (*(p+(pl = strlen(p)+1))) { - ds.pages = ds.offset = 0; - ds.name = getChunk(pl); - memcpy(data+ds.name, p, pl); - ds.type = NC_DIR; -#ifdef NC_DEBUG_INSERT - fprintf(stderr, "Insertion parent 2: %p\n", DE(sdo)); -#endif - // FIXME: crc calculation - sdo = ((char *)insert(sdo, &ds)) - data; - p += pl; - } - ds.type = t; - memcpy(data+(ds.name = getChunk(pl)), p, pl); - ds.pages = ds.offset = 0; -#ifdef NC_DEBUG_INSERT - fprintf(stderr, "Insertion parent 1: %p\n", DE(sdo)); -#endif - nd = insert(sdo, &ds); - sb->modtime++; - free(parse); - } else - if (nd->type != t) { - unLockFile(); - return NC_ERR_TYPE; - } - unsigned ndo = ((char *)nd) - data; - if (t != NC_DIR) { - if (value) { - if (nd->offset && CS(nd->offset)-sizeof(unsigned) < len) { - freeChunk(nd->offset); - nd = DE(ndo); - nd->offset = 0; - } - if (nd->offset) { - if (CS(nd->offset)-sizeof(unsigned) > alignSize(len)+sizeof(unsigned)) { - unsigned trim = CS(nd->offset) - alignSize(len) - sizeof(unsigned); - unsigned off = nd->offset + alignSize(len) + sizeof(unsigned); - CS(off) = trim; - CS(nd->offset) -= trim; - freeChunk(off); - nd = DE(ndo); - } - } else { - unsigned off = getChunk(len); - nd = DE(ndo); - nd->offset = off; - } - memcpy(data+nd->offset, value, len); - nd->pages = len; - } else - if (nd->offset) { - freeChunk(nd->offset); - DE(ndo)->offset = 0; - } - } else - // Preallocate pages for directory - if (len > nd->pages) { - unsigned off = getChunk(sizeof(unsigned)*len); - if (DE(ndo)->offset) { - memcpy(data+off, data+DE(ndo)->offset, sizeof(unsigned)*(DE(ndo)->pages)); - freeChunk(DE(ndo)->offset); - } - DE(ndo)->offset = off; - for (unsigned al = len - DE(ndo)->pages; al; al--) { - off = getChunk(sizeof(struct nc_de_s)); - ((unsigned *)(data+DE(ndo)->offset))[DE(ndo)->pages++] = off; - } - } - unLockFile(); -#ifdef NC_DEBUG_INSERT - fprintf(stderr, "%p\n", cdir); -#endif - return NC_ERR_OK; -} - -char *NConfig::getName(const struct nc_de_s *w) -{ - if (w == rdir) - return strdup("/"); - char *parent = getName(DE(w->parent)); - unsigned l1 = strlen(parent); - unsigned l2 = strlen(data+w->name)+1; - - parent = (char *) realloc(parent, l1 + l2 + (l1 == 1 ? 0 : 1)); - if (l1 != 1) { - memcpy(parent+l1, "/", 2); - l1++; - } - memcpy(parent+l1, data+w->name, l2); - return parent; -} - -int NConfig::chDir(const char *name) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - - int ret = NC_ERR_OK; - struct nc_de_s *nd = getDirEnt(name); - if (nd) { - if (nd->type == NC_DIR) { - cdir = nd; - free(cname); - cname = getName(cdir); - } else - ret = NC_ERR_NDIR; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -const char *NConfig::pwDir() -{ - if (fd < 0) - return NULL; - lockFile(NC_L_RO); - struct nc_de_s *l = cdir; - char * ret = strdup(data+l->name); - while (DE(l->parent) != l) { - unsigned len = CS(l->name); - char *r = (char *) malloc(strlen(ret) + len + 2); - memcpy(r, data+l->name, len); - if (*ret != '/' && DE(l->parent) != rdir) - strcat(r, "/"); - strcat(r, ret); - free(ret); - ret = r; - l = DE(l->parent); - } - unLockFile(); - return ret; -} - -struct nc_de_s *NConfig::getDirEnt(const char *name, struct nc_de_s *cc) -{ - struct nc_de_s *ret = cc ? cc : ((*name == '/') ? rdir : cdir); - char *c = canonize(name), *can; - - if (!(can = c)) - return ret; - while (*c) { - if (!strcmp(c, "..")) - ret = DE(ret->parent); - else - if (strcmp(c, ".")) { - struct nc_de_s *re = ret; - int left = 0, right = ret->pages-1, p, r; - - ret = NULL; - while (left <= right) { - p = (left + right) / 2; - r = strcmp(c, data+IDE(re, p)->name); - if (r < 0) { - left = p + 1; - continue; - } - if (!r) { - ret = IDE(re, p); - break; - } - right = p - 1; - } - } - c += strlen(c)+1; - if (!ret || (*c && ret->type != NC_DIR)) { - ret = NULL; - break; - } - } - free(can); - return ret; -} - -char *NConfig::canonize(const char *name) -{ - if (*name == '/') - name++; - size_t i = strlen(name); - char *ret = (char *)calloc(1, i+3); - memcpy(ret, name, i); - for (size_t j=0; jname, what->type); -#endif - struct nc_de_s *w = DE(where); - if (!DE(where)->offset || IDE(w, w->pages-1)->type) { - unsigned a = getChunk((w->pages+sb->ent_inc)*sizeof(unsigned)); - w = DE(where); - if (w->offset) { - memcpy(data+a, data+w->offset, w->pages*sizeof(unsigned)); - freeChunk(w->offset); - w = DE(where); - } - w->offset = a; - for (unsigned ha = 0; haent_inc; ha++) { - unsigned off = getChunk(sizeof(struct nc_de_s)); - w = DE(where); - ((unsigned *)(data+w->offset))[w->pages] = off; - w->pages++; - } - } - int i = 0, l = 0, r = w->pages - 1, c; - while (l <= r) { - c = (l + r) / 2; - if (!IDE(w, c)->type || strcmp(data+what->name, data+IDE(w, c)->name) > 0) { - i = c; - r = c - 1; - } else - l = c + 1; - } - -#ifdef NC_DEBUG_INSERT - fprintf(stderr, "Insertion to slot %u (%s)\n", i, data+what->name); -#endif - what->parent = where; - unsigned to = ((unsigned *)(data+w->offset))[w->pages-1]; - memmove(((unsigned *)(data+w->offset))+i+1, ((unsigned *)(data+w->offset))+i, sizeof(unsigned)*(w->pages-i-1)); - ((unsigned *)(data+w->offset))[i] = to; - void *ret = memcpy(DE(to), what, sizeof(struct nc_de_s)); - sb->modtime++; - return (struct nc_de_s *)ret; -} - -void NConfig::status() -{ - if (fd < 0) - return; - lockFile(NC_L_RO); - fprintf(stderr, "Size:\t%u\n", sb->size); - unsigned low=0, hi=chunks[0].size, cnt=0, ttl=0; - for (unsigned i=0; ichunk_ttl; i++) - if (chunks[i].size > 0) { - if (!low || low > chunks[i].size) - low = chunks[i].size; - ttl += chunks[i].size; - cnt++; - } - unLockFile(); - fprintf(stderr, "Free:\t%u in %u chunk%s\n", ttl, cnt, cnt > 1 ? "s" : ""); - if (cnt > 0) - fprintf(stderr, "Min:\t%u\nAvg:\t%u\nMax:\t%u\n", low, ttl / cnt, hi); -} - -struct nc_ls_s *NConfig::ls(const char *name) -{ - if (fd < 0) - return NULL; - lockFile(NC_L_RO); - - struct nc_ls_s *rt = NULL; - unsigned count = 0; - struct nc_de_s *de = NULL; - struct nc_de_s *ds = name ? getDirEnt(name) : cdir; - - if (ds && ds->type == NC_DIR) { - for (unsigned i=0; ipages; i++) { - de = IDE(ds, i); - if (de->type && de->name) { - rt = (struct nc_ls_s *) realloc(rt, (count+2)*sizeof(nc_ls_s)); - rt[count].type = de->type; - rt[count].name = strdup(data+de->name); - rt[++count].type = 0; - rt[count].name = NULL; - } - } - } - unLockFile(); - return rt; -} - -void NConfig::fast_free(unsigned offset) -{ - unsigned s = CS(offset), i = 0; - offset -= sizeof(unsigned); - - while (1) { - if (!chunks[i].size) { -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Inserting %u:%u to %u\n", offset, s, i); -#endif - chunks[i].offset = offset; - chunks[i].size = s; - break; - } - if (chunks[i].offset == offset + s) { -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Prepending %u:%u to %u (%u:%u)\n", offset, s, i, chunks[i].offset, chunks[i].size); -#endif - chunks[i].offset -= s; - chunks[i].size += s; - break; - } - if (offset == chunks[i].offset + chunks[i].size) { -#ifdef NC_DEBUG_ALLOC - fprintf(stderr, "Appending %u:%u to %u (%u:%u)\n", offset, s, i, chunks[i].offset, chunks[i].size); -#endif - chunks[i].size += s; - break; - } - i++; - } - - // Keep the array sorted - while (i && chunks[i].size > chunks[i-1].size) { - unsigned b = chunks[i].size; - unsigned j = i - 1; - chunks[i].size = chunks[j].size; - chunks[j].size = b; - b = chunks[i].offset; - chunks[i].offset = chunks[j].offset; - chunks[j].offset = b; - i = j; - } -} - -int NConfig::renameKey(const char *oldname, const char *newname) -{ - if (fd < 0) - return NC_ERR_NFILE; - if (omode != NC_O_RW) - return NC_ERR_RDONLY; - lockFile(NC_L_RW); - int ret = NC_ERR_OK; - struct nc_de_s *parent, *nd = getDirEnt(newname); - if (nd) { - if ((nd = getDirEnt(oldname))) { - size_t len = strlen(newname)+1; - int inc = strcmp(oldname, newname); - unsigned i, off, pos, ndo = ((char *)nd) - data; - if (alignSize(len) != CS(nd->name)) { - freeChunk(nd->name); - off = getChunk(len); - DE(ndo)->name = off; - nd = DE(ndo); - } - memcpy(data+nd->name, newname, len); - parent = DE(nd->parent); - for (pos = 0; pos < parent->pages && IDE(parent, pos) != nd; pos++) - ; - for (i = pos; i>=0 && ipages; i += inc) - if (strcmp(data+IDE(parent, i)->name, newname) != inc) - break; - if (inc == -1) - memmove(((unsigned *)(data+parent->offset))+i+1, - ((unsigned *)(data+parent->offset))+i, - sizeof(unsigned)*(pos - i)); - else - memmove(((unsigned *)(data+parent->offset))+pos, - ((unsigned *)(data+parent->offset))+pos+1, - sizeof(unsigned)*(i-pos)); - ((unsigned *)(data+parent->offset))[i] = ndo; - sb->modtime++; - } else - ret = NC_ERR_NEXIST; - } else - ret = NC_ERR_PERM; - unLockFile(); - return NC_ERR_OK; -} - -int NConfig::createDir(const char *name, unsigned entries) -{ - return _setKey(name, NC_DIR, NULL, entries); -} - -int NConfig::setKey(const char *name, const unsigned long long value) -{ - return _setKey(name, NC_UINT, (const char *)&value, sizeof(value)); -} - -int NConfig::setKey(const char *name, const unsigned value) -{ - unsigned long long b = value; - return _setKey(name, NC_UINT, (const char *)&b, sizeof(b)); -} - -int NConfig::setKey(const char *name, const signed long long value) -{ - return _setKey(name, NC_INT, (const char *)&value, sizeof(value)); -} - -int NConfig::setKey(const char *name, const int value) -{ - signed long long b = value; - return _setKey(name, NC_INT, (const char *)&b, sizeof(b)); -} - -int NConfig::setKey(const char *name, const char *value) -{ - return _setKey(name, NC_STRING, value, strlen(value)+1); -} - -int NConfig::setKey(const char *name, const long double value) +void ePythonConfigQuery::setQueryFunc(PyObject *queryFunc) { - return _setKey(name, NC_DOUBLE, (const char *)&value, sizeof(value)); + if (m_queryFunc) + Py_DECREF(m_queryFunc); + m_queryFunc = queryFunc; + if (m_queryFunc) + Py_INCREF(m_queryFunc); } -int NConfig::setKey(const char *name, const double value) +RESULT ePythonConfigQuery::getConfigValue(const char *key, std::string &value) { - long double b = value; - return _setKey(name, NC_DOUBLE, (const char *)&b, sizeof(b)); -} - -int NConfig::setKey(const char *name, const char *value, const unsigned len) -{ - if (!value && len) - return NC_ERR_NVAL; - if (!len) - return _setKey(name, NC_RAW, NULL, 0); - return _setKey(name, NC_RAW, value, len); -} - -int NConfig::getKey(const char *name, unsigned long long &value) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_UINT) { - memcpy(&value, data+k->offset, sizeof(value)); - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -int NConfig::getKey(const char *name, unsigned &value) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_UINT) { - unsigned long long b; - memcpy(&b, data+k->offset, sizeof(b)); - value = b; - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -int NConfig::getKey(const char *name, long double &value) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_DOUBLE) { - memcpy(&value, data+k->offset, sizeof(value)); - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -int NConfig::getKey(const char *name, double &value) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_DOUBLE) { - long double b; - memcpy(&b, data+k->offset, sizeof(b)); - value = b; - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -int NConfig::getKey(const char *name, signed long long &value) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_INT) { - memcpy(&value, data+k->offset, sizeof(value)); - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -int NConfig::getKey(const char *name, int &value) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_INT) { - signed long long b; - memcpy(&b, data+k->offset, sizeof(b)); - value = b; - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -int NConfig::getKey(const char *name, char *&value) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_STRING) { - if (k->offset) { - if (!(value = strdup(data+k->offset))) - ret = NC_ERR_NMEM; - } else - value = NULL; - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -int NConfig::getKey(const char *name, char *&value, unsigned &len) -{ - if (fd < 0) - return NC_ERR_NFILE; - lockFile(NC_L_RO); - int ret = NC_ERR_OK; - struct nc_de_s *k = getDirEnt(name); - if (k) { - if (k->type == NC_RAW) { - if (k->offset) { - len = k->pages; - value = (char *)malloc(len); - memcpy(value, data+k->offset, len); - } else { - len = 0; - value = NULL; + if (key && PyCallable_Check(m_queryFunc)) + { + PyObject *pArgs = PyTuple_New(1); + PyTuple_SET_ITEM(pArgs, 0, PyString_FromString(key)); + PyObject *pRet = PyObject_CallObject(m_queryFunc, pArgs); + Py_DECREF(pArgs); + if (pRet) + { + if (PyString_Check(pRet)) + { + value.assign(PyString_AS_STRING(pRet)); + return 0; } - } else - ret = NC_ERR_TYPE; - } else - ret = NC_ERR_NEXIST; - unLockFile(); - return ret; -} - -void NConfig::lockFile(int type, int force) -{ -#ifdef NC_DEBUG_LOCK - fprintf(stderr, "Lock called type=%d force=%d lock=%d olck=%u\n", type, force, lock, olck); -#endif - if (lock == NC_L_RO && type == NC_L_RW) { - fprintf(stderr, "Lock promotion is not possible.\n"); - abort(); - } - if (lock != NC_L_NONE) { - olck++; - return; - } - - struct flock flc = { type == NC_L_RW ? F_WRLCK : F_RDLCK, SEEK_SET, 0, 0, 0 }; - while (fcntl(fd, F_SETLKW, &flc)) { - sched_yield(); - flc.l_type = type == NC_L_RW ? F_WRLCK : F_RDLCK; - flc.l_whence = SEEK_SET; - flc.l_len = flc.l_start = 0; - } - -#ifdef NC_DEBUG_LOCK - fprintf(stderr, "Locked %u %u %s\n", sb->modtime, update, force ? "forced." : ""); -#endif - if (careful && type == NC_L_RW) - mprotect(data, sb->size, PROT_READ | PROT_WRITE); - lock = type; - olck = 0; - if (sb->modtime != update || force) { - // refresh memory mapping - if (lsize != sb->size) { - _remap(lsize, sb->size); - lsize = sb->size; - chunks = CM(sb->chunk); + Py_DECREF(pRet); } - cdir = getDirEnt(cname); - update = sb->modtime; } + return -1; } - -void NConfig::unLockFile() -{ -#ifdef NC_DEBUG_LOCK - fprintf(stderr, "UnLock called lock=%u olck=%u\n", lock, olck); -#endif - if (olck) { - olck--; - return; - } - if (lock == NC_L_NONE) - return; - struct flock flc = {F_UNLCK, SEEK_SET, 0, 0, 0 }; - update = sb->modtime; -#ifdef NC_DEBUG_LOCK - fprintf(stderr, "Unlock %u\n", update); -#endif - if (careful) - mprotect(data, sb->size, PROT_READ); - fcntl(fd, F_SETLK, &flc); - lock = NC_L_NONE; - olck = 0; -} - -void NConfig::_remap(const size_t osize, const size_t nsize) -{ - data = (char *) mremap(data, osize, nsize, 1); - if (data == MAP_FAILED) { - perror("mremap"); - abort(); - } - sb = SB; - rdir = DE(sb->root); -} - -char * NConfig::version() -{ - return strdup("EliteDVB registry"); -} -