Commit 4269f19c by Janne Blomqvist

PR 60324 Handle long path names, don't use PATH_MAX.

From-SVN: r210738
parent d5c67efd
2014-05-22 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/60324
* config.h.in: Regenerated.
* configure: Regenerated.
* configure.ac (AC_CHECK_FUNCS_ONCE): Check for strnlen and
strndup.
* libgfortran.h (fc_strdup): New prototype.
* runtime/string.c (strnlen): New fallback function.
(strndup): New fallback function.
(fc_strdup): New function.
* io/close.c (st_close): Use fc_strdup.
* io/open.c (new_unit): Likewise.
(already_open): Likewise.
* io/unit.c (filename_from_unit): Likewise.
* io/unix.c (unpack_filename): Remove function.
(regular_file): Rename to regular_file2, add path argument.
(regular_file): New function calling regular_file2.
(compare_file_filename): Use fc_strdup.
(find_file): Likewise.
(delete_file): Likewise.
(file_exists): Likewise.
(file_size): Likewise.
(inquire_sequential): Likewise.
(inquire_direct): Likewise.
(inquire_formatted): Likewise.
(inquire_access): Likewise.
* io/unix.h (unpack_filename): Remove prototype.
* runtime/main.c (please_free_exe_path_when_done): Change type to
bool.
(store_exe_path): Use malloced buffer, grow as needed.
2014-05-17 Jerry DeLisle <jvdelisle@gcc.gnu> 2014-05-17 Jerry DeLisle <jvdelisle@gcc.gnu>
PR libfortran/52539 PR libfortran/52539
......
...@@ -729,6 +729,12 @@ ...@@ -729,6 +729,12 @@
/* Define to 1 if you have the <string.h> header file. */ /* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H #undef HAVE_STRING_H
/* Define to 1 if you have the `strndup' function. */
#undef HAVE_STRNDUP
/* Define to 1 if you have the `strnlen' function. */
#undef HAVE_STRNLEN
/* Define to 1 if you have the `strtof' function. */ /* Define to 1 if you have the `strtof' function. */
#undef HAVE_STRTOF #undef HAVE_STRTOF
......
...@@ -2599,6 +2599,8 @@ as_fn_append ac_func_list " getegid" ...@@ -2599,6 +2599,8 @@ as_fn_append ac_func_list " getegid"
as_fn_append ac_func_list " secure_getenv" as_fn_append ac_func_list " secure_getenv"
as_fn_append ac_func_list " __secure_getenv" as_fn_append ac_func_list " __secure_getenv"
as_fn_append ac_func_list " mkostemp" as_fn_append ac_func_list " mkostemp"
as_fn_append ac_func_list " strnlen"
as_fn_append ac_func_list " strndup"
as_fn_append ac_header_list " math.h" as_fn_append ac_header_list " math.h"
# Check that the precious variables saved in the cache have kept the same # Check that the precious variables saved in the cache have kept the same
# value. # value.
...@@ -12344,7 +12346,7 @@ else ...@@ -12344,7 +12346,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 12347 "configure" #line 12349 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -12450,7 +12452,7 @@ else ...@@ -12450,7 +12452,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 12453 "configure" #line 12455 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -16606,6 +16608,10 @@ done ...@@ -16606,6 +16608,10 @@ done
fi fi
# Check strerror_r, cannot be above as versions with two and three arguments exist # Check strerror_r, cannot be above as versions with two and three arguments exist
......
...@@ -287,7 +287,7 @@ else ...@@ -287,7 +287,7 @@ else
strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \ strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \
getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \ getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \
readlink getgid getpid getppid getuid geteuid umask getegid \ readlink getgid getpid getppid getuid geteuid umask getegid \
secure_getenv __secure_getenv mkostemp) secure_getenv __secure_getenv mkostemp strnlen strndup)
fi fi
# Check strerror_r, cannot be above as versions with two and three arguments exist # Check strerror_r, cannot be above as versions with two and three arguments exist
......
...@@ -72,8 +72,7 @@ st_close (st_parameter_close *clp) ...@@ -72,8 +72,7 @@ st_close (st_parameter_close *clp)
generate_error (&clp->common, LIBERROR_BAD_OPTION, generate_error (&clp->common, LIBERROR_BAD_OPTION,
"Can't KEEP a scratch file on CLOSE"); "Can't KEEP a scratch file on CLOSE");
#if !HAVE_UNLINK_OPEN_FILE #if !HAVE_UNLINK_OPEN_FILE
path = (char *) gfc_alloca (u->file_len + 1); path = fc_strdup (u->file, u->file_len);
unpack_filename (path, u->file, u->file_len);
#endif #endif
} }
else else
...@@ -83,8 +82,7 @@ st_close (st_parameter_close *clp) ...@@ -83,8 +82,7 @@ st_close (st_parameter_close *clp)
#if HAVE_UNLINK_OPEN_FILE #if HAVE_UNLINK_OPEN_FILE
delete_file (u); delete_file (u);
#else #else
path = (char *) gfc_alloca (u->file_len + 1); path = fc_strdup (u->file, u->file_len);
unpack_filename (path, u->file, u->file_len);
#endif #endif
} }
} }
...@@ -93,7 +91,10 @@ st_close (st_parameter_close *clp) ...@@ -93,7 +91,10 @@ st_close (st_parameter_close *clp)
#if !HAVE_UNLINK_OPEN_FILE #if !HAVE_UNLINK_OPEN_FILE
if (path != NULL) if (path != NULL)
unlink (path); {
unlink (path);
free (path);
}
#endif #endif
} }
......
...@@ -502,12 +502,9 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags) ...@@ -502,12 +502,9 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
s = open_external (opp, flags); s = open_external (opp, flags);
if (s == NULL) if (s == NULL)
{ {
char *path, *msg; char *path = fc_strdup (opp->file, opp->file_len);
size_t msglen; size_t msglen = opp->file_len + 51;
path = (char *) gfc_alloca (opp->file_len + 1); char *msg = xmalloc (msglen);
msglen = opp->file_len + 51;
msg = (char *) gfc_alloca (msglen);
unpack_filename (path, opp->file, opp->file_len);
switch (errno) switch (errno)
{ {
...@@ -529,10 +526,13 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags) ...@@ -529,10 +526,13 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
break; break;
default: default:
free (msg);
msg = NULL; msg = NULL;
} }
generate_error (&opp->common, LIBERROR_OS, msg); generate_error (&opp->common, LIBERROR_OS, msg);
free (msg);
free (path);
goto cleanup; goto cleanup;
} }
...@@ -676,15 +676,6 @@ already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags) ...@@ -676,15 +676,6 @@ already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
if (!compare_file_filename (u, opp->file, opp->file_len)) if (!compare_file_filename (u, opp->file, opp->file_len))
{ {
#if !HAVE_UNLINK_OPEN_FILE
char *path = NULL;
if (u->file && u->flags.status == STATUS_SCRATCH)
{
path = (char *) gfc_alloca (u->file_len + 1);
unpack_filename (path, u->file, u->file_len);
}
#endif
if (sclose (u->s) == -1) if (sclose (u->s) == -1)
{ {
unlock_unit (u); unlock_unit (u);
...@@ -699,8 +690,14 @@ already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags) ...@@ -699,8 +690,14 @@ already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
u->file_len = 0; u->file_len = 0;
#if !HAVE_UNLINK_OPEN_FILE #if !HAVE_UNLINK_OPEN_FILE
char *path = NULL;
if (u->file && u->flags.status == STATUS_SCRATCH)
path = fc_strdup (u->file, u->file_len);
if (path != NULL) if (path != NULL)
unlink (path); {
unlink (path);
free (path);
}
#endif #endif
u = new_unit (opp, u, flags); u = new_unit (opp, u, flags);
......
...@@ -786,7 +786,6 @@ unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common) ...@@ -786,7 +786,6 @@ unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
char * char *
filename_from_unit (int n) filename_from_unit (int n)
{ {
char *filename;
gfc_unit *u; gfc_unit *u;
int c; int c;
...@@ -805,11 +804,7 @@ filename_from_unit (int n) ...@@ -805,11 +804,7 @@ filename_from_unit (int n)
/* Get the filename. */ /* Get the filename. */
if (u != NULL) if (u != NULL)
{ return fc_strdup (u->file, u->file_len);
filename = (char *) xmalloc (u->file_len + 1);
unpack_filename (filename, u->file, u->file_len);
return filename;
}
else else
return (char *) NULL; return (char *) NULL;
} }
......
...@@ -114,9 +114,6 @@ id_from_fd (const int fd) ...@@ -114,9 +114,6 @@ id_from_fd (const int fd)
typeof (b) _b = (b); \ typeof (b) _b = (b); \
_a < _b ? _a : _b; }) _a < _b ? _a : _b; })
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
/* These flags aren't defined on all targets (mingw32), so provide them /* These flags aren't defined on all targets (mingw32), so provide them
here. */ here. */
...@@ -1060,26 +1057,6 @@ unit_to_fd (int unit) ...@@ -1060,26 +1057,6 @@ unit_to_fd (int unit)
} }
/* unpack_filename()-- Given a fortran string and a pointer to a
* buffer that is PATH_MAX characters, convert the fortran string to a
* C string in the buffer. Returns nonzero if this is not possible. */
int
unpack_filename (char *cstring, const char *fstring, int len)
{
if (fstring == NULL)
return EFAULT;
len = fstrlen (fstring, len);
if (len >= PATH_MAX)
return ENAMETOOLONG;
memmove (cstring, fstring, len);
cstring[len] = '\0';
return 0;
}
/* Set the close-on-exec flag for an existing fd, if the system /* Set the close-on-exec flag for an existing fd, if the system
supports such. */ supports such. */
...@@ -1244,27 +1221,18 @@ tempfile (st_parameter_open *opp) ...@@ -1244,27 +1221,18 @@ tempfile (st_parameter_open *opp)
} }
/* regular_file()-- Open a regular file. /* regular_file2()-- Open a regular file.
* Change flags->action if it is ACTION_UNSPECIFIED on entry, * Change flags->action if it is ACTION_UNSPECIFIED on entry,
* unless an error occurs. * unless an error occurs.
* Returns the descriptor, which is less than zero on error. */ * Returns the descriptor, which is less than zero on error. */
static int static int
regular_file (st_parameter_open *opp, unit_flags *flags) regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
{ {
char path[min(PATH_MAX, opp->file_len + 1)];
int mode; int mode;
int rwflag; int rwflag;
int crflag, crflag2; int crflag, crflag2;
int fd; int fd;
int err;
err = unpack_filename (path, opp->file, opp->file_len);
if (err)
{
errno = err; /* Fake an OS error */
return -1;
}
#ifdef __CYGWIN__ #ifdef __CYGWIN__
if (opp->file_len == 7) if (opp->file_len == 7)
...@@ -1404,6 +1372,18 @@ regular_file (st_parameter_open *opp, unit_flags *flags) ...@@ -1404,6 +1372,18 @@ regular_file (st_parameter_open *opp, unit_flags *flags)
} }
/* Wrapper around regular_file2, to make sure we free the path after
we're done. */
static int
regular_file (st_parameter_open *opp, unit_flags *flags)
{
char *path = fc_strdup (opp->file, opp->file_len);
int fd = regular_file2 (path, opp, flags);
free (path);
return fd;
}
/* open_external()-- Open an external file, unix specific version. /* open_external()-- Open an external file, unix specific version.
* Change flags->action if it is ACTION_UNSPECIFIED on entry. * Change flags->action if it is ACTION_UNSPECIFIED on entry.
* Returns NULL on operating system error. */ * Returns NULL on operating system error. */
...@@ -1494,8 +1474,8 @@ error_stream (void) ...@@ -1494,8 +1474,8 @@ error_stream (void)
int int
compare_file_filename (gfc_unit *u, const char *name, int len) compare_file_filename (gfc_unit *u, const char *name, int len)
{ {
char path[min(PATH_MAX, len + 1)];
struct stat st; struct stat st;
int ret;
#ifdef HAVE_WORKING_STAT #ifdef HAVE_WORKING_STAT
unix_stream *s; unix_stream *s;
#else #else
...@@ -1504,18 +1484,21 @@ compare_file_filename (gfc_unit *u, const char *name, int len) ...@@ -1504,18 +1484,21 @@ compare_file_filename (gfc_unit *u, const char *name, int len)
# endif # endif
#endif #endif
if (unpack_filename (path, name, len)) char *path = fc_strdup (name, len);
return 0; /* Can't be the same */
/* If the filename doesn't exist, then there is no match with the /* If the filename doesn't exist, then there is no match with the
* existing file. */ * existing file. */
if (stat (path, &st) < 0) if (stat (path, &st) < 0)
return 0; {
ret = 0;
goto done;
}
#ifdef HAVE_WORKING_STAT #ifdef HAVE_WORKING_STAT
s = (unix_stream *) (u->s); s = (unix_stream *) (u->s);
return (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino); ret = (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
goto done;
#else #else
# ifdef __MINGW32__ # ifdef __MINGW32__
...@@ -1525,13 +1508,20 @@ compare_file_filename (gfc_unit *u, const char *name, int len) ...@@ -1525,13 +1508,20 @@ compare_file_filename (gfc_unit *u, const char *name, int len)
id1 = id_from_path (path); id1 = id_from_path (path);
id2 = id_from_fd (((unix_stream *) (u->s))->fd); id2 = id_from_fd (((unix_stream *) (u->s))->fd);
if (id1 || id2) if (id1 || id2)
return (id1 == id2); {
ret = (id1 == id2);
goto done;
}
# endif # endif
if (len != u->file_len) if (len != u->file_len)
return 0; ret = 0;
return (memcmp(path, u->file, len) == 0); else
ret = (memcmp(path, u->file, len) == 0);
#endif #endif
done:
free (path);
return ret;
} }
...@@ -1594,18 +1584,19 @@ find_file0 (gfc_unit *u, FIND_FILE0_DECL) ...@@ -1594,18 +1584,19 @@ find_file0 (gfc_unit *u, FIND_FILE0_DECL)
gfc_unit * gfc_unit *
find_file (const char *file, gfc_charlen_type file_len) find_file (const char *file, gfc_charlen_type file_len)
{ {
char path[min(PATH_MAX, file_len + 1)];
struct stat st[1]; struct stat st[1];
gfc_unit *u; gfc_unit *u;
#if defined(__MINGW32__) && !HAVE_WORKING_STAT #if defined(__MINGW32__) && !HAVE_WORKING_STAT
uint64_t id = 0ULL; uint64_t id = 0ULL;
#endif #endif
if (unpack_filename (path, file, file_len)) char *path = fc_strdup (file, file_len);
return NULL;
if (stat (path, &st[0]) < 0) if (stat (path, &st[0]) < 0)
return NULL; {
u = NULL;
goto done;
}
#if defined(__MINGW32__) && !HAVE_WORKING_STAT #if defined(__MINGW32__) && !HAVE_WORKING_STAT
id = id_from_path (path); id = id_from_path (path);
...@@ -1621,7 +1612,7 @@ retry: ...@@ -1621,7 +1612,7 @@ retry:
{ {
/* assert (u->closed == 0); */ /* assert (u->closed == 0); */
__gthread_mutex_unlock (&unit_lock); __gthread_mutex_unlock (&unit_lock);
return u; goto done;
} }
inc_waiting_locked (u); inc_waiting_locked (u);
...@@ -1641,6 +1632,8 @@ retry: ...@@ -1641,6 +1632,8 @@ retry:
dec_waiting_unlocked (u); dec_waiting_unlocked (u);
} }
done:
free (path);
return u; return u;
} }
...@@ -1713,16 +1706,10 @@ flush_all_units (void) ...@@ -1713,16 +1706,10 @@ flush_all_units (void)
int int
delete_file (gfc_unit * u) delete_file (gfc_unit * u)
{ {
char path[min(PATH_MAX, u->file_len + 1)]; char *path = fc_strdup (u->file, u->file_len);
int err = unpack_filename (path, u->file, u->file_len); int err = unlink (path);
free (path);
if (err) return err;
{ /* Shouldn't be possible */
errno = err;
return 1;
}
return unlink (path);
} }
...@@ -1732,12 +1719,10 @@ delete_file (gfc_unit * u) ...@@ -1732,12 +1719,10 @@ delete_file (gfc_unit * u)
int int
file_exists (const char *file, gfc_charlen_type file_len) file_exists (const char *file, gfc_charlen_type file_len)
{ {
char path[min(PATH_MAX, file_len + 1)]; char *path = fc_strdup (file, file_len);
int res = !(access (path, F_OK));
if (unpack_filename (path, file, file_len)) free (path);
return 0; return res;
return !(access (path, F_OK));
} }
...@@ -1746,15 +1731,12 @@ file_exists (const char *file, gfc_charlen_type file_len) ...@@ -1746,15 +1731,12 @@ file_exists (const char *file, gfc_charlen_type file_len)
GFC_IO_INT GFC_IO_INT
file_size (const char *file, gfc_charlen_type file_len) file_size (const char *file, gfc_charlen_type file_len)
{ {
char path[min(PATH_MAX, file_len + 1)]; char *path = fc_strdup (file, file_len);
struct stat statbuf; struct stat statbuf;
int err = stat (path, &statbuf);
if (unpack_filename (path, file, file_len)) free (path);
return -1; if (err == -1)
if (stat (path, &statbuf) < 0)
return -1; return -1;
return (GFC_IO_INT) statbuf.st_size; return (GFC_IO_INT) statbuf.st_size;
} }
...@@ -1767,11 +1749,15 @@ static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN"; ...@@ -1767,11 +1749,15 @@ static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
const char * const char *
inquire_sequential (const char *string, int len) inquire_sequential (const char *string, int len)
{ {
char path[min(PATH_MAX, len + 1)];
struct stat statbuf; struct stat statbuf;
if (string == NULL || if (string == NULL)
unpack_filename (path, string, len) || stat (path, &statbuf) < 0) return unknown;
char *path = fc_strdup (string, len);
int err = stat (path, &statbuf);
free (path);
if (err == -1)
return unknown; return unknown;
if (S_ISREG (statbuf.st_mode) || if (S_ISREG (statbuf.st_mode) ||
...@@ -1791,11 +1777,15 @@ inquire_sequential (const char *string, int len) ...@@ -1791,11 +1777,15 @@ inquire_sequential (const char *string, int len)
const char * const char *
inquire_direct (const char *string, int len) inquire_direct (const char *string, int len)
{ {
char path[min(PATH_MAX, len + 1)];
struct stat statbuf; struct stat statbuf;
if (string == NULL || if (string == NULL)
unpack_filename (path, string, len) || stat (path, &statbuf) < 0) return unknown;
char *path = fc_strdup (string, len);
int err = stat (path, &statbuf);
free (path);
if (err == -1)
return unknown; return unknown;
if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode)) if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
...@@ -1815,11 +1805,15 @@ inquire_direct (const char *string, int len) ...@@ -1815,11 +1805,15 @@ inquire_direct (const char *string, int len)
const char * const char *
inquire_formatted (const char *string, int len) inquire_formatted (const char *string, int len)
{ {
char path[min(PATH_MAX, len + 1)];
struct stat statbuf; struct stat statbuf;
if (string == NULL || if (string == NULL)
unpack_filename (path, string, len) || stat (path, &statbuf) < 0) return unknown;
char *path = fc_strdup (string, len);
int err = stat (path, &statbuf);
free (path);
if (err == -1)
return unknown; return unknown;
if (S_ISREG (statbuf.st_mode) || if (S_ISREG (statbuf.st_mode) ||
...@@ -1850,10 +1844,12 @@ inquire_unformatted (const char *string, int len) ...@@ -1850,10 +1844,12 @@ inquire_unformatted (const char *string, int len)
static const char * static const char *
inquire_access (const char *string, int len, int mode) inquire_access (const char *string, int len, int mode)
{ {
char path[min(PATH_MAX, len + 1)]; if (string == NULL)
return no;
if (string == NULL || unpack_filename (path, string, len) || char *path = fc_strdup (string, len);
access (path, mode) < 0) int res = access (path, mode);
free (path);
if (res == -1)
return no; return no;
return yes; return yes;
......
...@@ -185,8 +185,4 @@ internal_proto(stream_isatty); ...@@ -185,8 +185,4 @@ internal_proto(stream_isatty);
extern int stream_ttyname (stream *, char *, size_t); extern int stream_ttyname (stream *, char *, size_t);
internal_proto(stream_ttyname); internal_proto(stream_ttyname);
extern int unpack_filename (char *, const char *, int);
internal_proto(unpack_filename);
#endif #endif
...@@ -822,6 +822,9 @@ extern gfc_charlen_type string_len_trim_char4 (gfc_charlen_type, ...@@ -822,6 +822,9 @@ extern gfc_charlen_type string_len_trim_char4 (gfc_charlen_type,
const gfc_char4_t *); const gfc_char4_t *);
export_proto(string_len_trim_char4); export_proto(string_len_trim_char4);
extern char *fc_strdup(const char *, gfc_charlen_type);
internal_proto(fc_strdup);
/* io/intrinsics.c */ /* io/intrinsics.c */
extern void flush_all_units (void); extern void flush_all_units (void);
......
...@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
...@@ -70,23 +71,18 @@ static int argc_save; ...@@ -70,23 +71,18 @@ static int argc_save;
static char **argv_save; static char **argv_save;
static const char *exe_path; static const char *exe_path;
static int please_free_exe_path_when_done; static bool please_free_exe_path_when_done;
/* Save the path under which the program was called, for use in the /* Save the path under which the program was called, for use in the
backtrace routines. */ backtrace routines. */
void void
store_exe_path (const char * argv0) store_exe_path (const char * argv0)
{ {
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#ifndef DIR_SEPARATOR #ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '/' #define DIR_SEPARATOR '/'
#endif #endif
char buf[PATH_MAX], *path; char *cwd, *path;
const char *cwd;
/* This can only happen if store_exe_path is called multiple times. */ /* This can only happen if store_exe_path is called multiple times. */
if (please_free_exe_path_when_done) if (please_free_exe_path_when_done)
...@@ -95,13 +91,27 @@ store_exe_path (const char * argv0) ...@@ -95,13 +91,27 @@ store_exe_path (const char * argv0)
/* Reading the /proc/self/exe symlink is Linux-specific(?), but if /* Reading the /proc/self/exe symlink is Linux-specific(?), but if
it works it gives the correct answer. */ it works it gives the correct answer. */
#ifdef HAVE_READLINK #ifdef HAVE_READLINK
int len; ssize_t len, psize = 256;
if ((len = readlink ("/proc/self/exe", buf, sizeof (buf) - 1)) != -1) while (1)
{ {
buf[len] = '\0'; path = xmalloc (psize);
exe_path = strdup (buf); len = readlink ("/proc/self/exe", path, psize);
please_free_exe_path_when_done = 1; if (len < 0)
return; {
free (path);
break;
}
else if (len < psize)
{
path[len] = '\0';
exe_path = strdup (path);
free (path);
please_free_exe_path_when_done = true;
return;
}
/* The remaining option is len == psize. */
free (path);
psize *= 4;
} }
#endif #endif
...@@ -117,12 +127,29 @@ store_exe_path (const char * argv0) ...@@ -117,12 +127,29 @@ store_exe_path (const char * argv0)
#endif #endif
{ {
exe_path = argv0; exe_path = argv0;
please_free_exe_path_when_done = 0; please_free_exe_path_when_done = false;
return; return;
} }
#ifdef HAVE_GETCWD #ifdef HAVE_GETCWD
cwd = getcwd (buf, sizeof (buf)); size_t cwdsize = 256;
while (1)
{
cwd = xmalloc (cwdsize);
if (getcwd (cwd, cwdsize))
break;
else if (errno == ERANGE)
{
free (cwd);
cwdsize *= 4;
}
else
{
free (cwd);
cwd = NULL;
break;
}
}
#else #else
cwd = NULL; cwd = NULL;
#endif #endif
...@@ -130,7 +157,7 @@ store_exe_path (const char * argv0) ...@@ -130,7 +157,7 @@ store_exe_path (const char * argv0)
if (!cwd) if (!cwd)
{ {
exe_path = argv0; exe_path = argv0;
please_free_exe_path_when_done = 0; please_free_exe_path_when_done = false;
return; return;
} }
...@@ -138,10 +165,11 @@ store_exe_path (const char * argv0) ...@@ -138,10 +165,11 @@ store_exe_path (const char * argv0)
if the executable is not in the cwd, but at this point we're out if the executable is not in the cwd, but at this point we're out
of better ideas. */ of better ideas. */
size_t pathlen = strlen (cwd) + 1 + strlen (argv0) + 1; size_t pathlen = strlen (cwd) + 1 + strlen (argv0) + 1;
path = malloc (pathlen); path = xmalloc (pathlen);
snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0); snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0);
free (cwd);
exe_path = path; exe_path = path;
please_free_exe_path_when_done = 1; please_free_exe_path_when_done = true;
} }
......
...@@ -90,6 +90,49 @@ cf_strcpy (char *dest, gfc_charlen_type dest_len, const char *src) ...@@ -90,6 +90,49 @@ cf_strcpy (char *dest, gfc_charlen_type dest_len, const char *src)
} }
#ifndef HAVE_STRNLEN
static size_t
strnlen (const char *s, size_t maxlen)
{
for (size_t ii = 0; ii < maxlen; ii++)
{
if (s[ii] == '\0')
return ii;
}
return maxlen;
}
#endif
#ifndef HAVE_STRNDUP
static char *
strndup (const char *s, size_t n)
{
size_t len = strnlen (s, n);
char *p = malloc (len + 1);
if (!p)
return NULL;
memcpy (p, s, len);
p[len] = '\0';
return p;
}
#endif
/* Duplicate a non-null-terminated Fortran string to a malloced
null-terminated C string. */
char *
fc_strdup (const char *src, gfc_charlen_type src_len)
{
gfc_charlen_type n = fstrlen (src, src_len);
char *p = strndup (src, n);
if (!p)
os_error ("Memory allocation failed in fc_strdup");
return p;
}
/* Given a fortran string and an array of st_option structures, search through /* Given a fortran string and an array of st_option structures, search through
the array to find a match. If the option is not found, we generate an error the array to find a match. If the option is not found, we generate an error
if no default is provided. */ if no default is provided. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment