summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);