summaryrefslogtreecommitdiff
path: root/libnautilus-private
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@novell.com>2008-05-08 18:50:09 +0000
committerFederico Mena Quintero <federico@src.gnome.org>2008-05-08 18:50:09 +0000
commit0e85321fb6dcc0043d414d398932900121dd1f2b (patch)
tree63d1422a30d1370a478f27bf631bc7eb70200e77 /libnautilus-private
parent9b3056ae85f84b2d59ff651f3f5f41e0541e529f (diff)
downloadnautilus-0e85321fb6dcc0043d414d398932900121dd1f2b.tar.gz
bgo364843 - Don't exceed max path len when forming filenames for duplicates
2008-05-08 Federico Mena Quintero <federico@novell.com> http://bugzilla.gnome.org/show_bug.cgi?id=364843 Keep the generated names for "reallylongfilename (copy).txt" from overflowing the maximum allowed length for path names. Original patch by Dave Camp <campd@campd.org> * libnautilus-private/nautilus-file-operations.c (shorten_utf8_string): New function; takes an UTF8 string and hygienically truncates it to a given number of bytes. (get_link_name): Ensure the final name doesn't exceed a maximum length. (make_next_duplicate_name): Likewise. (get_max_name_length): Wrapper around pathconf() for basename lengths. (get_unique_target_file): Use a maximum length for the target name. (get_target_file_for_link): Likewise. Signed-off-by: Federico Mena Quintero <federico@gnu.org> svn path=/trunk/; revision=14147
Diffstat (limited to 'libnautilus-private')
-rw-r--r--libnautilus-private/nautilus-file-operations.c239
1 files changed, 186 insertions, 53 deletions
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index 28cae5aba..d79f8a537 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -229,15 +229,55 @@ format_time (int seconds)
hours), hours);
}
+static char *
+shorten_utf8_string (const char *base, int reduce_by_num_bytes)
+{
+ int len;
+ char *ret;
+ const char *p;
+
+ len = strlen (base);
+ len -= reduce_by_num_bytes;
+
+ if (len <= 0) {
+ return NULL;
+ }
+
+ ret = g_new (char, len + 1);
+
+ p = base;
+ while (len) {
+ char *next;
+ next = g_utf8_next_char (p);
+ if (next - p > len || *next == '\0') {
+ break;
+ }
+
+ len -= next - p;
+ p = next;
+ }
+
+ if (p - base == 0) {
+ g_free (ret);
+ return NULL;
+ } else {
+ memcpy (ret, base, p - base);
+ ret[p - base] = '\0';
+ return ret;
+ }
+}
+
/* Note that we have these two separate functions with separate format
* strings for ease of localization.
*/
static char *
-get_link_name (const char *name, int count)
+get_link_name (const char *name, int count, int max_length)
{
const char *format;
char *result;
+ int unshortened_length;
+ gboolean use_count;
g_assert (name != NULL);
@@ -263,8 +303,8 @@ get_link_name (const char *name, int count)
format = _("Another link to %s");
break;
}
- result = g_strdup_printf (format, name);
+ use_count = FALSE;
} else {
/* Handle special cases for the first few numbers of each ten.
* For locales where getting this exactly right is difficult,
@@ -291,7 +331,30 @@ get_link_name (const char *name, int count)
format = _("%'dth link to %s");
break;
}
+
+ use_count = TRUE;
+ }
+
+ if (use_count)
result = g_strdup_printf (format, count, name);
+ else
+ result = g_strdup_printf (format, name);
+
+ if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
+ char *new_name;
+
+ new_name = shorten_utf8_string (name, unshortened_length - max_length);
+ if (new_name) {
+ g_free (result);
+
+ if (use_count)
+ result = g_strdup_printf (format, count, new_name);
+ else
+ result = g_strdup_printf (format, new_name);
+
+ g_assert (strlen (result) <= max_length);
+ g_free (new_name);
+ }
}
return result;
@@ -483,11 +546,12 @@ parse_previous_duplicate_name (const char *name,
}
static char *
-make_next_duplicate_name (const char *base, const char *suffix, int count)
+make_next_duplicate_name (const char *base, const char *suffix, int count, int max_length)
{
const char *format;
char *result;
-
+ int unshortened_length;
+ gboolean use_count;
if (count < 1) {
g_warning ("bad count %d in get_duplicate_name", count);
@@ -511,7 +575,8 @@ make_next_duplicate_name (const char *base, const char *suffix, int count)
break;
}
- result = g_strdup_printf (format, base, suffix);
+
+ use_count = FALSE;
} else {
/* Handle special cases for the first few numbers of each ten.
@@ -554,14 +619,37 @@ make_next_duplicate_name (const char *base, const char *suffix, int count)
}
}
+ use_count = TRUE;
+
+ }
+
+ if (use_count)
result = g_strdup_printf (format, base, count, suffix);
+ else
+ result = g_strdup_printf (format, base, suffix);
+
+ if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) {
+ char *new_base;
+
+ new_base = shorten_utf8_string (base, unshortened_length - max_length);
+ if (new_base) {
+ g_free (result);
+
+ if (use_count)
+ result = g_strdup_printf (format, new_base, count, suffix);
+ else
+ result = g_strdup_printf (format, new_base, suffix);
+
+ g_assert (strlen (result) <= max_length);
+ g_free (new_base);
+ }
}
return result;
}
static char *
-get_duplicate_name (const char *name, int count_increment)
+get_duplicate_name (const char *name, int count_increment, int max_length)
{
char *result;
char *name_base;
@@ -569,7 +657,7 @@ get_duplicate_name (const char *name, int count_increment)
int count;
parse_previous_duplicate_name (name, &name_base, &suffix, &count);
- result = make_next_duplicate_name (name_base, suffix, count + count_increment);
+ result = make_next_duplicate_name (name_base, suffix, count + count_increment, max_length);
g_free (name_base);
@@ -2636,6 +2724,45 @@ report_copy_progress (CopyMoveJob *copy_job,
nautilus_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size);
}
+static int
+get_max_name_length (GFile *file_dir)
+{
+ int max_length;
+ char *dir;
+ long max_path;
+ long max_name;
+
+ max_length = -1;
+
+ if (!g_file_has_uri_scheme (file_dir, "file"))
+ return max_length;
+
+ dir = g_file_get_path (file_dir);
+ if (!dir)
+ return max_length;
+
+ max_path = pathconf (dir, _PC_PATH_MAX);
+ max_name = pathconf (dir, _PC_NAME_MAX);
+
+ if (max_name == -1 && max_path == -1) {
+ max_length = -1;
+ } else if (max_name == -1 && max_path != -1) {
+ max_length = max_path - (strlen (dir) + 1);
+ } else if (max_name != -1 && max_path == -1) {
+ max_length = max_name;
+ } else {
+ int leftover;
+
+ leftover = max_path - (strlen (dir) + 1);
+
+ max_length = MIN (leftover, max_name);
+ }
+
+ g_free (dir);
+
+ return max_length;
+}
+
static GFile *
get_unique_target_file (GFile *src,
GFile *dest_dir,
@@ -2646,6 +2773,9 @@ get_unique_target_file (GFile *src,
char *basename, *new_name;
GFileInfo *info;
GFile *dest;
+ int max_length;
+
+ max_length = get_max_name_length (dest_dir);
dest = NULL;
info = g_file_query_info (src,
@@ -2655,7 +2785,7 @@ get_unique_target_file (GFile *src,
editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
if (editname != NULL) {
- new_name = get_duplicate_name (editname, count);
+ new_name = get_duplicate_name (editname, count, max_length);
dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
g_free (new_name);
}
@@ -2667,7 +2797,7 @@ get_unique_target_file (GFile *src,
basename = g_file_get_basename (src);
if (g_utf8_validate (basename, -1, NULL)) {
- new_name = get_duplicate_name (basename, count);
+ new_name = get_duplicate_name (basename, count, max_length);
dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
g_free (new_name);
}
@@ -2697,7 +2827,10 @@ get_target_file_for_link (GFile *src,
char *basename, *new_name;
GFileInfo *info;
GFile *dest;
-
+ int max_length;
+
+ max_length = get_max_name_length (dest_dir);
+
dest = NULL;
info = g_file_query_info (src,
G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME,
@@ -2706,7 +2839,7 @@ get_target_file_for_link (GFile *src,
editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME);
if (editname != NULL) {
- new_name = get_link_name (editname, count);
+ new_name = get_link_name (editname, count, max_length);
dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
g_free (new_name);
}
@@ -2718,7 +2851,7 @@ get_target_file_for_link (GFile *src,
basename = g_file_get_basename (src);
if (g_utf8_validate (basename, -1, NULL)) {
- new_name = get_link_name (basename, count);
+ new_name = get_link_name (basename, count, max_length);
dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL);
g_free (new_name);
}
@@ -5243,47 +5376,47 @@ nautilus_self_check_file_operations (void)
/* test the next duplicate name generator */
- EEL_CHECK_STRING_RESULT (get_duplicate_name (" (copy)", 1), " (another copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo", 1), "foo (copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name (".bashrc", 1), ".bashrc (copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name (".foo.txt", 1), ".foo (copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo", 1), "foo foo (copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo.txt", 1), "foo (copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt", 1), "foo foo (copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt txt", 1), "foo foo (copy).txt txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...txt", 1), "foo (copy)...txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...", 1), "foo (copy)...");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo. (copy)", 1), "foo. (another copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy)", 1), "foo (another copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy).txt", 1), "foo (another copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy)", 1), "foo (3rd copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy).txt", 1), "foo (3rd copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (another copy).txt", 1), "foo foo (3rd copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy)", 1), "foo (14th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy).txt", 1), "foo (14th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy)", 1), "foo (22nd copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy).txt", 1), "foo (22nd copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy)", 1), "foo (23rd copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy).txt", 1), "foo (23rd copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy)", 1), "foo (24th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy).txt", 1), "foo (24th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy)", 1), "foo (25th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy).txt", 1), "foo (25th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy)", 1), "foo foo (25th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy).txt", 1), "foo foo (25th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (100000000000000th copy).txt", 1), "foo foo (copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy)", 1), "foo (11th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy).txt", 1), "foo (11th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy)", 1), "foo (12th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy).txt", 1), "foo (12th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy)", 1), "foo (13th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy).txt", 1), "foo (13th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy)", 1), "foo (111th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy).txt", 1), "foo (111th copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy)", 1), "foo (123rd copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy).txt", 1), "foo (123rd copy).txt");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy)", 1), "foo (124th copy)");
- EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy).txt", 1), "foo (124th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name (" (copy)", 1, -1), " (another copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo", 1, -1), "foo (copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name (".bashrc", 1, -1), ".bashrc (copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name (".foo.txt", 1, -1), ".foo (copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo", 1, -1), "foo foo (copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo.txt", 1, -1), "foo (copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt", 1, -1), "foo foo (copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...txt", 1, -1), "foo (copy)...txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...", 1, -1), "foo (copy)...");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo. (copy)", 1, -1), "foo. (another copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy)", 1, -1), "foo (another copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy).txt", 1, -1), "foo (another copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy)", 1, -1), "foo (3rd copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy).txt", 1, -1), "foo (3rd copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy)", 1, -1), "foo (14th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy).txt", 1, -1), "foo (14th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy)", 1, -1), "foo (22nd copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy)", 1, -1), "foo (23rd copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy)", 1, -1), "foo (24th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy)", 1, -1), "foo (25th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy).txt", 1, -1), "foo (25th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy)", 1, -1), "foo foo (25th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy)", 1, -1), "foo (11th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy).txt", 1, -1), "foo (11th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy)", 1, -1), "foo (12th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy).txt", 1, -1), "foo (12th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy)", 1, -1), "foo (13th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy).txt", 1, -1), "foo (13th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy)", 1, -1), "foo (111th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy).txt", 1, -1), "foo (111th copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy)", 1, -1), "foo (123rd copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy)", 1, -1), "foo (124th copy)");
+ EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt");
setlocale (LC_MESSAGES, "");
}