diff --git a/app.c b/app.c
index 5e5230e963a1b7fd94d932da177048ac850e4fc5..5f96478e3349abb96aef04ecc98e3316e3215240 100755
--- a/app.c
+++ b/app.c
@@ -1095,36 +1095,42 @@ int ast_separate_app_args(char *buf, char delim, char **array, int arraylen)
 	return x;
 }
 
-int ast_lock_path(const char *path)
+enum AST_LOCK_RESULT ast_lock_path(const char *path)
 {
 	char *s;
 	char *fs;
 	int res;
 	int fd;
 	time_t start;
+
 	s = alloca(strlen(path) + 10);
 	fs = alloca(strlen(path) + 20);
+
 	if (!fs || !s) {
 		ast_log(LOG_WARNING, "Out of memory!\n");
-		return -1;
+		return AST_LOCK_FAILURE;
 	}
-	snprintf(fs, strlen(path) + 19, "%s/%s-%08x", path, ".lock", rand());
+
+	snprintf(fs, strlen(path) + 19, "%s/.lock-%08x", path, rand());
 	fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
 	if (fd < 0) {
-		fprintf(stderr, "Unable to create lock file: %s\n", strerror(errno));
-		return -1;
+		fprintf(stderr, "Unable to create lock file '%s': %s\n", path, strerror(errno));
+		return AST_LOCK_PATH_NOT_FOUND;
 	}
 	close(fd);
-	snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
+
+	snprintf(s, strlen(path) + 9, "%s/.lock", path);
 	time(&start);
 	while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
 		usleep(1);
-	if (res < 0) {
+	if (res) {
 		ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
+		return AST_LOCK_TIMEOUT;
+	} else {
+		unlink(fs);
+		ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
+		return AST_LOCK_SUCCESS;
 	}
-	unlink(fs);
-	ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
-	return res;
 }
 
 int ast_unlock_path(const char *path)
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 3e8399694b1a187a93b6b1bf3fbf061d988226b9..0bdb40cd7c9afe09f69c57520cb6701163debedc 100755
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -692,6 +692,19 @@ static int make_file(char *dest, int len, char *dir, int num)
 	return snprintf(dest, len, "%s/msg%04d", dir, num);
 }
 
+/* only return failure if ast_lock_path returns 'timeout',
+   not if the path does not exist or any other reason
+*/
+static int vm_lock_path(const char *path)
+{
+	switch (ast_lock_path(path)) {
+	case AST_LOCK_TIMEOUT:
+		return -1;
+	default:
+		return 0;
+	}
+}
+
 
 #ifdef USE_ODBC_STORAGE
 static int retrieve_file(char *dir, int msgnum)
@@ -982,9 +995,9 @@ yuck:
  */
 static int count_messages(struct ast_vm_user *vmu, char *dir)
 {
-	int res = 0;
+	int res;
 	
-	res = last_message_index(vmu, dir) + 1;
+	res = last_message_index(vmu, dir);
 	return res >= 0 ? res + 1 : res;
 }
 
@@ -1259,23 +1272,19 @@ static int count_messages(struct ast_vm_user *vmu, char *dir)
 	DIR *vmdir = NULL;
 	struct dirent *vment = NULL;
 
-	if (!ast_lock_path(dir)) {
-		if ((vmdir = opendir(dir))) {
-			while ((vment = readdir(vmdir)))
-			{
-				if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,".txt",4))
-				{
-					vmcount++;
-				}
-			}
-			closedir(vmdir);
-		}
-		ast_unlock_path(dir);
-
-		return vmcount;
-	} else {
+	if (vm_lock_path(dir))
 		return ERROR_LOCK_PATH;
+
+	if ((vmdir = opendir(dir))) {
+		while ((vment = readdir(vmdir))) {
+			if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4)) 
+				vmcount++;
+		}
+		closedir(vmdir);
 	}
+	ast_unlock_path(dir);
+	
+	return vmcount;
 }
 
 static void rename_file(char *sfn, char *dfn)
