Had to get last call to multipass_split_output() inside
[pspp-builds.git] / src / filename.c
index 458b1c4102d93e048b1dbd9832cc4d07f7d63271..a52414613b11c7915d7030d6bd103af212b1aeb3 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA. */
 
-/* AIX requires this to be the first thing in the file.  */
 #include <config.h>
-#if __GNUC__
-#define alloca __builtin_alloca
-#else
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else
-#ifdef _AIX
-#pragma alloca
-#else
-#ifndef alloca                 /* predefined by HP cc +Olibcalls */
-char *alloca ();
-#endif
-#endif
-#endif
-#endif
-
-#include <assert.h>
+#include "error.h"
 #include "filename.h"
 #include <stdlib.h>
 #include <ctype.h>
@@ -50,7 +33,7 @@ char *alloca ();
 
 /* PORTME: Everything in this file is system dependent. */
 
-#if unix
+#ifdef unix
 #include <pwd.h>
 #if HAVE_UNISTD_H
 #include <unistd.h>
@@ -58,7 +41,7 @@ char *alloca ();
 #include "stat.h"
 #endif
 
-#if __WIN32__
+#ifdef __WIN32__
 #define NOGDI
 #define NOUSER
 #define NONLS
@@ -146,7 +129,7 @@ fn_interp_vars (const char *input, const char *(*getenv) (const char *))
       }
 }
 
-#if unix
+#ifdef unix
 /* Expands csh tilde notation from the path INPUT into a malloc()'d
    returned string. */
 char *
@@ -218,7 +201,7 @@ fn_tilde_expand (char *input)
    If PREPEND is non-NULL, then it is prepended to each filename;
    i.e., it looks like PREPEND/PATH_COMPONENT/NAME.  This is not done
    with absolute directories in the path. */
-#if unix || __MSDOS__ || __WIN32__
+#if defined (unix) || defined (__MSDOS__) || defined (__WIN32__)
 char *
 fn_search_path (const char *basename, const char *path, const char *prepend)
 {
@@ -334,7 +317,7 @@ fn_prepend_dir (const char *file, const char *dir)
    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).  */
-#if unix
+#ifdef unix
 char *
 fn_normalize (const char *filename)
 {
@@ -444,7 +427,7 @@ fn_normalize (const char *filename)
        }
     }
 }
-#elif __WIN32__
+#elif defined (__WIN32__)
 char *
 fn_normalize (const char *fn1)
 {
@@ -568,13 +551,13 @@ fn_get_cwd (void)
 int
 fn_absolute_p (const char *name)
 {
-#if unix
+#ifdef unix
   if (name[0] == '/'
       || !strncmp (name, "./", 2)
       || !strncmp (name, "../", 3)
       || name[0] == '~')
     return 1;
-#elif __MSDOS__
+#elif defined (__MSDOS__)
   if (name[0] == '\\'
       || !strncmp (name, ".\\", 2)
       || !strncmp (name, "..\\", 3)
@@ -592,7 +575,7 @@ fn_special_p (const char *filename)
 {
   if (!strcmp (filename, "-") || !strcmp (filename, "stdin")
       || !strcmp (filename, "stdout") || !strcmp (filename, "stderr")
-#if unix
+#ifdef unix
       || filename[0] == '|'
       || (*filename && filename[strlen (filename) - 1] == '|')
 #endif
@@ -606,7 +589,7 @@ fn_special_p (const char *filename)
 int
 fn_exists_p (const char *name)
 {
-#if unix
+#ifdef unix
   struct stat temp;
 
   return stat (name, &temp) == 0;
@@ -619,7 +602,7 @@ fn_exists_p (const char *name)
 #endif
 }
 
-#if unix
+#ifdef unix
 /* Stolen from libc.info but heavily modified, this is a wrapper
    around readlink() that allows for arbitrary filename length. */
 char *
@@ -709,10 +692,10 @@ fn_open (const char *fn, const char *mode)
   else if (mode[0] == 'w' && !strcmp (fn, "stderr"))
     return stderr;
   
-#if unix
+#ifdef unix
   if (fn[0] == '|')
     {
-      if (set_safer)
+      if (safer_mode())
        return safety_violation (fn);
 
       return popen (&fn[1], mode);
@@ -722,7 +705,7 @@ fn_open (const char *fn, const char *mode)
       char *s;
       FILE *f;
 
-      if (set_safer)
+      if (safer_mode())
        return safety_violation (fn);
       
       s = local_alloc (strlen (fn));
@@ -755,7 +738,7 @@ fn_close (const char *fn, FILE *f)
 {
   if (!strcmp (fn, "-"))
     return 0;
-#if unix
+#ifdef unix
   else if (fn[0] == '|' || (*fn && fn[strlen (fn) - 1] == '|'))
     {
       pclose (f);
@@ -871,3 +854,93 @@ fn_close_ext (struct file_ext *f)
     }
   return 1;
 }
+
+#ifdef unix
+/* A file's identity. */
+struct file_identity 
+  {
+    dev_t device;               /* Device number. */
+    ino_t inode;                /* Inode number. */
+  };
+
+/* Returns a pointer to a dynamically allocated structure whose
+   value can be used to tell whether two files are actually the
+   same file.  Returns a null pointer if no information about the
+   file is available, perhaps because it does not exist.  The
+   caller is responsible for freeing the structure with
+   fn_free_identity() when finished. */  
+struct file_identity *
+fn_get_identity (const char *filename) 
+{
+  struct stat s;
+
+  if (stat (filename, &s) == 0) 
+    {
+      struct file_identity *identity = xmalloc (sizeof *identity);
+      identity->device = s.st_dev;
+      identity->inode = s.st_ino;
+      return identity;
+    }
+  else
+    return NULL;
+}
+
+/* Frees IDENTITY obtained from fn_get_identity(). */
+void
+fn_free_identity (struct file_identity *identity) 
+{
+  free (identity);
+}
+
+/* Compares A and B, returning a strcmp()-type result. */
+int
+fn_compare_file_identities (const struct file_identity *a,
+                            const struct file_identity *b) 
+{
+  assert (a != NULL);
+  assert (b != NULL);
+  if (a->device != b->device)
+    return a->device < b->device ? -1 : 1;
+  else
+    return a->inode < b->inode ? -1 : a->inode > b->inode;
+}
+#else /* not unix */
+/* A file's identity. */
+struct file_identity 
+  {
+    char *normalized_filename;  /* File's normalized name. */
+  };
+
+/* Returns a pointer to a dynamically allocated structure whose
+   value can be used to tell whether two files are actually the
+   same file.  Returns a null pointer if no information about the
+   file is available, perhaps because it does not exist.  The
+   caller is responsible for freeing the structure with
+   fn_free_identity() when finished. */  
+struct file_identity *
+fn_get_identity (const char *filename) 
+{
+  struct file_identity *identity = xmalloc (sizeof *identity);
+  identity->normalized_filename = fn_normalize (filename);
+  return identity;
+}
+
+/* Frees IDENTITY obtained from fn_get_identity(). */
+void
+fn_free_identity (struct file_identity *identity) 
+{
+  if (identity != NULL) 
+    {
+      free (identity->normalized_filename);
+      free (identity);
+    }
+}
+
+/* Compares A and B, returning a strcmp()-type result. */
+int
+fn_compare_file_identities (const struct file_identity *a,
+                            const struct file_identity *b) 
+{
+  return strcmp (a->normalized_filename, b->normalized_filename);
+}
+#endif /* not unix */