pspp-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Make fn_open and fn_close take a struct file_handle instead of c


From: John Darrington
Subject: [PATCH] Make fn_open and fn_close take a struct file_handle instead of char *
Date: Sat, 21 Nov 2015 09:49:03 +0100

I would appreciate feedback on this change before I check it in.  Perhaps
Harry could test it under windows, and maybe Ben could cast an eye over it
to see if he thinks it could cause any problems in the future.




This change alters the signature of the fn_open and fn_close functions,
and changes all callers appropriately.  The purpose of such a change is
so that the encoding of the filename is passed to fn_open from wherever
it was created.

It also changes the implementation of fn_open on windows systems to call
_wfopen instead of fopen.  This should fix the problem of windows builds
not being able to open files whose pathnames included non-ascii characters.

As a bonus, we no longer require the rather contrived function
local_to_filename_encoding.

Some related issues (what about the pspprc file?) remain.
---
 src/data/any-reader.c                 |   12 ++---
 src/data/any-reader.h                 |    2 +-
 src/data/any-writer.c                 |    2 +-
 src/data/encrypted-file.c             |   11 ++---
 src/data/encrypted-file.h             |    3 +-
 src/data/file-handle-def.c            |    1 -
 src/data/file-name.c                  |   77 +++++++++++++++++++++------------
 src/data/file-name.h                  |   23 +++++++---
 src/data/make-file.c                  |    5 +--
 src/data/pc+-file-reader.c            |    4 +-
 src/data/por-file-reader.c            |    4 +-
 src/data/sys-file-reader.c            |    4 +-
 src/language/data-io/data-reader.c    |    4 +-
 src/language/data-io/data-writer.c    |    2 +-
 src/language/data-io/save-translate.c |    2 +-
 src/language/stats/quick-cluster.c    |   14 ------
 src/output/ascii.c                    |   23 +++++-----
 src/output/cairo.c                    |   19 +++++---
 src/output/csv.c                      |   17 ++++----
 src/output/driver-provider.h          |    6 ++-
 src/output/driver.c                   |    5 ++-
 src/output/html.c                     |   19 ++++----
 src/output/msglog.c                   |   13 +++---
 src/output/odt.c                      |    5 ++-
 src/ui/gui/psppire-window.c           |   10 +++--
 src/ui/gui/psppire.c                  |   74 ++++---------------------------
 utilities/pspp-convert.c              |   25 ++++++-----
 27 files changed, 191 insertions(+), 195 deletions(-)

diff --git a/src/data/any-reader.c b/src/data/any-reader.c
index aee034c..ff7f4ab 100644
--- a/src/data/any-reader.c
+++ b/src/data/any-reader.c
@@ -51,7 +51,7 @@ static const struct any_reader_class *classes[] =
 enum { N_CLASSES = sizeof classes / sizeof *classes };
 
 int
