#include <string.h>
#include "data/dataset.h"
-#include "data/file-name.h"
#include "data/variable.h"
+#include "libpspp/assertion.h"
#include "libpspp/cast.h"
#include "libpspp/compiler.h"
#include "libpspp/hash-functions.h"
/* Hash table of all active locks. */
static struct hmap locks = HMAP_INITIALIZER (locks);
-struct file_identity *fh_get_identity (const struct file_handle *);
+static struct file_identity *fh_get_identity (const struct file_handle *);
static void fh_free_identity (struct file_identity *);
static int fh_compare_file_identities (const struct file_identity *,
const struct file_identity *);
HMAP_FOR_EACH_SAFE (handle, next,
struct file_handle, name_node, &named_handles)
unname_handle (handle);
+
+ free_handle (inline_file);
}
/* Free HANDLE and remove it from the global list. */
static void
free_handle (struct file_handle *handle)
{
+ if (handle == NULL)
+ return;
+
/* Remove handle from global list. */
if (handle->id != NULL)
hmap_delete (&named_handles, &handle->name_node);
struct file_handle *
fh_ref (struct file_handle *handle)
{
+ if (handle == fh_inline_file ())
+ return handle;
assert (handle->ref_cnt > 0);
handle->ref_cnt++;
return handle;
{
if (handle != NULL)
{
+ if (handle == fh_inline_file ())
+ return;
assert (handle->ref_cnt > 0);
if (--handle->ref_cnt == 0)
free_handle (handle);
create_handle (const char *id, char *handle_name, enum fh_referent referent,
const char *encoding)
{
- struct file_handle *handle = xzalloc (sizeof *handle);
+ struct file_handle *handle = XZALLOC (struct file_handle);
handle->ref_cnt = 1;
- handle->id = id != NULL ? xstrdup (id) : NULL;
+ handle->id = xstrdup_if_nonnull (id);
handle->name = handle_name;
handle->referent = referent;
handle->encoding = xstrdup (encoding);
handle_name = id != NULL ? xstrdup (id) : xasprintf ("`%s'", file_name);
handle = create_handle (id, handle_name, FH_REF_FILE, properties->encoding);
handle->file_name = xstrdup (file_name);
- handle->file_name_encoding = file_name_encoding ? xstrdup (file_name_encoding) : NULL;
+ handle->file_name_encoding = xstrdup_if_nonnull (file_name_encoding);
handle->mode = properties->mode;
handle->line_ends = properties->line_ends;
handle->record_width = properties->record_width;
return handle->encoding;
}
+/* Returns true if A and B refer to the same file or dataset, false
+ otherwise. */
+bool
+fh_equal (const struct file_handle *a, const struct file_handle *b)
+{
+ if (a->referent != b->referent)
+ return false;
+
+ switch (a->referent)
+ {
+ case FH_REF_FILE:
+ {
+ struct file_identity *a_id = fh_get_identity (a);
+ struct file_identity *b_id = fh_get_identity (b);
+
+ int cmp = fh_compare_file_identities (a_id, b_id);
+
+ fh_free_identity (a_id);
+ fh_free_identity (b_id);
+
+ return cmp == 0;
+ }
+
+ case FH_REF_INLINE:
+ return true;
+
+ case FH_REF_DATASET:
+ return a->ds == b->ds;
+
+ default:
+ NOT_REACHED ();
+ }
+}
+
/* Returns the dataset handle associated with HANDLE.
Applicable to only FH_REF_DATASET files. */
struct dataset *
fh_unref (default_handle);
default_handle = new_default_handle;
if (default_handle != NULL)
- fh_ref (default_handle);
+ default_handle = fh_ref (default_handle);
}
\f
/* Information about a file handle's readers or writers. */
HMAP_FOR_EACH_WITH_HASH (lock, struct fh_lock, node, hash, &locks)
{
- if ( 0 == compare_fh_locks (lock, key))
+ if (0 == compare_fh_locks (lock, key))
{
found_lock = true;
break;
}
}
- if ( found_lock )
+ if (found_lock)
{
if (strcmp (lock->type, type))
{
return NULL;
}
lock->open_cnt++;
-
+
free_key (key);
free (key);
found_lock = false;
HMAP_FOR_EACH_WITH_HASH (lock, struct fh_lock, node, hash, &locks)
{
- if ( 0 == compare_fh_locks (lock, key))
+ if (0 == compare_fh_locks (lock, key))
{
found_lock = true;
break;
HMAP_FOR_EACH_WITH_HASH (k, struct fh_lock, node, hash, &locks)
{
- if ( 0 == compare_fh_locks (k, &key))
+ if (0 == compare_fh_locks (k, &key))
{
is_locked = true;
break;
/* 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
+ same file. The caller is responsible for freeing the structure with
fh_free_identity() when finished. */
-struct file_identity *
+static struct file_identity *
fh_get_identity (const struct file_handle *fh)
{
struct file_identity *identity = xmalloc (sizeof *identity);
const char *file_name = fh_get_file_name (fh);
-
+
#if !(defined _WIN32 || defined __WIN32__)
struct stat s;
if (lstat (file_name, &s) == 0)
size_t bufsize;
size_t pathlen = 255;
char *cname = NULL;
- do
+ do
{
bufsize = pathlen;
cname = xrealloc (cname, bufsize);