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
This commit is contained in:
Guy Harris 2012-06-02 18:53:13 +00:00
parent 2e4f30d0f9
commit 68a4971594
3 changed files with 113 additions and 4 deletions

View File

@ -104,6 +104,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
#

View File

@ -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().

View File

@ -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);