Avoid possible overflow in fn_identity.
[pspp] / src / data / file-name.c
index fa0eb794010f75b9b2666334c08b827422ed04bd..f59b2fa4ecd9bdcc367c1acffefe017859e6ad13 100644 (file)
@@ -82,14 +82,6 @@ fn_search_path (const char *base_name, char **path)
   return NULL;
 }
 
-/* Returns the directory part of FILE_NAME, as a malloc()'d
-   string. */
-char *
-fn_dir_name (const char *file_name)
-{
-  return dir_name (file_name);
-}
-
 /* Returns the extension part of FILE_NAME as a malloc()'d string.
    If FILE_NAME does not have an extension, returns an empty
    string. */
@@ -111,23 +103,6 @@ fn_is_absolute (const char *name)
   return IS_ABSOLUTE_FILE_NAME (name);
 }
 
-/* Returns true if FILE_NAME is a virtual file that doesn't
-   really exist on disk, false if it's a real file name. */
-bool
-fn_is_special (const char *file_name)
-{
-  if (!strcmp (file_name, "-") || !strcmp (file_name, "stdin")
-      || !strcmp (file_name, "stdout") || !strcmp (file_name, "stderr")
-#ifdef HAVE_POPEN
-      || file_name[0] == '|'
-      || (*file_name && file_name[strlen (file_name) - 1] == '|')
-#endif
-      )
-    return true;
-
-  return false;
-}
-
 /* Returns true if file with name NAME exists, and that file is not a
    directory */
 bool
@@ -139,28 +114,7 @@ fn_exists (const char *name)
 
   return ! S_ISDIR (temp.st_mode);
 }
-\f
-/* Environment variables. */
-
-/* Simulates $VER and $ARCH environment variables. */
-const char *
-fn_getenv (const char *s)
-{
-  if (!strcmp (s, "VER"))
-    return fn_getenv_default ("STAT_VER", bare_version);
-  else if (!strcmp (s, "ARCH"))
-    return fn_getenv_default ("STAT_ARCH", host_system);
-  else
-    return getenv (s);
-}
 
-/* Returns getenv(KEY) if that's non-NULL; else returns DEF. */
-const char *
-fn_getenv_default (const char *key, const char *def)
-{
-  const char *value = getenv (key);
-  return value ? value : def;
-}
 \f
 /* Basic file handling. */
 
@@ -250,29 +204,6 @@ fn_close (const char *fn, FILE *f)
     return fclose (f);
 }
 
-/* Creates a new file named FN with the given PERMISSIONS bits,
-   and returns a stream for it or a null pointer on failure.
-   MODE should be "w" or "wb". */
-FILE *
-create_stream (const char *fn, const char *mode, mode_t permissions)
-{
-  int fd;
-  FILE *stream;
-
-  fd = open (fn, O_WRONLY | O_CREAT | O_TRUNC, permissions);
-  if (fd < 0)
-    return NULL;
-
-  stream = fdopen (fd, mode);
-  if (stream == NULL)
-    {
-      int save_errno = errno;
-      close (fd);
-      errno = save_errno;
-    }
-
-  return stream;
-}
 
 /* A file's identity:
 
@@ -289,8 +220,8 @@ create_stream (const char *fn, const char *mode, mode_t permissions)
    there. */
 struct file_identity
 {
-  dev_t device;               /* Device number. */
-  ino_t inode;                /* Inode number. */
+  unsigned long long device;               /* Device number. */
+  unsigned long long inode;                /* Inode number. */
   char *name;                 /* File name, where needed, otherwise NULL. */
 };
 
@@ -331,12 +262,42 @@ fn_get_identity (const char *file_name)
       free (dir);
     }
 #else /* Windows */
-  char cname[PATH_MAX];
-  int ok = GetFullPathName (file_name, sizeof cname, cname, NULL);
-  identity->device = 0;
-  identity->inode = 0;
-  identity->name = xstrdup (ok ? cname : file_name);
-  str_lowercase (identity->name);
+  bool ok = false;
+  HANDLE h = CreateFile (file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
+  if (h != INVALID_HANDLE_VALUE)
+  {
+    BY_HANDLE_FILE_INFORMATION fi;
+    ok = GetFileInformationByHandle (h, &fi);
+    if (ok)
+      {
+       identity->device = fi.dwVolumeSerialNumber;
+       identity->inode = fi.nFileIndexHigh;
+       identity->inode <<= (sizeof fi.nFileIndexLow) * CHAR_BIT;
+       identity->inode |= fi.nFileIndexLow;
+       identity->name = 0;
+      }
+    CloseHandle (h);
+  }
+
+  if (!ok)
+    {
+      identity->device = 0;
+      identity->inode = 0;
+
+      size_t bufsize;
+      size_t pathlen = 255;
+      char *cname = NULL;
+      do 
+      {
+       bufsize = pathlen;
+       cname = xrealloc (cname, bufsize);
+       pathlen = GetFullPathName (file_name, bufsize, cname, NULL);
+      }
+      while (pathlen > bufsize);
+      identity->name = xstrdup (cname);
+      free (cname);
+      str_lowercase (identity->name);
+    }
 #endif /* Windows */
 
   return identity;