- /* Do tilde expansion. */
- if (ds_first (&dir) == '~')
- {
- char *tmp_str = fn_tilde_expand (ds_c_str (&dir));
- ds_assign_c_str (&dir, tmp_str);
- free (tmp_str);
- }
-
- /* Construct file name. */
- ds_clear (&file);
- if (prefix != NULL && !fn_is_absolute (ds_c_str (&dir)))
- {
- ds_puts (&file, prefix);
- ds_putc (&file, '/');
- }
- ds_puts (&file, ds_c_str (&dir));
- if (ds_length (&dir) && ds_last (&file) != '/')
- ds_putc (&file, '/');
- ds_puts (&file, base_name);
-
- /* Check whether file exists. */
- if (fn_exists (ds_c_str (&file)))
- {
- verbose_msg (2, _("...found \"%s\""), ds_c_str (&file));
- ds_destroy (&path);
- ds_destroy (&dir);
- return ds_c_str (&file);
- }
- }
-
- /* Failure. */
- verbose_msg (2, _("...not found"));
- ds_destroy (&path);
- ds_destroy (&dir);
- ds_destroy (&file);
- return NULL;
-}
-
-/* fn_normalize(): This very OS-dependent routine canonicalizes
- file name FN1. The file name should not need to be the name of an
- existing file. Returns a malloc()'d copy of the canonical name.
- This function must always succeed; if it needs to bail out then it
- should return xstrdup(FN1). */
-#ifdef unix
-char *
-fn_normalize (const char *file_name)
-{
- const char *src;
- char *fn1, *fn2, *dest;
- int maxlen;
-
- if (fn_is_special (file_name))
- return xstrdup (file_name);
-
- fn1 = fn_tilde_expand (file_name);
-
- /* Follow symbolic links. */
- for (;;)
- {
- fn2 = fn1;
- fn1 = fn_readlink (fn1);
- if (!fn1)
- {
- fn1 = fn2;
- break;
- }
- free (fn2);
- }
-
- maxlen = strlen (fn1) * 2;
- if (maxlen < 31)
- maxlen = 31;
- dest = fn2 = xmalloc (maxlen + 1);
- src = fn1;
-
- if (*src == '/')
- *dest++ = *src++;
- else
- {
- errno = 0;
- while (getcwd (dest, maxlen - (dest - fn2)) == NULL && errno == ERANGE)
- {
- maxlen *= 2;
- dest = fn2 = xrealloc (fn2, maxlen + 1);
- errno = 0;
- }
- if (errno)
- {
- free (fn1);
- free (fn2);
- return NULL;
- }
- dest = strchr (fn2, '\0');
- if (dest - fn2 >= maxlen)
- {
- int ofs = dest - fn2;
- maxlen *= 2;
- fn2 = xrealloc (fn2, maxlen + 1);
- dest = fn2 + ofs;
- }
- if (dest[-1] != '/')
- *dest++ = '/';
- }
-
- for (;;)
- {
- int c, f;
-
- c = *src++;