diff options
-rw-r--r-- | acinclude.m4 | 22 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | ui/gtk/capture_file_dlg.c | 90 |
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); |