-any_reader_detect (const char *file_name,
+any_reader_detect (const struct file_handle *file_handle,
                    const struct any_reader_class **classp)
 {
   struct detector
@@ -66,11 +66,11 @@ any_reader_detect (const char *file_name,
   if (classp)
     *classp = NULL;
 
-  file = fn_open (file_name, "rb");
+  file = fn_open (file_handle, "rb");
   if (file == NULL)
     {
       msg (ME, _("An error occurred while opening `%s': %s."),
-           file_name, strerror (errno));
+           fh_get_file_name (file_handle), strerror (errno));
       return -errno;
     }
 
@@ -90,9 +90,9 @@ any_reader_detect (const char *file_name,
     }
 
   if (retval < 0)
-    msg (ME, _("Error reading `%s': %s."), file_name, strerror (-retval));
+    msg (ME, _("Error reading `%s': %s."), fh_get_file_name (file_handle), 
strerror (-retval));
 
-  fn_close (file_name, file);
+  fn_close (file_handle, file);
 
   return retval;
 }
@@ -107,7 +107,7 @@ any_reader_open (struct file_handle *handle)
         const struct any_reader_class *class;
         int retval;
 
-        retval = any_reader_detect (fh_get_file_name (handle), &class);
+        retval = any_reader_detect (handle, &class);
         if (retval <= 0)
           {
             if (retval == 0)
diff --git a/src/data/any-reader.h b/src/data/any-reader.h
index a12c256..998e124 100644
--- a/src/data/any-reader.h
+++ b/src/data/any-reader.h
@@ -97,7 +97,7 @@ void any_read_info_destroy (struct any_read_info *);
 struct file_handle;
 struct dictionary;
 
-int any_reader_detect (const char *file_name,
+int any_reader_detect (const struct file_handle *file_name,
                        const struct any_reader_class **);
 
 struct any_reader *any_reader_open (struct file_handle *);
diff --git a/src/data/any-writer.c b/src/data/any-writer.c
index 61d6ffc..170702b 100644
--- a/src/data/any-writer.c
+++ b/src/data/any-writer.c
@@ -49,7 +49,7 @@ any_writer_open (struct file_handle *handle, struct 
dictionary *dict)
         struct casewriter *writer;
         char *extension;
 
-        extension = fn_extension (fh_get_file_name (handle));
+        extension = fn_extension (handle);
         str_lowercase (extension);
 
         if (!strcmp (extension, ".por"))
diff --git a/src/data/encrypted-file.c b/src/data/encrypted-file.c
index b90126e..f1074b4 100644
--- a/src/data/encrypted-file.c
+++ b/src/data/encrypted-file.c
@@ -17,6 +17,7 @@
 #include <config.h>
 
 #include "data/encrypted-file.h"
+#include "data/file-handle-def.h"
 
 #include <errno.h>
 #include <stdlib.h>
@@ -60,7 +61,7 @@ static bool fill_buffer (struct encrypted_file *);
 
    If FILENAME cannot be open or read, returns a negative errno value. */
 int
-encrypted_file_open (struct encrypted_file **fp, const char *filename)
+encrypted_file_open (struct encrypted_file **fp, const struct file_handle *fh)
 {
   struct encrypted_file *f;
   char header[36 + 16];
@@ -69,11 +70,11 @@ encrypted_file_open (struct encrypted_file **fp, const char 
*filename)
 
   f = xmalloc (sizeof *f);
   f->error = 0;
-  f->file = fn_open (filename, "rb");
+  f->file = fn_open (fh, "rb");
   if (f->file == NULL)
     {
       msg (ME, _("An error occurred while opening `%s': %s."),
-           filename, strerror (errno));
+           fh_get_file_name (fh), strerror (errno));
       retval = -errno;
       goto error;
     }
@@ -84,7 +85,7 @@ encrypted_file_open (struct encrypted_file **fp, const char 
*filename)
       int error = feof (f->file) ? 0 : errno;
       if (error)
         msg (ME, _("An error occurred while reading `%s': %s."),
-             filename, strerror (error));
+             fh_get_file_name (fh), strerror (error));
       retval = -error;
       goto error;
     }
@@ -107,7 +108,7 @@ encrypted_file_open (struct encrypted_file **fp, const char 
*filename)
 
 error:
   if (f->file)
-    fn_close (filename, f->file);
+    fn_close (fh, f->file);
   free (f);
   *fp = NULL;
 
diff --git a/src/data/encrypted-file.h b/src/data/encrypted-file.h
index d089a04..9e3116b 100644
--- a/src/data/encrypted-file.h
+++ b/src/data/encrypted-file.h
@@ -23,8 +23,9 @@
 /* Reading encrypted SPSS files. */
 
 struct encrypted_file;
+struct file_handle;
 
-int encrypted_file_open (struct encrypted_file **, const char *filename);
+int encrypted_file_open (struct encrypted_file **, const struct file_handle *);
 bool encrypted_file_unlock (struct encrypted_file *, const char *password);
 size_t encrypted_file_read (struct encrypted_file *, void *, size_t);
 int encrypted_file_close (struct encrypted_file *);
diff --git a/src/data/file-handle-def.c b/src/data/file-handle-def.c
index 53e00be..f058a00 100644
--- a/src/data/file-handle-def.c
+++ b/src/data/file-handle-def.c
@@ -24,7 +24,6 @@
 #include <string.h>
 
 #include "data/dataset.h"
-#include "data/file-name.h"
 #include "data/variable.h"
 #include "libpspp/cast.h"
 #include "libpspp/compiler.h"
diff --git a/src/data/file-name.c b/src/data/file-name.c
index a81ea93..1c47b47 100644
--- a/src/data/file-name.c
+++ b/src/data/file-name.c
@@ -31,6 +31,7 @@
 #include "data/settings.h"
 #include "libpspp/hash-functions.h"
 #include "libpspp/message.h"
+#include "libpspp/i18n.h"
 #include "libpspp/str.h"
 #include "libpspp/version.h"
 
@@ -48,7 +49,32 @@
 
 /* Functions for performing operations on file names. */
 
-/* Searches for a configuration file with name NAME in the directories given in
+
+/* Returns the extension part of FILE_NAME as a malloc()'d string.
+   If FILE_NAME does not have an extension, returns an empty
+   string. */
+char *
+fn_extension (const struct file_handle *fh)
+{
+  const char *file_name = fh_get_file_name (fh);
+
+  const char *extension = strrchr (file_name, '.');
+  if (extension == NULL)
+    extension = "";
+  return xstrdup (extension);
+}
+
+/* Find out information about files. */
+
+/* Returns true iff NAME specifies an absolute file name. */
+static bool
+fn_is_absolute (const char *name)
+{
+  return IS_ABSOLUTE_FILE_NAME (name);
+}
+
+
+/* Searches for a file with name NAME in the directories given in
    PATH, which is terminated by a null pointer.  Returns the full name of the
    first file found, which the caller is responsible for freeing with free(),
    or NULL if none is found. */
@@ -72,40 +98,23 @@ fn_search_path (const char *base_name, char **path)
       else
         file = xasprintf ("%s/%s", dir, base_name);
 
-      if (fn_exists (file))
-        return file;
+      struct stat temp;
+      if (( (stat (file, &temp) == 0 ) && ( ! S_ISDIR (temp.st_mode) )))
+       return file;
+      
       free (file);
     }
 
   return NULL;
 }
 
-/* Returns the extension part of FILE_NAME as a malloc()'d string.
-   If FILE_NAME does not have an extension, returns an empty
-   string. */
-char *
-fn_extension (const char *file_name)
-{
-  const char *extension = strrchr (file_name, '.');
-  if (extension == NULL)
-    extension = "";
-  return xstrdup (extension);
-}
-
-/* Find out information about files. */
-
-/* Returns true iff NAME specifies an absolute file name. */
-bool
-fn_is_absolute (const char *name)
-{
-  return IS_ABSOLUTE_FILE_NAME (name);
-}
 
 /* Returns true if file with name NAME exists, and that file is not a
    directory */
 bool
