X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Ffile-handle-def.c;h=09340833be4134d4125eefb96ec2ff1141884a11;hb=26fbb367aadf7701c1392a77ec19033dcaef2378;hp=ba45cb6d9d1bacfcf7fc0e825126b8fc092e2da5;hpb=d62bc5d865e472cd9c20ed54383f29c2a57344ec;p=pspp diff --git a/src/data/file-handle-def.c b/src/data/file-handle-def.c index ba45cb6d9d..09340833be 100644 --- a/src/data/file-handle-def.c +++ b/src/data/file-handle-def.c @@ -24,8 +24,8 @@ #include #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" @@ -91,7 +91,7 @@ static void unname_handle (struct file_handle *); /* 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 *); @@ -116,12 +116,17 @@ fh_done (void) 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); @@ -154,6 +159,8 @@ unname_handle (struct file_handle *handle) 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; @@ -166,6 +173,8 @@ fh_unref (struct file_handle *handle) { if (handle != NULL) { + if (handle == fh_inline_file ()) + return; assert (handle->ref_cnt > 0); if (--handle->ref_cnt == 0) free_handle (handle); @@ -213,10 +222,10 @@ static struct file_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); @@ -253,7 +262,7 @@ fh_create_file (const char *id, const char *file_name, const char *file_name_enc 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; @@ -384,6 +393,40 @@ fh_get_encoding (const struct file_handle *handle) 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 * @@ -410,7 +453,7 @@ fh_set_default_handle (struct file_handle *new_default_handle) fh_unref (default_handle); default_handle = new_default_handle; if (default_handle != NULL) - fh_ref (default_handle); + default_handle = fh_ref (default_handle); } /* Information about a file handle's readers or writers. */ @@ -495,14 +538,14 @@ fh_lock (struct file_handle *h, enum fh_referent mask UNUSED, 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)) { @@ -523,7 +566,7 @@ fh_lock (struct file_handle *h, enum fh_referent mask UNUSED, return NULL; } lock->open_cnt++; - + free_key (key); free (key); @@ -534,7 +577,7 @@ fh_lock (struct file_handle *h, enum fh_referent mask UNUSED, 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; @@ -609,7 +652,7 @@ fh_is_locked (const struct file_handle *handle, enum fh_access access) 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; @@ -702,17 +745,15 @@ struct file_identity /* 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) @@ -764,7 +805,7 @@ fh_get_identity (const struct file_handle *fh) size_t bufsize; size_t pathlen = 255; char *cname = NULL; - do + do { bufsize = pathlen; cname = xrealloc (cname, bufsize);