@@ -1354,17 +1363,18 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir)
 {
 	int x;
 	char fn[256];
-	if (!ast_lock_path(dir)) {
-		for (x = 0; x < vmu->maxmsg; x++) {
-			make_file(fn, sizeof(fn), dir, x);
-			if (ast_fileexists(fn, NULL, NULL) < 1)
-				break;
-		}
-		ast_unlock_path(dir);
-		return x-1;
-	} else {
+
+	if (vm_lock_path(dir))
 		return ERROR_LOCK_PATH;
+
+	for (x = 0; x < vmu->maxmsg; x++) {
+		make_file(fn, sizeof(fn), dir, x);
+		if (ast_fileexists(fn, NULL, NULL) < 1)
+			break;
 	}
+	ast_unlock_path(dir);
+
+	return x - 1;
 }
 
 static int vm_delete(char *file)
@@ -1997,24 +2007,24 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i
 
 	make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
 	make_file(frompath, sizeof(frompath), fromdir, msgnum);
-	if (!ast_lock_path(topath)) {
-		recipmsgnum = 0;
-		do {
-			make_file(topath, sizeof(topath), todir, recipmsgnum);
-			if (!EXISTS(todir, recipmsgnum, topath, chan->language))
-				break;
-			recipmsgnum++;
+
+	if (vm_lock_path(topath))
+		return ERROR_LOCK_PATH;
+
+	recipmsgnum = 0;
+	do {
+		make_file(topath, sizeof(topath), todir, recipmsgnum);
+		if (!EXISTS(todir, recipmsgnum, topath, chan->language))
+			break;
+		recipmsgnum++;
 	} while (recipmsgnum < recip->maxmsg);
 	if (recipmsgnum < recip->maxmsg) {
-			COPY(fromdir, msgnum, todir, recipmsgnum, frompath, topath);
-		} else {
-			ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
-		}
-		ast_unlock_path(topath);
-		notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
+		COPY(fromdir, msgnum, todir, recipmsgnum, frompath, topath);
 	} else {
-		return ERROR_LOCK_PATH;
+		ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
 	}
+	ast_unlock_path(topath);
+	notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
 	
 	return 0;
 }
@@ -2208,106 +2218,106 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int
 		ast_copy_string(fmt, vmfmts, sizeof(fmt));
 		if (!ast_strlen_zero(fmt)) {
 			msgnum = 0;
-			if (!ast_lock_path(dir)) {
-				if (res >= 0) {
-					/* Unless we're *really* silent, try to send the beep */
-					res = ast_streamfile(chan, "beep", chan->language);
-					if (!res)
-						res = ast_waitstream(chan, "");
-				}
-				do {
-					make_file(fn, sizeof(fn), dir, msgnum);
-					if (!EXISTS(dir,msgnum,fn,chan->language))
-						break;
-					msgnum++;
+
+			if (vm_lock_path(dir)) {
+				free_user(vmu);
+				return ERROR_LOCK_PATH;
+			}
+
+			if (res >= 0) {
+				/* Unless we're *really* silent, try to send the beep */
+				res = ast_streamfile(chan, "beep", chan->language);
+				if (!res)
+					res = ast_waitstream(chan, "");
+			}
+			do {
+				make_file(fn, sizeof(fn), dir, msgnum);
+				if (!EXISTS(dir,msgnum,fn,chan->language))
+					break;
+				msgnum++;
 			} while (msgnum < vmu->maxmsg);
 			if (msgnum < vmu->maxmsg) {
-	
-					/* assign a variable with the name of the voicemail file */	  
-					pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
-	
-					/* Store information */
-					snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
-					txt = fopen(txtfile, "w+");
-					if (txt) {
-						get_date(date, sizeof(date));
-						fprintf(txt, 
-";\n"
-"; Message Information file\n"
-";\n"
-"[message]\n"
-"origmailbox=%s\n"
-"context=%s\n"
-"macrocontext=%s\n"
-"exten=%s\n"
-"priority=%d\n"
-"callerchan=%s\n"
-"callerid=%s\n"
-"origdate=%s\n"
-"origtime=%ld\n"
-"category=%s\n",
-		ext,
-		chan->context,
-		chan->macrocontext, 
-		chan->exten,
-		chan->priority,
-		chan->name,
-		ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
-		date, (long)time(NULL),
-		category ? category : ""); 
-					} else
-						ast_log(LOG_WARNING, "Error opening text file for output\n");
-					res = play_record_review(chan, NULL, fn, vmmaxmessage, fmt, 1, vmu, &duration, dir);
-					if (res == '0') {
-						if (txt)
-							fclose(txt);
-						goto transfer;
-					}
-					if (res > 0)
-						res = 0;
-					if (txt) {
-						fprintf(txt, "duration=%d\n", duration);
+				/* assign a variable with the name of the voicemail file */	  
+				pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
+				
+				/* Store information */
+				snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
+				txt = fopen(txtfile, "w+");
+				if (txt) {
+					get_date(date, sizeof(date));
+					fprintf(txt, 
+						";\n"
+						"; Message Information file\n"
+						";\n"
+						"[message]\n"
+						"origmailbox=%s\n"
+						"context=%s\n"
+						"macrocontext=%s\n"
+						"exten=%s\n"
+						"priority=%d\n"
+						"callerchan=%s\n"
+						"callerid=%s\n"
+						"origdate=%s\n"
+						"origtime=%ld\n"
+						"category=%s\n",
+						ext,
+						chan->context,
+						chan->macrocontext, 
+						chan->exten,
+						chan->priority,
+						chan->name,
+						ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
+						date, (long)time(NULL),
+						category ? category : ""); 
+				} else
+					ast_log(LOG_WARNING, "Error opening text file for output\n");
+				res = play_record_review(chan, NULL, fn, vmmaxmessage, fmt, 1, vmu, &duration, dir);
+				if (res == '0') {
+					if (txt)
 						fclose(txt);
-					}
+					goto transfer;
+				}
+				if (res > 0)
+					res = 0;
+				if (txt) {
+					fprintf(txt, "duration=%d\n", duration);
+					fclose(txt);
+				}
 				
-					if (duration < vmminmessage) {
-						if (option_verbose > 2) 
-							ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
-						DELETE(dir,msgnum,fn);
-						/* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
-						goto leave_vm_out;
-					}
-					/* Are there to be more recipients of this message? */
-					while (tmpptr) {
-						struct ast_vm_user recipu, *recip;
-						char *exten, *context;
-	
-						exten = strsep(&tmpptr, "&");
-						context = strchr(exten, '@');
-						if (context) {
-							*context = '\0';
-							context++;
-						}
-						if ((recip = find_user(&recipu, context, exten))) {
-							copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
-							free_user(recip);
-						}
+				if (duration < vmminmessage) {
+					if (option_verbose > 2) 
+						ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
+					DELETE(dir,msgnum,fn);
+					/* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
+					goto leave_vm_out;
+				}
+				/* Are there to be more recipients of this message? */
+				while (tmpptr) {
+					struct ast_vm_user recipu, *recip;
+					char *exten, *context;
+					
+					exten = strsep(&tmpptr, "&");
+					context = strchr(exten, '@');
+					if (context) {
+						*context = '\0';
+						context++;
 					}
-					if (ast_fileexists(fn, NULL, NULL)) {
-						notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
-						STORE(dir, msgnum);
-						DISPOSE(dir, msgnum);
+					if ((recip = find_user(&recipu, context, exten))) {
+						copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
+						free_user(recip);
 					}
-				} else {
-					ast_unlock_path(dir);
-					res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
-					if (!res)
-						res = ast_waitstream(chan, "");
-					ast_log(LOG_WARNING, "No more messages possible\n");
+				}
+				if (ast_fileexists(fn, NULL, NULL)) {
+					notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
+					STORE(dir, msgnum);
+					DISPOSE(dir, msgnum);
 				}
 			} else {
-				free_user(vmu);
-				return ERROR_LOCK_PATH;
+				ast_unlock_path(dir);
+				res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
+				if (!res)
+					res = ast_waitstream(chan, "");
+				ast_log(LOG_WARNING, "No more messages possible\n");
 			}
 		} else
 			ast_log(LOG_WARNING, "No format for saving voicemail?\n");
@@ -2316,8 +2326,7 @@ leave_vm_out:
 	} else {
 		ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
 		/*Send the call to n+101 priority, where n is the current priority*/
-		if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num))
-			chan->priority+=100;
+		ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
 	}
 
 	return res;
@@ -2332,24 +2341,23 @@ static int resequence_mailbox(struct ast_vm_user *vmu, char *dir)
 	char sfn[256];
 	char dfn[256];
 
-	if (!ast_lock_path(dir)) {
-		for (x = 0, dest = 0; x < vmu->maxmsg; x++) {
-			make_file(sfn, sizeof(sfn), dir, x);
-			if (EXISTS(dir, x, sfn, NULL)) {
-	
-				if(x != dest) {
-					make_file(dfn, sizeof(dfn), dir, dest);
-					RENAME(dir, x, dir, dest, sfn, dfn);
-				}
-	
-				dest++;
+	if (vm_lock_path(dir))
+		return ERROR_LOCK_PATH;
+
+	for (x = 0, dest = 0; x < vmu->maxmsg; x++) {
+		make_file(sfn, sizeof(sfn), dir, x);
+		if (EXISTS(dir, x, sfn, NULL)) {
+			
+			if(x != dest) {
+				make_file(dfn, sizeof(dfn), dir, dest);
+				RENAME(dir, x, dir, dest, sfn, dfn);
 			}
+			
+			dest++;
 		}
-		ast_unlock_path(dir);
-	} else {
-		return ERROR_LOCK_PATH;
 	}
-	
+	ast_unlock_path(dir);
+
 	return 0;
 }
 
@@ -2371,23 +2379,23 @@ static int save_to_folder(struct ast_vm_user *vmu, char *dir, int msg, char *con
 	make_file(sfn, sizeof(sfn), dir, msg);
 	make_dir(ddir, sizeof(ddir), context, username, dbox);
 	mkdir(ddir, 0700);
-	if (!ast_lock_path(ddir)) {
-		for (x = 0; x < vmu->maxmsg; x++) {
-			make_file(dfn, sizeof(dfn), ddir, x);
-			if (!EXISTS(ddir, x, dfn, NULL))
-				break;
-		}
-		if (x >= vmu->maxmsg) {
-			ast_unlock_path(ddir);
-			return -1;
-		}
-		if (strcmp(sfn, dfn)) {
-			COPY(dir, msg, ddir, x, sfn, dfn);
-		}
-		ast_unlock_path(ddir);
-	} else {
+
+	if (vm_lock_path(ddir))
 		return ERROR_LOCK_PATH;
+
+	for (x = 0; x < vmu->maxmsg; x++) {
+		make_file(dfn, sizeof(dfn), ddir, x);
+		if (!EXISTS(ddir, x, dfn, NULL))
+			break;
 	}
+	if (x >= vmu->maxmsg) {
+		ast_unlock_path(ddir);
+		return -1;
+	}
+	if (strcmp(sfn, dfn)) {
+		COPY(dir, msg, ddir, x, sfn, dfn);
+	}
+	ast_unlock_path(ddir);
 	
 	return 0;
 }
@@ -3526,45 +3534,49 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
 {
 	int x;
 	int res = 0;
-	if (vms->lastmsg > -1) { 
-		/* Get the deleted messages fixed */ 
-		if (!ast_lock_path(vms->curdir)) {
-			vms->curmsg = -1; 
-		for (x=0;x < vmu->maxmsg;x++) { 
-				if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) { 
-					/* Save this message.  It's not in INBOX or hasn't been heard */ 
-					make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
-					if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
-						break;
-					vms->curmsg++; 
-					make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg); 
-					if (strcmp(vms->fn, vms->fn2)) { 
-						RENAME(vms->curdir, x, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
-					} 
-				} else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) { 
-					/* Move to old folder before deleting */ 
-					res = save_to_folder(vmu, vms->curdir, x, vmu->context, vms->username, 1);
-					if (res == ERROR_LOCK_PATH) {
-						/* If save failed do not delete the message */
-						vms->deleted[x] = 0;
-						vms->heard[x] = 0;
-						--x;
-					} 
-				} 
+
+	if (vms->lastmsg <= -1)
+		goto done;
+
+	/* Get the deleted messages fixed */ 
+	if (vm_lock_path(vms->curdir))
+		return ERROR_LOCK_PATH;
+	
+	vms->curmsg = -1; 
+	for (x=0;x < vmu->maxmsg;x++) { 
+		if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) { 
+			/* Save this message.  It's not in INBOX or hasn't been heard */ 
+			make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
+			if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
+				break;
+			vms->curmsg++; 
+			make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg); 
+			if (strcmp(vms->fn, vms->fn2)) { 
+				RENAME(vms->curdir, x, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
 			} 
-			for (x = vms->curmsg + 1; x <= vmu->maxmsg; x++) { 
-				make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
-				if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
-					break;
-				DELETE(vms->curdir, x, vms->fn);
+		} else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) { 
+			/* Move to old folder before deleting */ 
+			res = save_to_folder(vmu, vms->curdir, x, vmu->context, vms->username, 1);
+			if (res == ERROR_LOCK_PATH) {
+				/* If save failed do not delete the message */
+				vms->deleted[x] = 0;
+				vms->heard[x] = 0;
+				--x;
 			} 
-			ast_unlock_path(vms->curdir);
-		} else {
-			return ERROR_LOCK_PATH;
-		}
+		} 
+	} 
+	for (x = vms->curmsg + 1; x <= vmu->maxmsg; x++) { 
+		make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); 
+		if (!EXISTS(vms->curdir, x, vms->fn, NULL)) 
+			break;
+		DELETE(vms->curdir, x, vms->fn);
 	} 
+	ast_unlock_path(vms->curdir);
+
+done:
 	memset(vms->deleted, 0, sizeof(vms->deleted)); 
 	memset(vms->heard, 0, sizeof(vms->heard)); 
+
 	return 0;
 }
 
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index 8d571e28eb29293b9fb93bacb84c5faf1c039e09..4ab7ef26360adb164ba251d1fc3bf04c4a1a5449 100755
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -139,8 +139,19 @@ int ast_play_and_record(struct ast_channel *chan, const char *playfile, const ch
 /*   permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults. */
 int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence_ms);
 
-/* Lock a path */
-int ast_lock_path(const char *path);
+enum AST_LOCK_RESULT {
+	AST_LOCK_SUCCESS = 0,
+	AST_LOCK_TIMEOUT = -1,
+	AST_LOCK_PATH_NOT_FOUND = -2,
+	AST_LOCK_FAILURE = -3,
+};
+
+/*
+ * \brief Lock a filesystem path.
+ * \param path the path to be locked
+ * \return one of AST_LOCK_RESULT values
+ */
+enum AST_LOCK_RESULT ast_lock_path(const char *path);
 
 /* Unlock a path */
 int ast_unlock_path(const char *path);