-fn_exists (const char *name)
+fn_exists (const struct file_handle *fh)
 {
+  const char *name = fh_get_file_name (fh);
   struct stat temp;
   if ( stat (name, &temp) != 0 )
     return false;
@@ -133,8 +142,10 @@ safety_violation (const char *fn)
    NULL on failure.  If NULL is returned then errno is set to a
    sensible value.  */
 FILE *
-fn_open (const char *fn, const char *mode)
+fn_open (const struct file_handle *fh, const char *mode)
 {
+  const char *fn = fh_get_file_name (fh);
+
   assert (mode[0] == 'r' || mode[0] == 'w' || mode[0] == 'a');
 
   if (mode[0] == 'r')
@@ -178,15 +189,28 @@ fn_open (const char *fn, const char *mode)
     }
   else
 #endif
+
+#if WIN32
+    {
+      wchar_t *ss = convert_to_filename_encoding (fn, strlen (fn), 
fh_get_file_name_encoding (fh));
+      wchar_t *m =  (wchar_t *) recode_string ("UTF-16LE", "ASCII", mode, 
strlen (mode));
+      FILE *fp = _wfopen (ss, m);
+      free (m);
+      free (ss);
+      return fp;
+    }
+#else    
     return fopen (fn, mode);
+#endif    
 }
 
 /* Counterpart to fn_open that closes file F with name FN; returns 0
    on success, EOF on failure.  If EOF is returned, errno is set to a
    sensible value. */
 int
