[asterisk-commits] qwell: branch group/ast_storage r79630 - in /team/group/ast_storage: include/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Aug 15 17:33:20 CDT 2007


Author: qwell
Date: Wed Aug 15 17:33:19 2007
New Revision: 79630

URL: http://svn.digium.com/view/asterisk?view=rev&rev=79630
Log:
Fix up API a bunch.
Fix odbc storage get function to return a file list.

"storage show file" CLI command actually works for file/odbc now.

Modified:
    team/group/ast_storage/include/asterisk/storage.h
    team/group/ast_storage/main/storage.c
    team/group/ast_storage/res/res_storage_file.c
    team/group/ast_storage/res/res_storage_odbc.c

Modified: team/group/ast_storage/include/asterisk/storage.h
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/include/asterisk/storage.h?view=diff&rev=79630&r1=79629&r2=79630
==============================================================================
--- team/group/ast_storage/include/asterisk/storage.h (original)
+++ team/group/ast_storage/include/asterisk/storage.h Wed Aug 15 17:33:19 2007
@@ -32,8 +32,7 @@
 #endif
 
 struct ast_storage_dirent {
-	char name[256];
-	char ext[10];
+	char name[PATH_MAX];
 	int fd;
 };
 
@@ -59,7 +58,6 @@
 
 struct ast_storage_be {
 	const char *name;
-	struct ast_storage_filelist *fl;
 	struct ast_storage *(*create)(const char *uri);
 	int (*free)(struct ast_storage *st);
 	int (*get)(struct ast_storage *st, const char *objectname, const char *exts, char *localfile, size_t localfilesize);
@@ -82,7 +80,10 @@
 
 /* Most specific backends will have longer structures */
 struct ast_storage {
-	struct ast_storage_be *be;
+	const struct ast_storage_be *be;
+	char path[PATH_MAX];
+	struct ast_storage_filelist *fl;
+	void **xst; /* Backend specific structure */
 };
 
 int __ast_register_storage(const struct ast_storage_be *e, struct ast_module *mod);

Modified: team/group/ast_storage/main/storage.c
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/main/storage.c?view=diff&rev=79630&r1=79629&r2=79630
==============================================================================
--- team/group/ast_storage/main/storage.c (original)
+++ team/group/ast_storage/main/storage.c Wed Aug 15 17:33:19 2007
@@ -47,9 +47,12 @@
 
 static struct ast_storage *se_create_null(const char *uri)
 {
+	struct ast_storage *st = ast_calloc(1, sizeof(struct ast_storage));
 	struct ast_storage_null *nst = ast_calloc(1, sizeof(struct ast_storage_null));
-	nst->be = &null_se;
-	return ((struct ast_storage *)nst);
+	st->xst = (void *)nst;
+	st->be = &null_se;
+	ast_copy_string(st->path, uri, sizeof(st->path));
+	return st;
 }
 
 static int se_free_null(struct ast_storage *st)
@@ -58,7 +61,7 @@
 	return 0;
 }
 
-int __ast_register_storage(const struct ast_storage_be *e, struct ast_module *mod)
+int __ast_register_storage(const struct ast_storage_be *be, struct ast_module *mod)
 {
 	struct ast_storage_be *tmp;
 
@@ -67,9 +70,9 @@
 		return -1;
 	}
 	AST_RWLIST_TRAVERSE(&storage_engines, tmp, list) {
-		if (!strcasecmp(e->name, tmp->name)) {
+		if (!strcasecmp(be->name, tmp->name)) {
 			AST_RWLIST_UNLOCK(&storage_engines);
-			ast_log(LOG_WARNING, "Tried to register storage engine '%s', already registered\n", e->name);
+			ast_log(LOG_WARNING, "Tried to register storage engine '%s', already registered\n", be->name);
 			return -1;
 		}
 	}
@@ -77,7 +80,7 @@
 		AST_RWLIST_UNLOCK(&storage_engines);
 		return -1;
 	}
-	*tmp = *e;
+	*tmp = *be;
 	tmp->module = mod;
 	
 	memset(&tmp->list, 0, sizeof(tmp->list));
@@ -85,7 +88,7 @@
 	AST_RWLIST_INSERT_TAIL(&storage_engines, tmp, list);
 	AST_RWLIST_UNLOCK(&storage_engines);
 	if (option_verbose > 1)
-		ast_verbose(VERBOSE_PREFIX_2 "Registered storage engine '%s'\n", e->name);
+		ast_verbose(VERBOSE_PREFIX_2 "Registered storage engine '%s'\n", be->name);
 
 	return 0;
 }
