- char *dir;
- char *base_versions;
- int highest_backup;
-
- if (backup_type == simple)
- return concat (file, simple_backup_suffix);
- base_versions = concat (basename (file), ".~");
- if (base_versions == 0)
- return 0;
- dir = dirname (file);
- if (dir == 0)
+ char *base = base_name (file);
+ size_t baselen = base_len (base);
+ size_t baselen_max = HAVE_LONG_FILE_NAMES ? 255 : NAME_MAX_MINIMUM;
+
+ if (HAVE_DOS_FILE_NAMES || NAME_MAX_MINIMUM < baselen)
+ {
+ /* The new base name is long enough to require a pathconf check. */
+ long name_max;
+
+ /* Temporarily modify the buffer into its parent directory name,
+ invoke pathconf on the directory, and then restore the buffer. */
+ char tmp[sizeof "."];
+ memcpy (tmp, base, sizeof ".");
+ strcpy (base, ".");
+ errno = 0;
+ name_max = pathconf (file, _PC_NAME_MAX);
+ if (0 <= name_max || errno == 0)
+ {
+ long size = baselen_max = name_max;
+ if (name_max != size)
+ baselen_max = SIZE_MAX;
+ }
+ memcpy (base, tmp, sizeof ".");
+ }
+
+ if (HAVE_DOS_FILE_NAMES && baselen_max <= 12)
+ {
+ /* Live within DOS's 8.3 limit. */
+ char *dot = strchr (base, '.');
+ if (!dot)
+ baselen_max = 8;
+ else
+ {
+ char const *second_dot = strchr (dot + 1, '.');
+ baselen_max = (second_dot
+ ? second_dot - base
+ : dot + 1 - base + 3);
+ }
+ }
+
+ if (baselen_max < baselen)