-fn_close (const char *fn, FILE *f)
+fn_close (const struct file_handle *fh, FILE *f)
 {
+  const char *fn = fh_get_file_name (fh);
   if (fileno (f) == STDIN_FILENO
       || fileno (f) == STDOUT_FILENO
       || fileno (f) == STDERR_FILENO)
@@ -216,7 +240,6 @@ default_output_path (void)
     {
       /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give preference
         to HOME, because the user can change HOME.  */
-
       const char *home_dir = getenv ("HOME");
       int i;
 
diff --git a/src/data/file-name.h b/src/data/file-name.h
index 0a0e2f2..b4eee83 100644
--- a/src/data/file-name.h
+++ b/src/data/file-name.h
@@ -21,15 +21,28 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
+struct file_handle ;
+
 char *fn_search_path (const char *base_name, char **path);
-char *fn_extension (const char *fn);
+char *fn_extension (const struct file_handle *);
+
+bool fn_exists (const struct file_handle *);
 
-bool fn_is_absolute (const char *fn);
-bool fn_exists (const char *fn);
 
-FILE *fn_open (const char *fn, const char *mode);
-int fn_close (const char *fn, FILE *file);
+FILE *fn_open (const struct file_handle *fn, const char *mode);
+int fn_close (const struct file_handle *fn, FILE *file);
 
 const char * default_output_path (void);
 
+#if defined _WIN32 || defined __WIN32__
+#define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+#define UNICODE 1
+#include <windows.h>
+#else
+typedef char TCHAR;
+#endif
+
+TCHAR * convert_to_filename_encoding (const char *s, size_t len, const char 
*current_encoding);
+
+
 #endif /* file-name.h */
diff --git a/src/data/make-file.c b/src/data/make-file.c
index b67ed30..f4456ca 100644
--- a/src/data/make-file.c
+++ b/src/data/make-file.c
@@ -45,7 +45,6 @@
 
 #if defined _WIN32 || defined __WIN32__
 #define WIN32_LEAN_AND_MEAN  /* avoid including junk */
-#define UNICODE 1
 #include <windows.h>
 #define TS_stat _stat
 #define Tunlink _wunlink
@@ -149,7 +148,7 @@ Trename (TCHAR const *src, TCHAR const *dst)
   return -1;
 }
 
-static TCHAR * 
+TCHAR * 
 convert_to_filename_encoding (const char *s, size_t len, const char 
*current_encoding)
 {
   const char *enc = current_encoding;
@@ -168,7 +167,7 @@ typedef char TCHAR;
 #define Topen open
 #define Tstat stat
 
-static TCHAR * 
+TCHAR * 
 convert_to_filename_encoding (const char *s, size_t len UNUSED, const char 
*current_encoding UNUSED)
 {
   /* Non-windows systems don't care about the encoding.  
diff --git a/src/data/pc+-file-reader.c b/src/data/pc+-file-reader.c
index 08e6470..4d08f27 100644
--- a/src/data/pc+-file-reader.c
+++ b/src/data/pc+-file-reader.c
@@ -209,7 +209,7 @@ pcp_open (struct file_handle *fh)
     goto error;
 
   /* Open file. */
-  r->file = fn_open (fh_get_file_name (fh), "rb");
+  r->file = fn_open (fh, "rb");
   if (r->file == NULL)
     {
       msg (ME, _("Error opening `%s' for reading as an SPSS/PC+ "
@@ -478,7 +478,7 @@ pcp_close (struct any_reader *r_)
 
   if (r->file)
     {
-      if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
+      if (fn_close (r->fh, r->file) == EOF)
         {
           msg (ME, _("Error closing system file `%s': %s."),
                fh_get_file_name (r->fh), strerror (errno));
diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c
index 058a0a8..15a3b79 100644
--- a/src/data/por-file-reader.c
+++ b/src/data/por-file-reader.c
@@ -170,7 +170,7 @@ pfm_close (struct any_reader *r_)
   any_read_info_destroy (&r->info);
   if (r->file)
     {
-      if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
+      if (fn_close (r->fh, r->file) == EOF)
         {
           msg (ME, _("Error closing portable file `%s': %s."),
                fh_get_file_name (r->fh), strerror (errno));
@@ -288,7 +288,7 @@ pfm_open (struct file_handle *fh)
     goto error;
 
   /* Open file. */
-  r->file = fn_open (fh_get_file_name (r->fh), "rb");
+  r->file = fn_open (r->fh, "rb");
   if (r->file == NULL)
     {
       msg (ME, _("An error occurred while opening `%s' for reading "
diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c
index ddc6854..a1193de 100644
--- a/src/data/sys-file-reader.c
+++ b/src/data/sys-file-reader.c
@@ -408,7 +408,7 @@ sfm_open (struct file_handle *fh)
   if (r->lock == NULL)
     goto error;
 
-  r->file = fn_open (fh_get_file_name (fh), "rb");
+  r->file = fn_open (fh, "rb");
   if (r->file == NULL)
     {
       msg (ME, _("Error opening `%s' for reading as a system file: %s."),
@@ -894,7 +894,7 @@ sfm_close (struct any_reader *r_)
 
   if (r->file)
     {
-      if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
+      if (fn_close (r->fh, r->file) == EOF)
         {
           msg (ME, _("Error closing system file `%s': %s."),
                fh_get_file_name (r->fh), strerror (errno));
diff --git a/src/language/data-io/data-reader.c 
b/src/language/data-io/data-reader.c
index c28fa07..0a00619 100644
--- a/src/language/data-io/data-reader.c
+++ b/src/language/data-io/data-reader.c
@@ -95,7 +95,7 @@ dfm_close_reader (struct dfm_reader *r)
 
   /* This was the last client, so close the underlying file. */
   if (fh_get_referent (r->fh) != FH_REF_INLINE)
-    fn_close (fh_get_file_name (r->fh), r->file);
+    fn_close (r->fh, r->file);
   else
     {
       /* Skip any remaining data on the inline file. */
@@ -157,7 +157,7 @@ dfm_open_reader (struct file_handle *fh, struct lexer 
*lexer,
     {
       struct stat s;
       r->line_number = 0;
-      r->file = fn_open (fh_get_file_name (fh), "rb");
+      r->file = fn_open (fh, "rb");
       if (r->file == NULL)
         {
           msg (ME, _("Could not open `%s' for reading as a data file: %s."),
diff --git a/src/language/data-io/data-writer.c 
b/src/language/data-io/data-writer.c
index 65de635..bf9505e 100644
--- a/src/language/data-io/data-writer.c
+++ b/src/language/data-io/data-writer.c
@@ -218,7 +218,7 @@ dfm_close_writer (struct dfm_writer *w)
   if (w->file != NULL)
     {
       const char *file_name = fh_get_file_name (w->fh);
-      ok = !dfm_write_error (w) && !fn_close (file_name, w->file);
+      ok = !dfm_write_error (w) && !fn_close (w->fh, w->file);
 
       if (!ok)
         msg (ME, _("I/O error occurred writing data file `%s'."), file_name);
diff --git a/src/language/data-io/save-translate.c 
b/src/language/data-io/save-translate.c
index 54b769d..c366f56 100644
--- a/src/language/data-io/save-translate.c
+++ b/src/language/data-io/save-translate.c
@@ -247,7 +247,7 @@ cmd_save_translate (struct lexer *lexer, struct dataset *ds)
       lex_sbc_missing ("OUTFILE");
       goto error;
     }
-  else if (!replace && fn_exists (fh_get_file_name (handle)))
+  else if (!replace && fn_exists (handle))
     {
       msg (SE, _("Output file `%s' exists but %s was not specified."),
            fh_get_file_name (handle), "REPLACE");
diff --git a/src/language/stats/quick-cluster.c 
b/src/language/stats/quick-cluster.c
index 0a2b75d..f4c64b0 100644
--- a/src/language/stats/quick-cluster.c
+++ b/src/language/stats/quick-cluster.c
@@ -190,20 +190,6 @@ matrix_mindist (const gsl_matrix *m, int *mn, int *mm)
 }
 
 
-static void
-dump_matrix (const gsl_matrix *m)
-{
-  size_t i, j;
-
-  for (i = 0 ; i < m->size1; ++i)
-    {
-      for (j = 0 ; j < m->size2; ++j)
-       printf ("%02f ", gsl_matrix_get (m, i, j));
-      printf ("\n");
-    }
-}
-
-
 /* Return the distance of C from the group whose index is WHICH */
 static double
 dist_from_case (const struct Kmeans *kmeans, const struct ccase *c, const 
struct qc *qc, int which)
diff --git a/src/output/ascii.c b/src/output/ascii.c
index 0b6d659..636d9ec 100644
--- a/src/output/ascii.c
+++ b/src/output/ascii.c
@@ -28,6 +28,7 @@
 #include <uniwidth.h>
 
 #include "data/file-name.h"
+#include "data/file-handle-def.h"
 #include "data/settings.h"
 #include "libpspp/assertion.h"
 #include "libpspp/cast.h"
@@ -172,7 +173,7 @@ struct ascii_driver
     char *command_name;
     char *title;
     char *subtitle;
-    char *file_name;            /* Output file name. */
+    struct file_handle *handle;
     FILE *file;                 /* Output file. */
     bool error;                 /* Output error? */
     int page_number;           /* Current page number. */
@@ -233,7 +234,7 @@ opt (struct output_driver *d, struct string_map *options, 
const char *key,
 }
 
 static struct output_driver *
-ascii_create (const char *file_name, enum settings_output_devices device_type,
+ascii_create (struct  file_handle *fh, enum settings_output_devices 
device_type,
               struct string_map *o)
 {
   enum { BOX_ASCII, BOX_UNICODE } box;
@@ -244,7 +245,7 @@ ascii_create (const char *file_name, enum 
settings_output_devices device_type,
 
   a = xzalloc (sizeof *a);
   d = &a->driver;
-  output_driver_init (&a->driver, &ascii_driver_class, file_name, device_type);
+  output_driver_init (&a->driver, &ascii_driver_class, fh_get_file_name (fh), 
device_type);
   a->append = parse_boolean (opt (d, o, "append", "false"));
   a->headers = parse_boolean (opt (d, o, "headers", "false"));
   a->paginate = parse_boolean (opt (d, o, "paginate", "false"));
@@ -255,7 +256,8 @@ ascii_create (const char *file_name, enum 
settings_output_devices device_type,
                             "none", EMPH_NONE,
                             NULL_SENTINEL);
 
-  a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", file_name));
+  a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", 
fh_get_file_name (fh)));
+  a->handle = fh;
 
   a->top_margin = parse_int (opt (d, o, "top-margin", "0"), 0, INT_MAX);
   a->bottom_margin = parse_int (opt (d, o, "bottom-margin", "0"), 0, INT_MAX);
@@ -283,7 +285,6 @@ ascii_create (const char *file_name, enum 
settings_output_devices device_type,
   a->command_name = NULL;
   a->title = xstrdup ("");
   a->subtitle = xstrdup ("");
-  a->file_name = xstrdup (file_name);
   a->file = NULL;
   a->error = false;
   a->page_number = 0;
@@ -380,11 +381,11 @@ ascii_destroy (struct output_driver *driver)
     ascii_close_page (a);
 
   if (a->file != NULL)
-    fn_close (a->file_name, a->file);
+    fn_close (a->handle, a->file);
+  fh_unref (a->handle);
   free (a->command_name);
   free (a->title);
   free (a->subtitle);
-  free (a->file_name);
   free (a->chart_file_name);
   for (i = 0; i < a->allocated_lines; i++)
     u8_line_destroy (&a->lines[i]);
@@ -400,8 +401,8 @@ ascii_flush (struct output_driver *driver)
     {
       ascii_close_page (a);
 
-      if (fn_close (a->file_name, a->file) != 0)
-        msg_error (errno, _("ascii: closing output file `%s'"), a->file_name);
+      if (fn_close (a->handle, a->file) != 0)
+        msg_error (errno, _("ascii: closing output file `%s'"), 
fh_get_file_name (a->handle));
       a->file = NULL;
     }
 }
@@ -1091,7 +1092,7 @@ ascii_open_page (struct ascii_driver *a)
 
   if (a->file == NULL)
     {
-      a->file = fn_open (a->file_name, a->append ? "a" : "w");
+      a->file = fn_open (a->handle, a->append ? "a" : "w");
       if (a->file != NULL)
         {
          if ( isatty (fileno (a->file)))
@@ -1111,7 +1112,7 @@ ascii_open_page (struct ascii_driver *a)
       else
         {
           msg_error (errno, _("ascii: opening output file `%s'"),
-                 a->file_name);
+                    fh_get_file_name (a->handle));
           a->error = true;
           return false;
         }
diff --git a/src/output/cairo.c b/src/output/cairo.c
index 7f22064..122d1b7 100644
--- a/src/output/cairo.c
+++ b/src/output/cairo.c
@@ -25,6 +25,7 @@
 #include "libpspp/str.h"
 #include "libpspp/string-map.h"
 #include "libpspp/version.h"
+#include "data/file-handle-def.h"
 #include "output/cairo-chart.h"
 #include "output/chart-item-provider.h"
 #include "output/charts/boxplot.h"
@@ -475,24 +476,30 @@ xr_create (const char *file_name, enum 
settings_output_devices device_type,
 }
 
 static struct output_driver *
-xr_pdf_create (const char *file_name, enum settings_output_devices device_type,
+xr_pdf_create (struct  file_handle *fh, enum settings_output_devices 
device_type,
                struct string_map *o)
 {
-  return xr_create (file_name, device_type, o, XR_PDF);
+  struct output_driver *od = xr_create (fh_get_file_name (fh), device_type, o, 
XR_PDF);
+  fh_unref (fh);
+  return od ;
 }
 
 static struct output_driver *
-xr_ps_create (const char *file_name, enum settings_output_devices device_type,
+xr_ps_create (struct  file_handle *fh, enum settings_output_devices 
device_type,
                struct string_map *o)
 {
-  return xr_create (file_name, device_type, o, XR_PS);
+  struct output_driver *od =  xr_create (fh_get_file_name (fh), device_type, 
o, XR_PS);
+  fh_unref (fh);
+  return od ;
 }
 
 static struct output_driver *
-xr_svg_create (const char *file_name, enum settings_output_devices device_type,
+xr_svg_create (struct file_handle *fh, enum settings_output_devices 
device_type,
                struct string_map *o)
 {
-  return xr_create (file_name, device_type, o, XR_SVG);
+  struct output_driver *od = xr_create (fh_get_file_name (fh), device_type, o, 
XR_SVG);
+  fh_unref (fh);
+  return od ;
 }
 
 static void
diff --git a/src/output/csv.c b/src/output/csv.c
index cf17545..4555849 100644
--- a/src/output/csv.c
+++ b/src/output/csv.c
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #include "data/file-name.h"
+#include "data/file-handle-def.h"
 #include "libpspp/assertion.h"
 #include "libpspp/compiler.h"
 #include "libpspp/message.h"
@@ -49,7 +50,7 @@ struct csv_driver
     bool titles;                /* Print table titles? */
     bool captions;              /* Print table captions? */
 
-    char *file_name;            /* Output file name. */
+    struct file_handle *handle;
     char *command_name;         /* Current command. */
     FILE *file;                 /* Output file. */
     int n_items;                /* Number of items output so far. */
@@ -72,7 +73,7 @@ opt (struct output_driver *d, struct string_map *options, 
const char *key,
 }
 
 static struct output_driver *
-csv_create (const char *file_name, enum settings_output_devices device_type,
+csv_create (struct file_handle *fh, enum settings_output_devices device_type,
             struct string_map *o)
 {
   struct output_driver *d;
@@ -81,7 +82,7 @@ csv_create (const char *file_name, enum 
settings_output_devices device_type,
 
   csv = xzalloc (sizeof *csv);
   d = &csv->driver;
-  output_driver_init (&csv->driver, &csv_driver_class, file_name, device_type);
+  output_driver_init (&csv->driver, &csv_driver_class, fh_get_file_name (fh), 
device_type);
 
   csv->separator = parse_string (opt (d, o, "separator", ","));
   quote = parse_string (opt (d, o, "quote", "\""));
@@ -90,13 +91,13 @@ csv_create (const char *file_name, enum 
settings_output_devices device_type,
   csv->quote_set = xasprintf ("\n\r\t%s%c", csv->separator, csv->quote);
   csv->titles = parse_boolean (opt (d, o, "titles", "true"));
   csv->captions = parse_boolean (opt (d, o, "captions", "true"));
-  csv->file_name = xstrdup (file_name);
-  csv->file = fn_open (csv->file_name, "w");
+  csv->handle = fh;
+  csv->file = fn_open (fh, "w");
   csv->n_items = 0;
 
   if (csv->file == NULL)
     {
-      msg_error (errno, _("error opening output file `%s'"), csv->file_name);
+      msg_error (errno, _("error opening output file `%s'"), fh_get_file_name 
(fh));
       output_driver_destroy (d);
       return NULL;
     }
@@ -110,11 +111,11 @@ csv_destroy (struct output_driver *driver)
   struct csv_driver *csv = csv_driver_cast (driver);
 
   if (csv->file != NULL)
-    fn_close (csv->file_name, csv->file);
+    fn_close (csv->handle, csv->file);
 
   free (csv->separator);
   free (csv->quote_set);
-  free (csv->file_name);
+  fh_unref (csv->handle);
   free (csv);
 }
 
diff --git a/src/output/driver-provider.h b/src/output/driver-provider.h
index 754b0d0..aa70bb4 100644
--- a/src/output/driver-provider.h
+++ b/src/output/driver-provider.h
@@ -25,6 +25,7 @@
 
 struct output_item;
 struct string_map;
+struct file_handle;
 
 /* A configured output driver. */
 struct output_driver
@@ -36,7 +37,8 @@ struct output_driver
 
 void output_driver_init (struct output_driver *,
                          const struct output_driver_class *,
-                         const char *name, enum settings_output_devices);
+                         const char *, enum settings_output_devices);
+
 void output_driver_destroy (struct output_driver *);
 
 const char *output_driver_get_name (const struct output_driver *);
@@ -98,7 +100,7 @@ struct output_driver_factory
        The returned driver should not have been registered (with
        output_driver_register).  The caller will register the driver (if this
        is desirable). */
-    struct output_driver *(*create) (const char *name,
+    struct output_driver *(*create) (struct file_handle *,
                                      enum settings_output_devices type,
                                      struct string_map *options);
   };
diff --git a/src/output/driver.c b/src/output/driver.c
index 94bc241..6f72ffe 100644
--- a/src/output/driver.c
+++ b/src/output/driver.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "data/file-handle-def.h"
 #include "data/settings.h"
 #include "libpspp/array.h"
 #include "libpspp/assertion.h"
@@ -374,8 +375,10 @@ output_driver_create (struct string_map *options)
                      device_string, "terminal", "listing");
       device_type = default_device_type (file_name);
     }
+  
+  struct file_handle *fh = fh_create_file (NULL, file_name, NULL, 
fh_default_properties ());
 
-  driver = f->create (file_name, device_type, options);
+  driver = f->create (fh, device_type, options);
   if (driver != NULL)
     {
       const struct string_map_node *node;
diff --git a/src/output/html.c b/src/output/html.c
index 9e7f567..8b16ffa 100644
--- a/src/output/html.c
+++ b/src/output/html.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "data/file-name.h"
+#include "data/file-handle-def.h"
 #include "libpspp/assertion.h"
 #include "libpspp/cast.h"
 #include "libpspp/compiler.h"
@@ -51,7 +52,7 @@ struct html_driver
     struct xr_color fg;
     struct xr_color bg;
 #endif    
-    char *file_name;
+    struct file_handle *handle;
     char *chart_file_name;
 
     char *command_name;
@@ -86,7 +87,7 @@ opt (struct output_driver *d, struct string_map *options, 
const char *key,
 }
 
 static struct output_driver *
-html_create (const char *file_name, enum settings_output_devices device_type,
+html_create (struct file_handle *fh, enum settings_output_devices device_type,
              struct string_map *o)
 {
   struct output_driver *d;
@@ -94,24 +95,24 @@ html_create (const char *file_name, enum 
settings_output_devices device_type,
 
   html = xzalloc (sizeof *html);
   d = &html->driver;
-  output_driver_init (&html->driver, &html_driver_class, file_name,
+  output_driver_init (&html->driver, &html_driver_class, fh_get_file_name (fh),
                       device_type);
   html->css = parse_boolean (opt (d, o, "css", "true"));
   html->borders = parse_boolean (opt (d, o, "borders", "true"));
 
-  html->file_name = xstrdup (file_name);
+  html->handle = fh;
   html->chart_file_name = parse_chart_file_name (opt (d, o, "charts",
-                                                      file_name));
+                                                      fh_get_file_name (fh)));
   html->file = NULL;
   html->chart_cnt = 1;
 #ifdef HAVE_CAIRO
   parse_color (d, o, "background-color", "#FFFFFFFFFFFF", &html->bg);
   parse_color (d, o, "foreground-color", "#000000000000", &html->fg);
 #endif
-  html->file = fn_open (html->file_name, "w");
+  html->file = fn_open (html->handle, "w");
   if (html->file == NULL)
     {
-      msg_error (errno, _("error opening output file `%s'"), html->file_name);
+      msg_error (errno, _("error opening output file `%s'"), fh_get_file_name 
(html->handle));
       goto error;
     }
 
@@ -216,10 +217,10 @@ html_destroy (struct output_driver *driver)
                "</BODY>\n"
                "</HTML>\n"
                "<!-- end of file -->\n");
-      fn_close (html->file_name, html->file);
+      fn_close (html->handle, html->file);
     }
   free (html->chart_file_name);
-  free (html->file_name);
+  fh_unref (html->handle);
   free (html->command_name);
   free (html);
 }
diff --git a/src/output/msglog.c b/src/output/msglog.c
index a3f1954..0d03295 100644
--- a/src/output/msglog.c
+++ b/src/output/msglog.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "data/file-name.h"
+#include "data/file-handle-def.h"
 #include "data/settings.h"
 #include "libpspp/cast.h"
 #include "libpspp/message.h"
@@ -40,7 +41,7 @@ struct msglog_driver
   {
     struct output_driver driver;
     FILE *file;
-    char *file_name;
+    struct file_handle *handle;
     char *command_name;
   };
 
@@ -60,7 +61,9 @@ msglog_create (const char *file_name)
   struct msglog_driver *ml;
   FILE *file;
 
-  file = fn_open (file_name, "w");
+  struct file_handle *handle = fh_create_file  (NULL, file_name, NULL, 
fh_default_properties ());
+
+  file = fn_open (handle, "w");
   if (file == NULL)
     {
       msg_error (errno, _("error opening output file `%s'"), file_name);
@@ -72,9 +75,9 @@ msglog_create (const char *file_name)
           : SETTINGS_DEVICE_UNFILTERED);
 
   ml = xzalloc (sizeof *ml);
+  ml->handle = handle;
   output_driver_init (&ml->driver, &msglog_class, file_name, type);
   ml->file = file;
-  ml->file_name = xstrdup (file_name);
   ml->command_name = NULL;
 
   output_driver_register (&ml->driver);
@@ -87,9 +90,9 @@ msglog_destroy (struct output_driver *driver)
 {
   struct msglog_driver *ml = msglog_driver_cast (driver);
 
-  fn_close (ml->file_name, ml->file);
-  free (ml->file_name);
+  fn_close (ml->handle, ml->file);
   free (ml->command_name);
+  fh_unref (ml->handle);
   free (ml);
 }
 
diff --git a/src/output/odt.c b/src/output/odt.c
index a29c045..8e94dd7 100644
--- a/src/output/odt.c
+++ b/src/output/odt.c
@@ -36,6 +36,7 @@
 #include "libpspp/temp-file.h"
 #include "libpspp/version.h"
 #include "libpspp/zip-writer.h"
+#include "data/file-handle-def.h"
 #include "output/driver-provider.h"
 #include "output/message-item.h"
 #include "output/options.h"
@@ -290,12 +291,13 @@ write_meta_data (struct odt_driver *odt)
 }
 
 static struct output_driver *
-odt_create (const char *file_name, enum settings_output_devices device_type,
+odt_create (struct file_handle *fh, enum settings_output_devices device_type,
             struct string_map *o UNUSED)
 {
   struct output_driver *d;
   struct odt_driver *odt;
   struct zip_writer *zip;
+  const char *file_name = fh_get_file_name (fh);
 
   zip = zip_writer_create (file_name);
   if (zip == NULL)
@@ -303,6 +305,7 @@ odt_create (const char *file_name, enum 
settings_output_devices device_type,
 
   odt = xzalloc (sizeof *odt);
   d = &odt->driver;
+
   output_driver_init (d, &odt_driver_class, file_name, device_type);
 
   odt->zip = zip;
diff --git a/src/ui/gui/psppire-window.c b/src/ui/gui/psppire-window.c
index 6ef2dd4..8e34c21 100644
--- a/src/ui/gui/psppire-window.c
+++ b/src/ui/gui/psppire-window.c
@@ -30,6 +30,7 @@
 #define N_(msgid) msgid
 
 #include "data/any-reader.h"
+#include "data/file-handle-def.h"
 #include "data/dataset.h"
 #include "libpspp/version.h"
 
@@ -778,19 +779,22 @@ psppire_window_open (PsppireWindow *de)
        gchar *name =
          gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
 
-       gchar *sysname = convert_glib_filename_to_system_filename (name, NULL);
+       const gchar **cs = NULL;
+       g_get_filename_charsets (&cs);
 
         gchar *encoding = psppire_encoding_selector_get_encoding (
           gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog)));
 
-        int retval = any_reader_detect (sysname, NULL);
+       struct file_handle *fh = fh_create_file (NULL, name, cs[0], 
fh_default_properties ());
+
+        int retval = any_reader_detect (fh, NULL);
        if (retval == 1)
           open_data_window (de, name, encoding, NULL);
        else if (retval == 0)
          open_syntax_window (name, encoding);
 
         g_free (encoding);
-       g_free (sysname);
+       fh_unref (fh);
        g_free (name);
       }
       break;
diff --git a/src/ui/gui/psppire.c b/src/ui/gui/psppire.c
index e55e616..9ed7d15 100644
--- a/src/ui/gui/psppire.c
+++ b/src/ui/gui/psppire.c
@@ -64,8 +64,6 @@
 #include "gl/relocatable.h"
 
 static void create_icon_factory (void);
-static gchar *local_to_filename_encoding (const char *fn);
-
 
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
@@ -130,9 +128,13 @@ initialize (const struct init_source *is)
       {
       if (is->file)
        {
-         gchar *filename = local_to_filename_encoding (is->file);
+         const gchar *local_encoding = NULL;
+         g_get_charset (&local_encoding);
+
+         struct file_handle *fh = fh_create_file (NULL, is->file, 
local_encoding, fh_default_properties ());
+         const char *filename = fh_get_file_name (fh);
 
-         int retval = any_reader_detect (filename, NULL);
+         int retval = any_reader_detect (fh, NULL);
 
          /* Check to see if the file is a .sav or a .por file.  If not
             assume that it is a syntax file */
@@ -143,7 +145,8 @@ initialize (const struct init_source *is)
              create_data_window ();
              open_syntax_window (filename, NULL);
            }
-         g_free (filename);
+
+         fh_unref (fh);
        }
       else
        {
@@ -328,67 +331,8 @@ create_icon_factory (void)
 
   gtk_icon_factory_add_default (factory);
 }
-
-/* 
-   Convert a filename from the local encoding into "filename" encoding.
-   The return value will be allocated on the heap.  It is the responsibility
-   of the caller to free it.
- */
-static gchar *
-local_to_filename_encoding (const char *fn)
-{
-  gchar *filename = NULL;
-  gchar *utf8 = NULL;
-  const gchar *local_encoding = NULL;
-  gsize written = -1;
-  const gboolean local_is_utf8 = g_get_charset (&local_encoding);
-
-  /* There seems to be no Glib function to convert from local encoding
-     to filename encoding.  Therefore it has to be done in two steps:
-     the intermediate encoding is UTF8.
-
-     Either step could fail.  However, in many cases the file can still
-     be loaded even if the conversion fails. So in those cases, after showing
-     a warning, we simply copy the locally encoded filename to the destination
-     and hope for the best.
-  */
-
-  if ( local_is_utf8)
-    {
-      utf8 = xstrdup (fn);
-    }
-  else
-    {
-      GError *err = NULL;
-      utf8 = g_locale_to_utf8 (fn, -1, NULL, &written, &err);
-      if ( NULL == utf8)
-        {
-          g_warning ("Cannot convert filename from local encoding `%s' to 
UTF-8: %s",
-                     local_encoding,
-                     err->message);
-          g_clear_error (&err);
-        }
-    }
-
-  if ( NULL != utf8)
-    {
-      GError *err = NULL;
-      filename = g_filename_from_utf8 (utf8, written, NULL, NULL, &err);
-      if ( NULL == filename)
-        {
-          g_warning ("Cannot convert filename from UTF8 to filename encoding: 
%s",
-                     err->message);
-          g_clear_error (&err);
-        }
-    }
 
-  g_free (utf8);
-
-  if ( filename == NULL)
-    filename = xstrdup (fn);
-
-  return filename;
-}
+
 
 static void
 handle_msg (const struct msg *m_, void *lexer_)
diff --git a/utilities/pspp-convert.c b/utilities/pspp-convert.c
index f711095..ce5fd87 100644
--- a/utilities/pspp-convert.c
+++ b/utilities/pspp-convert.c
@@ -47,8 +47,8 @@
 static void usage (void);
 
 static void decrypt_file (struct encrypted_file *enc,
-                          const char *input_filename,
-                          const char *output_filename,
+                          const struct file_handle *input_filename,
+                          const struct file_handle *output_filename,
                           const char *password);
 
 int
@@ -135,6 +135,8 @@ main (int argc, char *argv[])
 
   input_filename = argv[optind];
   output_filename = argv[optind + 1];
+  input_fh = fh_create_file (NULL, input_filename, NULL, fh_default_properties 
());
+
   if (output_format == NULL)
     {
       const char *dot = strrchr (output_filename, '.');
@@ -145,7 +147,8 @@ main (int argc, char *argv[])
       output_format = dot + 1;
     }
 
-  if (encrypted_file_open (&enc, input_filename) > 0)
+  output_fh = fh_create_file (NULL, output_filename, NULL, 
fh_default_properties ());
+  if (encrypted_file_open (&enc, input_fh) > 0)
     {
       if (encrypted_file_is_sav (enc))
         {
@@ -160,16 +163,16 @@ main (int argc, char *argv[])
                            "format"));
         }
 
-      decrypt_file (enc, input_filename, output_filename, password);
+      decrypt_file (enc, input_fh, output_fh, password);
       goto exit;
     }
 
-  input_fh = fh_create_file (NULL, input_filename, NULL, fh_default_properties 
());
+
   reader = any_reader_open_and_decode (input_fh, encoding, &dict, NULL);
   if (reader == NULL)
     exit (1);
 
-  output_fh = fh_create_file (NULL, output_filename, NULL, 
fh_default_properties ());
+
   if (!strcmp (output_format, "csv") || !strcmp (output_format, "txt"))
     {
       struct csv_writer_options options;
@@ -224,12 +227,14 @@ exit:
 
 static void
 decrypt_file (struct encrypted_file *enc,
-              const char *input_filename,
-              const char *output_filename,
+             const struct file_handle *ifh,
+             const struct file_handle *ofh,
               const char *password)
 {
   FILE *out;
   int err;
+  const char *input_filename = fh_get_file_name (ifh);
+  const char *output_filename = fh_get_file_name (ofh);
 
   if (password == NULL)
     {
@@ -241,7 +246,7 @@ decrypt_file (struct encrypted_file *enc,
   if (!encrypted_file_unlock (enc, password))
     error (1, 0, _("sorry, wrong password"));
 
-  out = fn_open (output_filename, "wb");
+  out = fn_open (ofh, "wb");
   if (out == NULL)
     error (1, errno, ("%s: error opening output file"), output_filename);
 
@@ -264,7 +269,7 @@ decrypt_file (struct encrypted_file *enc,
 
   if (fflush (out) == EOF)
     error (1, errno, ("%s: write error"), output_filename);
-  fn_close (output_filename, out);
+  fn_close (ofh, out);
 }
 
 static void
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]