summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2012-06-02 18:53:13 +0000
committerGuy Harris <guy@alum.mit.edu>2012-06-02 18:53:13 +0000
commit68a4971594be308056cd28833cb4f21213beb71c (patch)
tree17f79825410c1847824774adca2381fa2a113ca5
parent2e4f30d0f92025226ed1168bfa7b1b5fe50548c4 (diff)
downloadwireshark-68a4971594be308056cd28833cb4f21213beb71c.tar.gz
If the user tries to save a capture file atop a file that has all its
write bits turned off or, on 4.4-Lite-based systems, has its "user immutable" bit turned on, ask them if they really want to overwrite the file (as those are both used to say "this file is precious, don't let me easily accidentally trash it") and, if the "user immutable" bit is set, turn it off first so that the move in the "safe save" won't fail. svn path=/trunk/; revision=43006
-rw-r--r--acinclude.m422
-rw-r--r--configure.in5
-rw-r--r--ui/gtk/capture_file_dlg.c90
3 files changed, 113 insertions, 4 deletions
diff --git a/acinclude.m4 b/acinclude.m4
index 45cbc1dfbb..052b2beb17 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -105,6 +105,28 @@ AC_DEFUN([AC_WIRESHARK_TIMEZONE_ABBREV],
#
+# AC_WIRESHARK_STRUCT_ST_FLAGS
+#
+dnl AC_STRUCT_ST_BLKSIZE extracted from the file in question,
+dnl "acspecific.m4" in GNU Autoconf 2.12, and turned into
+dnl AC_WIRESHARK_STRUCT_ST_FLAGS, which checks if "struct stat"
+dnl has the 4.4BSD "st_flags" member, and defines HAVE_ST_FLAGS; that's
+dnl what's in this file.
+dnl Done by Guy Harris <guy@alum.mit.edu> on 2012-06-02.
+
+dnl ### Checks for structure members
+
+AC_DEFUN([AC_WIRESHARK_STRUCT_ST_FLAGS],
+[AC_CACHE_CHECK([for st_flags in struct stat], ac_cv_wireshark_struct_st_flags,
+[AC_TRY_COMPILE([#include <sys/stat.h>], [struct stat s; s.st_flags;],
+ac_cv_wireshark_struct_st_flags=yes, ac_cv_wireshark_struct_st_flags=no)])
+if test $ac_cv_wireshark_struct_st_flags = yes; then
+ AC_DEFINE(HAVE_ST_FLAGS, 1, [Define if st_flags field exists in struct stat])
+fi
+])
+
+
+#
# AC_WIRESHARK_STRUCT_SA_LEN
#
dnl AC_STRUCT_ST_BLKSIZE extracted from the file in question,
diff --git a/configure.in b/configure.in
index 9d77edc592..4c6b15986e 100644
--- a/configure.in
+++ b/configure.in
@@ -1755,6 +1755,11 @@ dnl Checks for typedefs, structures, and compiler characteristics.
# Check how we can get the time zone abbreviation
AC_WIRESHARK_TIMEZONE_ABBREV
+# We need to know whether "struct stat" has an "st_flags" member
+# for file_user_immutable().
+
+AC_WIRESHARK_STRUCT_ST_FLAGS
+
# We need to know whether "struct sockaddr" has an "sa_len" member
# for get_interface_list().
diff --git a/ui/gtk/capture_file_dlg.c b/ui/gtk/capture_file_dlg.c
index 3c8270c50a..9bda1e4078 100644
--- a/ui/gtk/capture_file_dlg.c
+++ b/ui/gtk/capture_file_dlg.c
@@ -1292,6 +1292,7 @@ do_file_save_as(capture_file *cf)
gchar *display_basename;
gint response;
char *cf_name;
+ ws_statb64 statbuf;
if (file_save_as_w != NULL) {
/* There's already an "Save Capture File As" dialog box; reactivate it. */
@@ -1398,10 +1399,6 @@ do_file_save_as(capture_file *cf)
}
/* The file exists. Ask the user if they want to overwrite it. */
-
- /*
- * Format the message.
- */
display_basename = g_filename_display_basename(cf_name);
msg_dialog = gtk_message_dialog_new(GTK_WINDOW(file_save_as_w),
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -1435,6 +1432,91 @@ do_file_save_as(capture_file *cf)
continue;
}
+ /* Check whether the file has all the write permission bits clear
+ and, on systems that have the 4.4-Lite file flags, whether it
+ has the "user immutable" flag set. Treat both of those as an
+ indication that the user wants to protect the file from
+ casual overwriting, and ask the user if they want to override
+ that.
+
+ (Linux's "immutable" flag, as fetched and set by the appropriate
+ ioctls (FS_IOC_GETFLAGS/FS_IOC_SETFLAGS in newer kernels,
+ EXT2_IOC_GETFLAGS/EXT2_IOC_SETFLAGS in older kernels - non-ext2
+ file systems that support those ioctls use the same values as ext2
+ does), appears to be more like the *BSD/OS X "system immutable"
+ flag, as it can be set only by the superuser or by processes with
+ CAP_LINUX_IMMUTABLE, so it sounds as if it's not intended for
+ arbitrary users to set or clear. */
+ if (ws_stat64(cf_name, &statbuf) != -1) {
+ /* OK, we have the permission bits and, if HAVE_ST_FLAGS is defined,
+ the flags. (If we don't, we don't worry about it.) */
+#ifdef HAVE_ST_FLAGS
+ if (statbuf.st_flags & UF_IMMUTABLE) {
+ display_basename = g_filename_display_basename(cf_name);
+ msg_dialog = gtk_message_dialog_new(GTK_WINDOW(file_save_as_w),
+ GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+#ifdef __APPLE__
+ /* Stuff in the OS X UI calls files with the "user immutable" bit
+ "locked"; pre-OS X Mac software might have had that notion and
+ called it "locked". */
+ "The file \"%s\" is locked.",
+#else /* __APPLE__ */
+ /* Just call it "immutable" in *BSD. */
+ "The file \"%s\" is immutable.",
+#endif /* __APPLE__ */
+ display_basename);
+ g_free(display_basename);
+ } else
+#endif /* HAVE_ST_FLAGS */
+ if ((statbuf.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0) {
+ display_basename = g_filename_display_basename(cf_name);
+ msg_dialog = gtk_message_dialog_new(GTK_WINDOW(file_save_as_w),
+ GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ "The file \"%s\" is not writable.",
+ display_basename);
+ g_free(display_basename);
+ } else {
+ /* No problem, just drive on. */
+ msg_dialog = NULL;
+ }
+ if (msg_dialog != NULL) {
+ /* OK, ask the user if they want to overwrite the file. */
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg_dialog),
+ "Do you want to overwrite it anyway?");
+
+ gtk_dialog_add_buttons(GTK_DIALOG(msg_dialog),
+ "Overwrite", GTK_RESPONSE_ACCEPT,
+ "Don't overwrite", GTK_RESPONSE_REJECT,
+ NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(msg_dialog), GTK_RESPONSE_REJECT);
+
+ response = gtk_dialog_run(GTK_DIALOG(msg_dialog));
+ gtk_widget_destroy(msg_dialog);
+
+ if (response != GTK_RESPONSE_ACCEPT) {
+ /* The user doesn't want to overwrite this file; let them choose
+ another one */
+ g_free(cf_name);
+ continue;
+ }
+
+#ifdef HAVE_ST_FLAGS
+ /* OK, they want to overwrite the file. If it has the "user
+ immutable" flag, we have to turn that off first, so we
+ can move the file. */
+ if (statbuf.st_flags & UF_IMMUTABLE) {
+ /* If this fails, the attempt to save will fail, so just
+ let that happen and pop up a "you lose" dialog. */
+ chflags(cf_name, statbuf.st_flags & ~UF_IMMUTABLE);
+ }
+#endif
+ }
+ }
+
/* save file */
gtk_widget_hide(GTK_WIDGET(file_save_as_w));
file_save_as_cb(file_save_as_w);