@@ -118,7 +121,7 @@
 	return res;
 }
 
-static int destroy_filelist(struct ast_storage_filelist *fl)
+static int empty_filelist(struct ast_storage_filelist *fl)
 {
 	struct ast_storage_fileinst *fi;
 
@@ -126,83 +129,97 @@
 		return 0;
 
 	AST_RWLIST_WRLOCK(&fl->files);
-	AST_RWLIST_TRAVERSE(&fl->files, fi, list) {
+	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&fl->files, fi, list) {
+		AST_RWLIST_REMOVE_CURRENT(&fl->files, list);
 		free(fi->ent);
 		free(fi);
 	}
+	AST_RWLIST_TRAVERSE_SAFE_END
 	AST_RWLIST_UNLOCK(&fl->files);
-	free(fl);
 	return 0;
 }
 
 struct ast_storage_be *ast_storage_getbyname(const char *name)
 {
-	struct ast_storage_be *e;
+	struct ast_storage_be *be;
 	if (AST_RWLIST_RDLOCK(&storage_engines)) {
 		ast_log(LOG_WARNING, "Unable to lock storage engine list\n");
 		return NULL;
 	}
 
-	AST_RWLIST_TRAVERSE(&storage_engines, e, list) {
-		if (!strcasecmp(name, e->name))
+	AST_RWLIST_TRAVERSE(&storage_engines, be, list) {
+		if (!strcasecmp(name, be->name))
 			break;
 	}
 	AST_RWLIST_UNLOCK(&storage_engines);
-	return e;
+	return be;
 }
 
 struct ast_storage *ast_storage_request(const char *storage_type, const char *uri)
 {
-	struct ast_storage_be *e;
-
-	AST_RWLIST_TRAVERSE(&storage_engines, e, list) {
-		if (!strcasecmp(e->name, storage_type))
-			return e->create(S_OR(uri, ""));
+	struct ast_storage_be *be;
+	struct ast_storage *st = NULL;
+
+	AST_RWLIST_TRAVERSE(&storage_engines, be, list) {
+		if (!strcasecmp(be->name, storage_type)) {
+			if ((st = be->create(S_OR(uri, ""))))
+				st->fl = ast_calloc(1, sizeof(*st->fl));
+			return st;
+		}
 	}
 	return NULL;
 }
 
 int ast_storage_release(struct ast_storage *st)
 {
-	destroy_filelist(st->be->fl);
-	return st && st->be->free ? st->be->free(st) : -1;
+	if (st) {
+		empty_filelist(st->fl);
+		free(st->fl);
+		return st->be->free ? st->be->free(st) : -1;
+	} else
+		return -1;
 }
 
 int ast_storage_get(struct ast_storage *st, const char *objectname, const char *exts, char *localfile, size_t localfilesize)
 {
-	return st->be->get ? st->be->get(st, objectname, exts, localfile, localfilesize) : -1;
+	if (st) {
+		/* Empty the file list first, just to be safe */
+		empty_filelist(st->fl);
+		return st->be->get ? st->be->get(st, objectname, exts, localfile, localfilesize) : -1;
+	} else
+		return -1;
 }
 
 #if 0
 int ast_storage_put(struct ast_storage *st, struct ast_storage_filelist *fl, const char *exts)
 {
-	return st->be->put ? st->be->put(st, fl, exts) : -1;
+	return st && st->be->put ? st->be->put(st, fl, exts) : -1;
 }
 #endif
 
 int ast_storage_open(struct ast_storage *st, struct ast_storage_fileinst *fi, int mode)
 {
-	return st->be->open ? st->be->open(st, fi, mode) : -1;
+	return st && st->be->open ? st->be->open(st, fi, mode) : -1;
 }
 
 int ast_storage_close(struct ast_storage *st, struct ast_storage_fileinst *fi)
 {
-	return st->be->close ? st->be->close(st, fi) : -1;
+	return st && st->be->close ? st->be->close(st, fi) : -1;
 }
 
 void *ast_storage_read(struct ast_storage *st, struct ast_storage_fileinst *fi, size_t chunksize)
 {
-	return st->be->read ? st->be->read(st, fi, chunksize) : NULL;
+	return st && st->be->read ? st->be->read(st, fi, chunksize) : NULL;
 }
 
 int ast_storage_write(struct ast_storage *st, struct ast_storage_fileinst *fi, void *data, size_t chunksize)
 {
-	return st->be->write ? st->be->write(st, fi, data, chunksize) : -1;
+	return st && st->be->write ? st->be->write(st, fi, data, chunksize) : -1;
 }
 
 int ast_storage_del(struct ast_storage *st, const char *exts)
 {
-	return st->be->del ? st->be->del(st, exts) : -1;
+	return st && st->be->del ? st->be->del(st, exts) : -1;
 }
 
 int ast_storage_copy(struct ast_storage *st, struct ast_storage_fileinst *from, struct ast_storage_fileinst *to)
@@ -251,7 +268,13 @@
 		return -1;
 
 	while (st->be->readdir(st, dirptr, &dirent) == 0) {
-		if (strcmp(dirent.ext, "txt") == 0)
+		char *ext;
+
+		/* Parse out the file extension */
+		if ((ext = strrchr(dirent.name, '.'))) {
+			ext++;
+		}
+		if (strcmp(ext, "txt") == 0)
 			count++;
 	}
 
@@ -261,46 +284,59 @@
 
 static int storage_show_file(int fd, int argc, char *argv[])
 {
-	struct ast_storage *e;
+	struct ast_storage *st;
 	struct ast_storage_fileinst *fi;
-	char tmp[256];
+	char tmp[PATH_MAX];
 	char *stringp = tmp;
 	char *sename;
+	char *fn;
 	int count_files = 0;
 	/* XXX We want to remove the need to pass in a char array like this now.. */
-	char blah[256];
+	char blah[PATH_MAX];
 	if (argc != 4)
 		return RESULT_SHOWUSAGE;
 
 	stringp = ast_strdupa(argv[3]);
-	sename = strsep(&stringp, ":");
+	if ((fn = strstr(stringp, "://"))) {
+		*fn = '\0';
+		fn += 3;
+	}
+	sename = stringp;
 
 	if (!(ast_storage_getbyname(sename))) {
 		ast_cli(fd, "No storage engine named '%s' found.\n", sename);
 		return RESULT_SUCCESS;
 	}
 
-	if (!(e = ast_storage_request(sename, stringp)))
+	if (!(st = ast_storage_request(sename, fn)))
 		ast_cli(fd, "Could not create storage engine named '%s'.\n", sename);
 	else {
 		ast_cli(fd, "File information\n");
 		/* We don't care about format/extension here, so just send NULL */
-		if (!(ast_storage_get(e, stringp, NULL, blah, sizeof(blah)))) {
-			AST_RWLIST_TRAVERSE(&e->be->fl->files, fi, list) {
+		if (!(ast_storage_get(st, st->path, NULL, blah, sizeof(blah)))) {
+			AST_RWLIST_TRAVERSE(&st->fl->files, fi, list) {
+				char *ext;
+
+				/* Parse out the file extension */
+				if ((ext = strrchr(fi->ent->name, '.'))) {
+					ext++;
+				}
+
 				count_files++;
-				ast_cli(fd, "Name  : '%s'\n", fi->ent->name);
-				ast_cli(fd, "Format: '%s'\n", ast_getformatname(ast_getformatbyextension(fi->ent->ext)));
+				ast_cli(fd, "Name  : %s\n", fi->ent->name);
+				ast_cli(fd, "Format: %s\n", ast_getformatname(ast_getformatbyextension(ext)));
 			}
 		}
 		ast_cli(fd, "\n");
 		ast_cli(fd, "Found %d matching file(s).\n", count_files);
 	}
+	ast_storage_release(st);
 	return RESULT_SUCCESS;
 }
 
 static int storage_show_engines(int fd, int argc, char *argv[])
 {
-	struct ast_storage_be *e;
+	struct ast_storage_be *be;
 	int count_se = 0;
 
 	if (argc != 3)
@@ -312,8 +348,8 @@
 		return RESULT_FAILURE;
 	}
 
-	AST_RWLIST_TRAVERSE(&storage_engines, e, list) {
-		ast_cli(fd, "%s\n", e->name);
+	AST_RWLIST_TRAVERSE(&storage_engines, be, list) {
+		ast_cli(fd, "%s\n", be->name);
 		count_se++;
 	}
 	AST_RWLIST_UNLOCK(&storage_engines);
@@ -323,25 +359,28 @@
 
 static int storage_show_engine(int fd, int argc, char *argv[])
 {
-	struct ast_storage_be *e;
+	struct ast_storage_be *be;
 
 	if (argc != 4)
 		return RESULT_SHOWUSAGE;
 
-	if ((e = ast_storage_getbyname(argv[3]))) {
-		ast_cli(fd, "Storage Engine: %s\n", e->name);
-		ast_cli(fd, "Can get       : %s\n", e->get ? "yes" : "no");
+	if ((be = ast_storage_getbyname(argv[3]))) {
+		ast_cli(fd, "Storage Engine: %s\n", be->name);
+		ast_cli(fd, "Can get       : %s\n", be->get ? "yes" : "no");
 #if 0
-		ast_cli(fd, "Can put       : %s\n", e->put ? "yes" : "no");
+		ast_cli(fd, "Can put       : %s\n", be->put ? "yes" : "no");
 #endif
-		ast_cli(fd, "Can del       : %s\n", e->del ? "yes" : "no");
-		ast_cli(fd, "Can opendir   : %s\n", e->opendir ? "yes" : "no");
-		ast_cli(fd, "Can readdir   : %s\n", e->readdir ? "yes" : "no");
-		ast_cli(fd, "Can closedir  : %s\n", e->closedir ? "yes" : "no");
-		if (e->status) {
+		ast_cli(fd, "Can del       : %s\n", be->del ? "yes" : "no");
+		ast_cli(fd, "Can opendir   : %s\n", be->opendir ? "yes" : "no");
+		ast_cli(fd, "Can readdir   : %s\n", be->readdir ? "yes" : "no");
+		ast_cli(fd, "Can closedir  : %s\n", be->closedir ? "yes" : "no");
+		if (be->status) {
 			ast_cli(fd, "\n");
 			ast_cli(fd, "Additional status\n");
-			e->status((struct ast_storage *)e, fd);
+			/* XXX Need to rethink this.
+			 * This requires a struct ast_storage *, and we can't cast to it from ast_storage_be
+			be->status((struct ast_storage *)be, fd);
+			 */
 		}
 	} else
 		ast_cli(fd, "No storage engine named '%s' found.\n", argv[3]);
@@ -350,15 +389,15 @@
 
 static char *complete_storage_show_engines(const char *line, const char *word, int pos, int state)
 {
-	struct ast_storage_be *e;
+	struct ast_storage_be *be;
 	char *ret = NULL;
 	int which = 0;
 	int wordlen = strlen(word);
 
 	AST_RWLIST_RDLOCK(&storage_engines);
-	AST_RWLIST_TRAVERSE(&storage_engines, e, list) {
-		if (!strncasecmp(word, e->name, wordlen) && ++which > state) {
-			ret = strdup(e->name);
+	AST_RWLIST_TRAVERSE(&storage_engines, be, list) {
+		if (!strncasecmp(word, be->name, wordlen) && ++which > state) {
+			ret = strdup(be->name);
 			break;
 		}
 	}
@@ -368,7 +407,7 @@
 }
 
 char storage_show_file_usage[] =
-"Usage: storage show file <engine:filename>\n"
+"Usage: storage show file <engine://filename>\n"
 "       Displays information about a file via the storage engine\n";
 
 char storage_show_engines_usage[] = 

Modified: team/group/ast_storage/res/res_storage_file.c
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/res/res_storage_file.c?view=diff&rev=79630&r1=79629&r2=79630
==============================================================================
--- team/group/ast_storage/res/res_storage_file.c (original)
+++ team/group/ast_storage/res/res_storage_file.c Wed Aug 15 17:33:19 2007
@@ -40,42 +40,42 @@
 #include "asterisk/file.h"
 
 struct ast_storage_file {
-	const struct ast_storage_be *be;
-	char rootpath[128];
+	/* Nothing here */
 };
 
 struct file_storage_dir {
 	DIR *dir;
-	char path[256];
+	char path[PATH_MAX];
 };
 
 static const struct ast_storage_be file_se;
 
 static struct ast_storage *se_create_file(const char *uri)
 {
+	struct ast_storage *st = ast_calloc(1, sizeof(struct ast_storage));
 	struct ast_storage_file *fst = ast_calloc(1, sizeof(struct ast_storage_file));
-	struct ast_storage_filelist *fl = ast_calloc(1, sizeof(struct ast_storage_filelist));
-	ast_copy_string(fst->rootpath, uri, sizeof(fst->rootpath));
-	fst->be = &file_se;
-	((struct ast_storage_be *)fst->be)->fl = fl;
-	return ((struct ast_storage *)fst);
+	st->xst = (void *)fst;
+	st->be = &file_se;
+	ast_copy_string(st->path, uri, sizeof(st->path));
+	return st;
 }
 
 static int se_free_file(struct ast_storage *st)
 {
+	if (st->xst)
+		free(st->xst);
 	free(st);
 	return 0;
 }
 
 static void *se_opendir_file(struct ast_storage *st, const char *objectpath)
 {
-	struct ast_storage_file *fst = (struct ast_storage_file *)st;
 	struct file_storage_dir *dir = ast_calloc(1, sizeof(*dir));
 
 	if (objectpath[0] == '/')
 		ast_copy_string(dir->path, objectpath, sizeof(dir->path));
 	else
-		snprintf(dir->path, sizeof(dir->path), "%s/%s", fst->rootpath, objectpath);
+		snprintf(dir->path, sizeof(dir->path), "%s/%s", st->path, objectpath);
 
 	if ((dir->dir = opendir(dir->path)))
 		return dir;
@@ -89,7 +89,6 @@
 {
 	struct dirent *f;
 	struct file_storage_dir *dir = dirptr;
-	char *ext;
 
 	if (dirent == NULL)
 		return EINVAL;
@@ -98,11 +97,6 @@
 
 	if ((f = readdir(dir->dir))) {
 		ast_copy_string(dirent->name, f->d_name, sizeof(dirent->name));
-		/* Parse out the file extension */
-		if ((ext = strrchr(dirent->name, '.'))) {
-			*ext++ = '\0';
-			ast_copy_string(dirent->ext, ext, sizeof(dirent->ext));
-		}
 		return 0;
 	}
 	return -1;
@@ -147,11 +141,10 @@
 
 static int se_get_file(struct ast_storage *st, const char *objectname, const char *exts, char *localfile, size_t localfilesize)
 {
-	struct ast_storage_filelist *fl = NULL;
-	struct ast_storage_file *fst = (struct ast_storage_file *)st;
 	struct file_storage_dir *dir;
 	struct ast_storage_dirent *dirent;
-	char dirname[256], *dirnameptr;
+	struct stat statbuf;
+	char dirname[PATH_MAX], *dirnameptr;
 
 	if (ast_strlen_zero(objectname))
 		return -1;
@@ -159,7 +152,7 @@
 	if (objectname[0] == '/')
 		ast_copy_string(localfile, objectname, localfilesize);
 	else
-		snprintf(localfile, localfilesize, "%s/%s", fst->rootpath, objectname);
+		snprintf(localfile, localfilesize, "%s/%s", st->path, objectname);
 
 	ast_copy_string(dirname, localfile, sizeof(dirname));
 	dirnameptr = strrchr(dirname, '/');
@@ -168,22 +161,37 @@
 	else
 		return -1;
 
-	fl = ast_calloc(1, sizeof(*fl));
-
 	if ((dir = se_opendir_file(st, dirname))) {
 		dirent = ast_calloc(1, sizeof(*dirent));
 		while ((!se_readdir_file(st, dir, dirent))) {
 			int found = 0;
-
-			if (!ast_strlen_zero(dirent->ext)) {
-				char fullfn[256];
-				snprintf(fullfn, sizeof(fullfn), "%s.%s", dirent->name, dirent->ext);
+			char *fn = ast_strdupa(dirent->name);
+			char fullfn[PATH_MAX];
+			char *ext = NULL;
+
+			/* Parse out the file extension */
+			if ((ext = strrchr(fn, '.'))) {
+				*ext++ = '\0';
+			}
+
+			if (ext && !strcmp(ext, "txt"))
+				continue;
+
+			snprintf(fullfn, sizeof(fullfn), "%s/%s", dirname, dirent->name);
+
+			if (stat(fullfn, &statbuf))
+				continue;
+
+			if (!S_ISREG(statbuf.st_mode))
+				continue;
+
+			if (!ast_strlen_zero(ext)) {
 				/* If it's going to be an exact match, we don't care about exts */
-				if (!strcmp(fullfn, dirnameptr))
+				if (!strcmp(dirent->name, dirnameptr))
 					found = 1;
 			}
-			if (!found && !strcmp(dirent->name, dirnameptr)) {
-				if (ast_strlen_zero(dirent->ext) || !exts || ast_exts_compare(exts, dirent->ext))
+			if (!found && !strcmp(fn, dirnameptr)) {
+				if (ast_strlen_zero(ext) || !exts || ast_exts_compare(exts, ext))
 					found = 1;
 			}
 
@@ -192,35 +200,32 @@
 				fi = ast_calloc(1, sizeof(*fi));
 				fi->ent = ast_calloc(1, sizeof(struct ast_storage_dirent));
 				ast_copy_string(fi->ent->name, dirent->name, sizeof(fi->ent->name));
-				ast_copy_string(fi->ent->ext, dirent->ext, sizeof(fi->ent->ext));
-				AST_RWLIST_WRLOCK(&fl->files);
-				AST_RWLIST_INSERT_TAIL(&fl->files, fi, list);
-				AST_RWLIST_UNLOCK(&fl->files);
+				AST_RWLIST_WRLOCK(&st->fl->files);
+				AST_RWLIST_INSERT_TAIL(&st->fl->files, fi, list);
+				AST_RWLIST_UNLOCK(&st->fl->files);
 			}
 		}
 		free(dirent);
 		se_closedir_file(st, dir);
 	} else {
-		free(fl);
-		return -1;
-	}
-
-	st->be->fl = fl;
+		return -1;
+	}
+
 	return 0;
 }
 
 #if 0
 static int se_put_file(struct ast_storage *st, struct ast_storage_filelist *fl, const char *exts)
 {
-	struct ast_storage_file *fst = (struct ast_storage_file *)st;
+	struct ast_storage_file *fst = (struct ast_storage_file *)st->xst;
 	int ifd;
 	int ofd;
 	int res = 0;
 	int len = 0;
-	char dest[256];
+	char dest[PATH_MAX];
 	char buf[4096];
 
-	snprintf(dest, sizeof(dest), "%s/%s", fst->rootpath, fl->name);
+	snprintf(dest, sizeof(dest), "%s/%s", st->path, fl->name);
 
 /* XXX We aren't going to read() directly from the filesystem for put()s.
 	if ((ifd = open(localfile, O_RDONLY)) < 0) {
@@ -261,13 +266,12 @@
 
 static int se_del_file(struct ast_storage *st, const char *exts)
 {
-	struct ast_storage_file *fst = (struct ast_storage_file *)st;
-	char dest[256];
-
-	if (st->be->fl->name[0] == '/')
-		return unlink(st->be->fl->name);
+	char dest[PATH_MAX];
+
+	if (st->fl->name[0] == '/')
+		return unlink(st->fl->name);
 	else {
-		snprintf(dest, sizeof(dest), "%s/%s", fst->rootpath, st->be->fl->name);
+		snprintf(dest, sizeof(dest), "%s/%s", st->path, st->fl->name);
 		return unlink(dest);
 	}
 }

Modified: team/group/ast_storage/res/res_storage_odbc.c
URL: http://svn.digium.com/view/asterisk/team/group/ast_storage/res/res_storage_odbc.c?view=diff&rev=79630&r1=79629&r2=79630
==============================================================================
--- team/group/ast_storage/res/res_storage_odbc.c (original)
+++ team/group/ast_storage/res/res_storage_odbc.c Wed Aug 15 17:33:19 2007
@@ -59,10 +59,8 @@
 };
 
 struct ast_storage_odbc {
-	const struct ast_storage_be *be;
 	char odbc_class[128];
 	char tablename[128];
-	char pathname[128];
 	struct odbc_obj *conn;
 	AST_RWLIST_HEAD(odbc_columns, columns) columns;
 };
@@ -115,9 +113,11 @@
 
 static int se_free_odbc(struct ast_storage *st)
 {
-	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
-	ast_odbc_release_obj(ost->conn);
-	free(ost);
+	if (((struct ast_storage_odbc *)st->xst)->conn)
+		ast_odbc_release_obj(((struct ast_storage_odbc *)st->xst)->conn);
+	if (st->xst)
+		free(st->xst);
+	free(st);
 	return 0;
 }
 
@@ -125,7 +125,8 @@
 {
 	char tmp[256], columnname[80];
 	int res;
-	struct ast_storage_odbc *ost = ast_calloc(1, sizeof(struct ast_storage_odbc));
+	struct ast_storage *st = ast_calloc(1, sizeof(struct ast_storage));
+	struct ast_storage_odbc *ost;
 	struct columns *entry;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(class);
@@ -135,33 +136,39 @@
 	SQLHSTMT stmt = NULL;
 	SQLLEN sqlptr;
 
-	if (!ost)
+	if (!st) {
+		se_free_odbc(st);
 		return NULL;
-
-	if (ast_strlen_zero(uri))
+	}
+
+	if (ast_strlen_zero(uri)) {
+		se_free_odbc(st);
 		return NULL;
+	}
+
+	ost = ast_calloc(1, sizeof(struct ast_storage_odbc));
+	st->xst = (void *)ost;
+	st->be = &odbc_se;
+	ast_copy_string(tmp, uri, sizeof(tmp));
 
 	AST_RWLIST_HEAD_INIT(&ost->columns);
 
-	ast_copy_string(tmp, uri, sizeof(tmp));
 	AST_NONSTANDARD_APP_ARGS(args, tmp, '/');
 
-	ost->be = &odbc_se;
 	ast_copy_string(ost->odbc_class, args.class, sizeof(ost->odbc_class));
 	ast_copy_string(ost->tablename, args.tablename, sizeof(ost->tablename));
-	ast_copy_string(ost->pathname, args.pathname, sizeof(ost->pathname));
+	ast_copy_string(st->path, args.pathname, sizeof(st->path));
 	ost->conn = ast_odbc_request_obj(ost->odbc_class, 0);
 
 	if (!ost->conn) {
-		free(ost);
+		se_free_odbc(st);
 		return NULL;
 	}
 
 	res = SQLAllocHandle(SQL_HANDLE_STMT, ost->conn->con, &stmt);
 	if (res != SQL_SUCCESS && res != SQL_SUCCESS_WITH_INFO) {
 		ast_log(LOG_ERROR, "Allocation of database handle failed.\n");
-		ast_odbc_release_obj(ost->conn);
-		free(ost);
+		se_free_odbc(st);
 		return NULL;
 	}
 
@@ -169,8 +176,7 @@
 	res = SQLColumns(stmt, NULL, 0, NULL, 0, (unsigned char *)ost->tablename, SQL_NTS, (unsigned char *)"%", SQL_NTS);
 	if (res != SQL_SUCCESS && res != SQL_SUCCESS_WITH_INFO) {
 		ast_log(LOG_ERROR, "Unable to query database columns on table '%s@%s'.  Storage method fails.\n", ost->tablename, ost->odbc_class);
-		ast_odbc_release_obj(ost->conn);
-		free(ost);
+		se_free_odbc(st);
 		return NULL;
 	}
 
@@ -179,7 +185,7 @@
 		entry = ast_calloc(sizeof(char), sizeof(*entry) + strlen(columnname) + 1);
 		if (!entry) {
 			ast_log(LOG_ERROR, "Unable to allocate column entry\n");
-			se_free_odbc((struct ast_storage *)ost);
+			se_free_odbc(st);
 			return NULL;
 		}
 
@@ -196,7 +202,7 @@
 		AST_LIST_INSERT_TAIL(&ost->columns, entry, list);
 	}
 
-	return ((struct ast_storage *)ost);
+	return st;
 }
 
 static void get_path_file(struct ast_storage_odbc *ost, const char *objectname, char *pathname, size_t pathnamesize, char *filename, size_t filenamesize)
@@ -213,12 +219,12 @@
 
 			/* Absolute or relative path? */
 			if (tmp[0] == '/')
-				ast_copy_string(pathname, tmp, sizeof(pathname));
+				ast_copy_string(pathname, tmp, pathnamesize);
 			else
-				snprintf(pathname, sizeof(pathname), "%s/%s", ost->pathname, tmp);
+				snprintf(pathname, pathnamesize, "%s/%s", ((struct ast_storage *)ost)->path, tmp);
 		}
 	} else {
-		ast_copy_string(pathname, ost->pathname, sizeof(pathname));
+		ast_copy_string(pathname, ((struct ast_storage *)ost)->path, pathnamesize);
 		filename2 = tmp;
 	}
 	ast_copy_string(filename, filename2, filenamesize);
@@ -226,12 +232,12 @@
 
 static int se_get_odbc(struct ast_storage *st, const char *objectname, const char *exts, char *localfile, size_t localfilesize)
 {
-	struct ast_storage_filelist *fl = NULL;
-	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
+	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st->xst;
 	int res = -1, tempfd, x, gotten = 0;
 	char sql[128];
 	char pathname[256], filename[256], reallocalfile[256];
 	char ext[10], rowdata[256], coltitle[128];
+	char *fext = NULL;
 	SQLHSTMT stmt;
 	SQLSMALLINT colcount, collen, datatype;
 	FILE *txt;
@@ -256,7 +262,15 @@
 
 	get_path_file(ost, objectname, pathname, sizeof(pathname), filename, sizeof(filename));
 
-	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE pathname=? AND filename=?", ost->tablename);
+	/* Parse out the file extension */
+	if ((fext = strrchr(filename, '.'))) {
+		*fext++ = '\0';
+	}
+
+	if (fext)
+		snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE pathname=? AND filename=? AND extension=?", ost->tablename);
+	else
+		snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE pathname=? AND filename=?", ost->tablename);
 
 	res = SQLAllocHandle(SQL_HANDLE_STMT, ost->conn->con, &stmt);
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
@@ -275,6 +289,8 @@
 
 	SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(pathname), 0, (void *)pathname, 0, NULL);
 	SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(filename), 0, (void *)filename, 0, NULL);
+	if (fext)
+		SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(fext), 0, (void *)fext, 0, NULL);
 
 	res = ast_odbc_smart_execute(ost->conn, stmt);
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
@@ -283,6 +299,8 @@
 	}
 
 	while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
+		struct ast_storage_fileinst *fi;
+		int createdest = 0;
 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 			ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n", sql);
 			goto endget;
@@ -316,7 +334,7 @@
 				void *fdm = NULL;
 				SQLLEN colsize2;
 
-				if (!ast_strlen_zero(ext)) {
+				if (createdest && !ast_strlen_zero(ext)) {
 					/* We have an extension, just go ahead and create the destination */
 					snprintf(reallocalfile, sizeof(reallocalfile), "%s.%s", localfile, ext);
 					fd = open(reallocalfile, O_CREAT | O_WRONLY | O_EXCL);
@@ -375,6 +393,7 @@
 					goto endget;
 				}
 				if (!strcasecmp(coltitle, "extension")) {
+					ast_copy_string(ext, rowdata, sizeof(ext));
 					/* Is there a recording waiting for us? */
 					if (lseek(tempfd, 0, SEEK_CUR) > 0) {
 						snprintf(reallocalfile, sizeof(reallocalfile), "%s.%s", localfile, rowdata);
@@ -382,13 +401,22 @@
 						lseek(tempfd, 0, SEEK_SET);
 						truncate(localfile, 0);
 					} else
-						ast_copy_string(ext, rowdata, sizeof(ext));
+						createdest = 1;
 				} else if (strcasecmp(coltitle, "filename") && strcasecmp(coltitle, "pathname") && !ast_strlen_zero(rowdata) && !gotten)
 					fprintf(txt, "%s=%s\n", coltitle, rowdata);
 			}
 			if (fd > -1 && fd != tempfd)
 				close(fd);
 		}
+		fi = ast_calloc(1, sizeof(*fi));
+		fi->ent = ast_calloc(1, sizeof(struct ast_storage_dirent));
+		if (!ast_strlen_zero(ext))
+			snprintf(fi->ent->name, sizeof(fi->ent->name), "%s.%s", filename, ext);
+		else
+			ast_copy_string(fi->ent->name, filename, sizeof(fi->ent->name));
+		AST_RWLIST_WRLOCK(&st->fl->files);
+		AST_RWLIST_INSERT_TAIL(&st->fl->files, fi, list);
+		AST_RWLIST_UNLOCK(&st->fl->files);
 		gotten = 1;
 	}
 	res = 0;
@@ -399,14 +427,13 @@
 	/* This is just the temp marker */
 	unlink(localfile);
 
-	st->be->fl = res ? NULL : fl;
 	return res;
 }
 
 #if 0
 static int se_put_odbc(struct ast_storage *st, struct ast_storage_filelist *fl, const char *exts)
 {
-	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
+	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st->xst;
 	int res = -1, x;
 	struct ast_config *cfg;
 	struct ast_variable *cfgvar, *var;
@@ -540,11 +567,11 @@
 static int se_del_odbc(struct ast_storage *st, const char *exts)
 {
 	char pathname[256], filename[256], sql[256];
-	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
+	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st->xst;
 	int res;
 	SQLHSTMT sth;
 
-	get_path_file(ost, st->be->fl->name, pathname, sizeof(pathname), filename, sizeof(filename));
+	get_path_file(ost, st->fl->name, pathname, sizeof(pathname), filename, sizeof(filename));
 
 	snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE pathname=? AND filename=?", ost->tablename);
 
@@ -616,7 +643,7 @@
 
 static int se_status_odbc(struct ast_storage *st, int fd)
 {
-	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st;
+	struct ast_storage_odbc *ost = (struct ast_storage_odbc *)st->xst;
 	ast_cli(fd, "Connected: %s\n", (ost && ost->conn && ost->conn->up) ? "yes" : "no");
 	return 0;
 }




More information about the asterisk-commits mailing list