aboutsummaryrefslogtreecommitdiffstats
path: root/res
diff options
context:
space:
mode:
authorjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2009-11-04 23:47:08 +0000
committerjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2009-11-04 23:47:08 +0000
commit6f242aa9408194bc2c10330e52e6bca8afe7d02e (patch)
treeeed816b3e62c679874fe4667bfc8c30f42bd06a0 /res
parent5af26eb1aa769737e5aa5388f20787027917d1fc (diff)
Fix incorrect filename comparsion after monitor file change
The logic to detect if a requested file is indeed a different file from the current file was incorrect. The main issue being confusion of the use of filename_base which was previously set without pathing information and then compared to another full path. Robust file comparison logic has been added to properly check if two files are the same even if symlinks are used. (closes issue #15313) Reported by: caspy Patches: 20091103__issue15313__1.4.diff.txt uploaded by jpeeler (license 325) but mostly tilghman's work git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@227944 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res')
-rw-r--r--res/res_monitor.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/res/res_monitor.c b/res/res_monitor.c
index 69db65cd2..437705c77 100644
--- a/res/res_monitor.c
+++ b/res/res_monitor.c
@@ -169,7 +169,8 @@ int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out",
directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
- ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base));
+ snprintf(monitor->filename_base, FILENAME_MAX, "%s/%s",
+ ast_config_AST_MONITOR_DIR, fname_base);
} else {
ast_mutex_lock(&monitorlock);
snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
@@ -378,12 +379,47 @@ int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, i
int directory = strchr(fname_base, '/') ? 1 : 0;
const char *absolute = *fname_base == '/' ? "" : "/";
char tmpstring[sizeof(chan->monitor->filename_base)] = "";
+ int i, fd[2] = { -1, -1 }, doexit = 0;
/* before continuing, see if we're trying to rename the file to itself... */
snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
- if (!strcmp(tmpstring, chan->monitor->filename_base)) {
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n");
+
+ /*!\note We cannot just compare filenames, due to symlinks, relative
+ * paths, and other possible filesystem issues. We could use
+ * realpath(3), but its use is discouraged. However, if we try to
+ * create the same file from two different paths, the second will
+ * fail, and so we have our notification that the filenames point to
+ * the same path.
+ *
+ * Remember, also, that we're using the basename of the file (i.e.
+ * the file without the format suffix), so it does not already exist
+ * and we aren't interfering with the recording itself.
+ */
+ if (option_debug > 2) {
+ ast_log(LOG_DEBUG, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base);
+ }
+ if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||
+ (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
+ if (fd[0] < 0) {
+ ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno));
+ } else {
+ if (option_debug > 2) {
+ ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n");
+ }
+ }
+ doexit = 1;
+ }
+
+ /* Cleanup temporary files */
+ for (i = 0; i < 2; i++) {
+ if (fd[i] >= 0) {
+ while (close(fd[i]) < 0 && errno == EINTR);
+ }
+ }
+ unlink(tmpstring);
+ unlink(chan->monitor->filename_base);
+
+ if (doexit) {
UNLOCK_IF_NEEDED(chan, need_lock);
return 0;
}