⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xdb_file.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL").  You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/.   * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights *  * Portions created by or assigned to Jabber.com, Inc. are  * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. *  * Acknowledgements *  * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. *  * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above.  If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL.  If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL.  *  *  * --------------------------------------------------------------------------*/ #include <jabberd.h>#include <dirent.h>#define FILES_PRIME 509/* gcc -fPIC -shared -o xdb_file.so xdb_file.c -I../srcneeds to have a spool section in the config:<load><xdb_file>../load/xdb_file.so</xdb_file></load><xdb_file xmlns="jabber:config:xdb_file">  <spool>/var/spool/jabber</spool></xdb_file>within the spool, xdb_file will make folders for hostnames it has to save data for, and within those save username.xml files containing a user's namespaces*/typedef struct cacher_struct{    char *fname;    xmlnode file;    int lastset;} *cacher, _cacher;typedef struct xdbf_struct{    char *spool;    instance i;    int timeout;    xht cache;    int sizelimit;    int use_hashspool;} *xdbf, _xdbf;void _xdb_file_purge(xht h, const char *key, void *data, void *arg){    xdbf xf = (xdbf)arg;    cacher c = (cacher)data;    int now = time(NULL);    if((now - c->lastset) > xf->timeout)    {        log_debug2(ZONE, LOGT_STORAGE, "purging %s",c->fname);        xhash_zap(xf->cache,c->fname);        xmlnode_free(c->file);    }}/* walk the table looking for stale files to expire */result xdb_file_purge(void *arg){    xdbf xf = (xdbf)arg;    log_debug2(ZONE, LOGT_STORAGE, "purge check");    xhash_walk(xf->cache,_xdb_file_purge,(void *)xf);    return r_DONE;}/* this function acts as a loader, getting xml data from a file */xmlnode xdb_file_load(char *host, char *fname, xht cache){    xmlnode data = NULL;    cacher c;    int fd;    log_debug2(ZONE, LOGT_STORAGE, "loading %s",fname);    /* first, check the cache */    if((c = xhash_get(cache,fname)) != NULL)        return c->file;    /* test the file first, so we can be more descriptive */    fd = open(fname,O_RDONLY);    if(fd < 0) {	if (errno == ENOENT) {	    log_debug2(ZONE, LOGT_STORAGE, "xdb_file failed to open file %s: %s", fname, strerror(errno));	} else {	    log_warn(host,"xdb_file failed to open file %s: %s",fname,strerror(errno));	}    } else {        close(fd);        data = xmlnode_file(fname);    }    /* if there's nothing on disk, create an empty root node */    if(data == NULL)        data = xmlnode_new_tag("xdb");    log_debug2(ZONE, LOGT_STORAGE, "caching %s",fname);    c = pmalloco(xmlnode_pool(data),sizeof(_cacher));    c->fname = pstrdup(xmlnode_pool(data),fname);    c->lastset = time(NULL);    c->file = data;    xhash_put(cache,c->fname,c);    return data;}/** * calculate the left-most four digits of the SHA-1 hash over a filename * * @param filename the filename * @param digit01 where to place the first two digits (size 3 chars!) * @param digit23 where to place the next two digits (size 3 chars!) */void _xdb_get_hashes(const char *filename, char digit01[3], char digit23[3]){    char hashedfilename[9];        /* generate a hash over the filename */    bzero(hashedfilename, sizeof(hashedfilename));    bzero(digit01, sizeof(digit01));    bzero(digit23, sizeof(digit23));    crc32_r(filename, hashedfilename);    log_debug2(ZONE, LOGT_STORAGE, "hash of %s is %s", filename, hashedfilename);    memcpy(digit01, hashedfilename+1, 2);    memcpy(digit23, hashedfilename+4, 2);    return;}/** * create folders in the spool * * @param spoolroot the root of the spool * @param host the host for which the directory should be created * @param hash1 the hash for the first subdirectory * @param hash2 the second subdirectory * @param use_subdirs true if file should be located in subdirectories * @return 1 on success, 0 on failure */int _xdb_gen_dirs(spool sp, const char *spoolroot, char *host, const char *hash1, const char *hash2, int use_subdirs){    struct stat s;    char *tmp;    /* check that the root of the spool structure exists */    if (stat(spoolroot, &s) < 0)    {	log_error(host, "the spool root directory %s does not seem to exist", spoolroot);	return 0;    }    /* check and create the host-named folder */    spooler(sp, spoolroot, "/", host, sp);    tmp = spool_print(sp);    if(stat(tmp,&s) < 0 && mkdir(tmp, S_IRWXU) < 0)    {	log_error(host, "could not create spool folder %s: %s", tmp, strerror(errno));	return 0;    }    if (use_subdirs)    {	/* check or create the first level subdirectory */	spooler(sp, "/", hash1, sp);	tmp = spool_print(sp);	if(stat(tmp,&s) < 0 && mkdir(tmp, S_IRWXU) < 0)	{	    log_error(host, "could not create spool folder %s: %s", tmp, strerror(errno));	    return 0;	}	/* check or create the second level subdirectory */	spooler(sp, "/", hash2, sp);	tmp = spool_print(sp);	if(stat(tmp,&s) < 0 && mkdir(tmp, S_IRWXU) < 0)	{	    log_error(host, "could not create spool folder %s: %s", tmp, strerror(errno));	    return 0;	}    }    return 1;}/** * utility that generates the filename for a spool file * * @param create true if the directory for the file should be generated * @param p pool that should be used for string operations * @param spl location for the spool root * @param host host of the xdb request (the 'spool folder') * @param file the basename of the xdb file * @param ext the extension for the xdb file * @param use_subdirs true if file should be located in subdirectories * @return concatenated string of the form spl+"/"+somehashes+"/"+file+"."+ext */char *xdb_file_full(int create, pool p, char *spl, char *host, char *file, char *ext, int use_subdirs){    spool sp = spool_new(p);    char digit01[3], digit23[3];    char *ret;    char *filename;    filename = spools(p, file, ".", ext, p);    _xdb_get_hashes(filename, digit01, digit23);    /* is the creation of the folder requested? */    if(create)    {	if (!_xdb_gen_dirs(sp, spl, host, digit01, digit23, use_subdirs))	{	    log_error(host, "xdb request failed, necessary directory was not created");	    return NULL;	}    } else if (use_subdirs) {	spooler(sp, spl, "/", host, "/", digit01, "/", digit23, sp);    } else {	spooler(sp, spl, "/", host, sp);    }    /* full path to file */    spooler(sp,"/",filename, sp);    ret = spool_print(sp);    return ret;}/* the callback to handle xdb packets */result xdb_file_phandler(instance i, dpacket p, void *arg){    char *full, *ns, *act, *match;    xdbf xf = (xdbf)arg;    xmlnode file, top, data;    int ret = 0, flag_set = 0;    log_debug2(ZONE, LOGT_STORAGE|LOGT_DELIVER, "handling xdb request %s",xmlnode2str(p->x));    if((ns = xmlnode_get_attrib(p->x,"ns")) == NULL)        return r_ERR;    if(j_strcmp(xmlnode_get_attrib(p->x,"type"), "set") == 0)        flag_set = 1;    /* is this request specific to a user or global data? use that for the file name */    if(p->id->user != NULL)        full = xdb_file_full(flag_set, p->p, xf->spool, p->id->server, p->id->user, "xml", xf->use_hashspool);    else        full = xdb_file_full(flag_set, p->p, xf->spool, p->id->server, "global", "xdb", 0);    if(full == NULL)        return r_ERR;    /* load the data from disk/cache */    top = file = xdb_file_load(p->host, full, xf->cache);    /* if we're dealing w/ a resource, just get that element */    if(p->id->resource != NULL)    {        if((top = xmlnode_get_tag(top,spools(p->p,"res?id=",p->id->resource,p->p))) == NULL)        {            top = xmlnode_insert_tag(file,"res");            xmlnode_put_attrib(top,"id",p->id->resource);        }    }    /* just query the relevant namespace */    data = xmlnode_get_tag(top,spools(p->p,"?xdbns=",ns,p->p));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -