<pre style='margin:0'>
Mihai Moldovan (Ionic) pushed a commit to branch master
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/ba8e3a66f9300d66fe30474dc69043f2d7ba6717">https://github.com/macports/macports-base/commit/ba8e3a66f9300d66fe30474dc69043f2d7ba6717</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit ba8e3a66f9300d66fe30474dc69043f2d7ba6717
</span>Author: Mihai Moldovan <ionic@ionic.de>
AuthorDate: Thu Feb 16 08:58:32 2017 +0100

<span style='display:block; white-space:pre;color:#404040;'>    misc: let 'port provides' and trace mode honor the FS case-sensitivity.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Extend Pextlib with functions to fetch the file system case-sensitivity
</span><span style='display:block; white-space:pre;color:#404040;'>    value for a specific path. The TCL interface than uses this function
</span><span style='display:block; white-space:pre;color:#404040;'>    when mapping a file path to a port name is requested.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    cregistry and registry2.0 were updated to perform lookups of paths to
</span><span style='display:block; white-space:pre;color:#404040;'>    port IDs or names case-insensitively if requested by using the "COLLATE
</span><span style='display:block; white-space:pre;color:#404040;'>    NOCASE" option.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    For this to actually work in a timely manner, a new "COLLATE NOCASE"
</span><span style='display:block; white-space:pre;color:#404040;'>    index is needed for the actual_path column. Thus bumping the internal DB
</span><span style='display:block; white-space:pre;color:#404040;'>    version number.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    This fixes bugs where port build systems access files on
</span><span style='display:block; white-space:pre;color:#404040;'>    case-insensitive file systems with different capitalization than
</span><span style='display:block; white-space:pre;color:#404040;'>    registered in our database - thus bypassing trace mode's sanity checks
</span><span style='display:block; white-space:pre;color:#404040;'>    as the files in question are "unknown".
</span>---
 src/cregistry/entry.c              |  43 +++++++-
 src/cregistry/entry.h              |   6 +-
 src/cregistry/sql.c                |  35 ++++++-
 src/pextlib1.0/Pextlib.c           | 200 ++++++++++++++++++++++++++++++++++++-
 src/pextlib1.0/Pextlib.h           |   8 +-
 src/pextlib1.0/tracelib.c          |  21 +++-
 src/registry2.0/entry.c            |  20 +++-
 src/registry2.0/receipt_flat.tcl   |   7 +-
 src/registry2.0/receipt_sqlite.tcl |   6 +-
 src/registry2.0/registry.tcl       |  10 +-
 10 files changed, 332 insertions(+), 24 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/entry.c b/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index c056d66..9dfc782 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,7 +1,7 @@
</span> /*
  * entry.c
  *
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Copyright (c) 2010-2011, 2014 The MacPorts Project
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2010-2011, 2014, 2017 The MacPorts Project
</span>  * Copyright (c) 2007 Chris Pickel <sfiera@macports.org>
  * All rights reserved.
  *
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -39,6 +39,7 @@
</span> #include <sqlite3.h>
 #include <stdlib.h>
 #include <string.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdio.h>
</span> 
 /*
  * TODO: possibly, allow reg_entry_search to take different matching strategies
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -517,16 +518,31 @@ int reg_entry_installed(reg_registry* reg, char* name, reg_entry*** entries,
</span>  *
  * @param [in] reg     registry to search in
  * @param [in] path    path of the file to check ownership of
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param [in] cs      false if check should be performed case-insensitive,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *                     true otherwise
</span>  * @param [out] entry  the owner, or NULL if no active port owns the file
  * @param [out] errPtr on error, a description of the error that occurred
  * @return             true if success; false if failure
  */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-int reg_entry_owner(reg_registry* reg, char* path, reg_entry** entry,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int reg_entry_owner(reg_registry* reg, char* path, int cs, reg_entry** entry,
</span>         reg_error* errPtr) {
     int result = 0;
     sqlite3_stmt* stmt = NULL;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    char* query = "SELECT id FROM registry.files WHERE actual_path=? AND active";
</span>     int lower_bound = 0;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Make sure query_template is as big as the buffer might get. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    const char* query_template = "SELECT id FROM registry.files WHERE (actual_path = ? COLLATE NOCASE) AND active";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    const int query_max_size = strlen(query_template) + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char* query = malloc(query_max_size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!query) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    snprintf(query, query_max_size, "SELECT id FROM registry.files WHERE (actual_path = ? %s) AND active",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             cs ? "" : "COLLATE NOCASE");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>     if ((sqlite3_prepare_v2(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
             && (sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC)
                 == SQLITE_OK)) {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -555,6 +571,7 @@ int reg_entry_owner(reg_registry* reg, char* path, reg_entry** entry,
</span>     if (stmt) {
         sqlite3_finalize(stmt);
     }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(query);
</span>     return result;
 }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -568,12 +585,27 @@ int reg_entry_owner(reg_registry* reg, char* path, reg_entry** entry,
</span>  *
  * @param [in] reg  registry to find file in
  * @param [in] path path of file to get owner of
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param [in] cs   false if check should be performed case-insensitive,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *                  true otherwise
</span>  * @return          id of owner, or 0 for none
  */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-sqlite_int64 reg_entry_owner_id(reg_registry* reg, char* path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sqlite_int64 reg_entry_owner_id(reg_registry* reg, char* path, int cs) {
</span>     sqlite3_stmt* stmt = NULL;
     sqlite_int64 result = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    char* query = "SELECT id FROM registry.files WHERE actual_path=? AND active";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Make sure query_template is as big as the buffer might get. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    const char* query_template = "SELECT id FROM registry.files WHERE (actual_path = ? COLLATE NOCASE) AND active";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    const int query_max_size = strlen(query_template) + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char* query = malloc(query_max_size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!query) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    snprintf(query, query_max_size, "SELECT id FROM registry.files WHERE (actual_path = ? %s) AND active",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             cs ? "" : "COLLATE NOCASE");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>     if ((sqlite3_prepare_v2(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
             && (sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC)
                 == SQLITE_OK)) {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -588,6 +620,7 @@ sqlite_int64 reg_entry_owner_id(reg_registry* reg, char* path) {
</span>     if (stmt) {
         sqlite3_finalize(stmt);
     }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(query);
</span>     return result;
 }
 
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/entry.h b/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;color:#808080;'>index a412ed3..67bbf5f 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/entry.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -61,9 +61,9 @@ int reg_entry_imaged(reg_registry* reg, const char* name, const char* version,
</span> int reg_entry_installed(reg_registry* reg, char* name, reg_entry*** entries,
         reg_error* errPtr);
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-sqlite_int64 reg_entry_owner_id(reg_registry* reg, char* path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-int reg_entry_owner(reg_registry* reg, char* path, reg_entry** entry,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        reg_error* errPtr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+sqlite_int64 reg_entry_owner_id(reg_registry* reg, char* path, int cs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int reg_entry_owner(reg_registry* reg, char* path, int cs,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        reg_entry** entry, reg_error* errPtr);
</span> 
 int reg_entry_propget(reg_entry* entry, char* key, char** value,
         reg_error* errPtr);
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/sql.c b/src/cregistry/sql.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 59b7e9d..8fa681b 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/sql.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/sql.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2,7 +2,7 @@
</span>  * sql.c
  *
  * Copyright (c) 2007 Chris Pickel <sfiera@macports.org>
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Copyright (c) 2012, 2014 The MacPorts Project
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2012, 2014, 2017 The MacPorts Project
</span>  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -134,7 +134,7 @@ int create_tables(sqlite3* db, reg_error* errPtr) {
</span> 
         /* metadata table */
         "CREATE TABLE registry.metadata (key UNIQUE, value)",
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        "INSERT INTO registry.metadata (key, value) VALUES ('version', '1.202')",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        "INSERT INTO registry.metadata (key, value) VALUES ('version', '1.203')",
</span>         "INSERT INTO registry.metadata (key, value) VALUES ('created', strftime('%s', 'now'))",
 
         /* ports table */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -172,6 +172,7 @@ int create_tables(sqlite3* db, reg_error* errPtr) {
</span>         "CREATE INDEX registry.file_port ON files(id)",
         "CREATE INDEX registry.file_path ON files(path)",
         "CREATE INDEX registry.file_actual ON files(actual_path)",
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        "CREATE INDEX registry.file_actual_nocase ON files(actual_path COLLATE NOCASE)",
</span> 
         /* dependency map */
         "CREATE TABLE registry.dependencies ("
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -587,6 +588,34 @@ int update_db(sqlite3* db, reg_error* errPtr) {
</span>             continue;
         }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (sql_version(NULL, -1, version, -1, "1.203") < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             * A new index on files.actual_path with the COLLATE NOCASE attribute
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             * will speed up queries with the equality operator and the COLLATE NOCASE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             * attribute or the LIKE operator. Needed for file mapping to ports
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             * on case-insensitive file systems. Without it, any search operation
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             * will be very, very, very slow.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            static char* version_1_203_queries[] = {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                "CREATE INDEX registry.file_actual_nocase ON files(actual_path COLLATE NOCASE)",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* Update version and commit */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                "UPDATE registry.metadata SET value = '1.203' WHERE key = 'version'",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                "COMMIT",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                NULL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            sqlite3_finalize(stmt);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            stmt = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (!do_queries(db, version_1_203_queries, errPtr)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                rollback_db(db);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            did_update = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>         /* add new versions here, but remember to:
          *  - finalize the version query statement and set stmt to NULL
          *  - do _not_ use "BEGIN" in your query list, since a transaction has
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -596,7 +625,7 @@ int update_db(sqlite3* db, reg_error* errPtr) {
</span>          *  - update the current version number below
          */
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (sql_version(NULL, -1, version, -1, "1.202") > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (sql_version(NULL, -1, version, -1, "1.203") > 0) {
</span>             /* the registry was already upgraded to a newer version and cannot be used anymore */
             reg_throw(errPtr, REG_INVALID, "Version number in metadata table is newer than expected.");
             sqlite3_finalize(stmt);
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/Pextlib.c b/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;color:#808080;'>index d5c7699..0a125cf 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4,7 +4,7 @@
</span>  * Copyright (c) 2002 - 2003 Apple Inc.
  * Copyright (c) 2004 - 2005 Paul Guyot <pguyot@kallisys.net>
  * Copyright (c) 2004 Landon Fuller <landonf@macports.org>
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Copyright (c) 2007 - 2016 The MacPorts Project
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2007 - 2017 The MacPorts Project
</span>  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -52,6 +52,7 @@
</span> #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/param.h>
</span> #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -648,6 +649,201 @@ int SetMaxOpenFilesCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int obj
</span>   return TCL_OK;
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef __APPLE__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/attr.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/mount.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef struct volcaps {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      u_int32_t size;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      vol_capabilities_attr_t volcaps;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+} volcaps_t;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Default function for determining the FS case sensitivity on Darwin.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Using getattrlist().
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int fs_case_sensitive_darwin(const char *path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* TODO: cache mount point CS value. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int ret = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct statfs f = { 0 };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct attrlist attrlist = { 0 };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    volcaps_t volcaps = { 0 };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == statfs(path, &f)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    attrlist.volattr = ATTR_VOL_CAPABILITIES;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == getattrlist(f.f_mntonname, &attrlist, &volcaps, sizeof(volcaps), 0)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((attrlist.volattr & ATTR_VOL_CAPABILITIES) == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((volcaps.volcaps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* capabilities bit for case-sensitivity valid */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ret = (volcaps.volcaps.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE) != 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __APPLE__ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Fallback function to determine FS case sensitivity.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * lstat()'s the given path, its lowercase and uppercase versions.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * If all three versions exist and are the same file (as determined
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * by their inode numbers), then the FS is case-insensitive and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * 0 is returned.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Otherwise, the FS is case-sensitive and 1 is returned.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * In case of errors (e.g., if the original file does not exist),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * -1 is returned.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int fs_case_sensitive_fallback(const char *path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* TODO: fetch mount point and cache mount point CS value. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int ret = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char *lowercase_path = strdup(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char *uppercase_path = strdup(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((!lowercase_path) || (!uppercase_path)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(lowercase_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(uppercase_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    for (char *tmp_ptr_low = lowercase_path,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+              *tmp_ptr_up  = uppercase_path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         *tmp_ptr_low && *tmp_ptr_up; /* Since both are copies of the same string,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                         should be the same anyway. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         ++tmp_ptr_low, ++tmp_ptr_up) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        *tmp_ptr_low = tolower(*tmp_ptr_low);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        *tmp_ptr_up  = toupper(*tmp_ptr_up);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct stat path_stat = { 0 },
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           lowercase_path_stat = { 0 },
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           uppercase_path_stat = { 0 };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == lstat(path, &path_stat)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(lowercase_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(uppercase_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((0 == strcmp(path, lowercase_path)) &&
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (0 == strcmp(path, uppercase_path))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         * All three strings are equal. We can't check for
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         * FS case-sensitivity in this case.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         * And it doesn't matter either way!
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ret = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (-1 == lstat(lowercase_path, &lowercase_path_stat)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* Lowercased version doesn't exist, CS. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ret = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        else if (-1 == lstat(uppercase_path, &uppercase_path_stat)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* Uppercased version doesn't exist, CS. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ret = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             * All three files exists, but we must make sure they
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             * are really the same file.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (path_stat.st_ino == lowercase_path_stat.st_ino) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * Lowercase and original path files are the same,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * but that's not too surprising since most passed
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * values will already be in lowercased form.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * Also check the uppercase variant.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * The special case that all three versions are
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * actually the same (can happen if a path consists
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * of case-agnostic Unicode characters only) is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 * already handled above.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if (path_stat.st_ino == uppercase_path_stat.st_ino) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    /* Truly case-insensitive! */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    ret = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     * Bummer, lowercased version matches the original
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     * file's inode number, but the uppercased one
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     * doesn't. CS.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    ret = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* Just similar-named, still a case-sensitive FS. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ret = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(lowercase_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(uppercase_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Determines FS case-sensitivity for a specific path.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Returns 1 if the FS is case-sensitive, 0 otherwise.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Errors out if the case-sensitivity could not be determined.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int FSCaseSensitiveCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    Tcl_Obj *tcl_result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int ret = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (objc != 2) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_WrongNumArgs(interp, 1, objv, "path");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char *path = Tcl_GetString(objv[1]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef __APPLE__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ret = fs_case_sensitive_darwin(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __APPLE__ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == ret) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ret = fs_case_sensitive_fallback(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == ret) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_SetResult(interp, "unable to determine FS case-sensitivity", TCL_STATIC);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        tcl_result = Tcl_NewBooleanObj(ret);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_SetObjResult(interp, tcl_result);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_OK;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> int Pextlib_Init(Tcl_Interp *interp)
 {
     if (Tcl_InitStubs(interp, "8.4", 0) == NULL)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -710,6 +906,8 @@ int Pextlib_Init(Tcl_Interp *interp)
</span>     Tcl_CreateObjCommand(interp, "check_broken_dns", CheckBrokenDNSCmd, NULL, NULL);
     Tcl_CreateObjCommand(interp, "set_max_open_files", SetMaxOpenFilesCmd, NULL, NULL);
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    Tcl_CreateObjCommand(interp, "fs_case_sensitive", FSCaseSensitiveCmd, NULL, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>     if (Tcl_PkgProvide(interp, "Pextlib", "1.0") != TCL_OK)
         return TCL_ERROR;
 
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/Pextlib.h b/src/pextlib1.0/Pextlib.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 4ab4fb3..aaee1fa 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/Pextlib.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/Pextlib.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,7 +1,7 @@
</span> /*
  * Pextlib.h
  *
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Copyright (c) 2009 The MacPorts Project
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2009, 2017 The MacPorts Project
</span>  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -35,3 +35,9 @@ void ui_msg(Tcl_Interp *interp, const char *format, ...) __attribute__((format(p
</span> void ui_notice(Tcl_Interp *interp, const char *format, ...) __attribute__((format(printf, 2, 3)));
 void ui_info(Tcl_Interp *interp, const char *format, ...) __attribute__((format(printf, 2, 3)));
 void ui_debug(Tcl_Interp *interp, const char *format, ...) __attribute__((format(printf, 2, 3)));
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef __APPLE__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int fs_case_sensitive_darwin(const char *path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __APPLE__ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int fs_case_sensitive_fallback(const char *path);
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/tracelib.c b/src/pextlib1.0/tracelib.c
</span><span style='display:block; white-space:pre;color:#808080;'>index f27acbb..cb9c146 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/tracelib.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/tracelib.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4,7 +4,7 @@
</span>  * tracelib.c
  *
  * Copyright (c) 2007-2008 Eugene Pimenov (GSoC)
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Copyright (c) 2008-2010, 2012-2015 The MacPorts Project
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2008-2010, 2012-2015, 2017 The MacPorts Project
</span>  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -604,6 +604,7 @@ static void sandbox_violation(int sock UNUSED, const char *path, sandbox_violati
</span> static void dep_check(int sock, char *path) {
     char *port = 0;
     char *t;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    int fs_cs = -1;
</span>     reg_registry *reg;
     reg_entry entry;
     reg_error error;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -614,10 +615,26 @@ static void dep_check(int sock, char *path) {
</span>         answer(sock, "#");
     }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef __APPLE__
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    fs_cs = fs_case_sensitive_darwin(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __APPLE__ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == fs_cs) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fs_cs = fs_case_sensitive_fallback(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (-1 == fs_cs) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         * Unable to determine FS case-sensitivity.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         * Assume the worst case (case-insensitive.)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fs_cs = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>     /* find the port id */
     entry.reg = reg;
     entry.proc = NULL;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    entry.id = reg_entry_owner_id(reg, path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    entry.id = reg_entry_owner_id(reg, path, fs_cs);
</span>     if (entry.id == 0) {
         /* file isn't known to MacPorts */
         answer(sock, "?");
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/entry.c b/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index f13d3b9..0647816 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/entry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -437,22 +437,32 @@ static int entry_installed(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]){
</span> 
 
 /*
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * registry::entry owner filename
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * registry::entry owner filename [cs = true]
</span>  *
  * Returns the port that owns the given filename (empty string if none).
  */
 static int entry_owner(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
     reg_registry* reg = registry_for(interp, reg_attached);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (objc != 3) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        Tcl_WrongNumArgs(interp, 2, objv, "path");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int cs = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((objc < 3) || (objc > 4)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_WrongNumArgs(interp, 2, objv, "path ?cs?");
</span>         return TCL_ERROR;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    } else if (reg == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (objc == 4) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (Tcl_GetBooleanFromObj(interp, objv[3], &cs) != TCL_OK) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (reg == NULL) {
</span>         return TCL_ERROR;
     } else {
         char* path = Tcl_GetString(objv[2]);
         reg_entry* entry;
         reg_error error;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (reg_entry_owner(reg, path, &entry, &error)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (reg_entry_owner(reg, path, cs, &entry, &error)) {
</span>             if (entry == NULL) {
                 return TCL_OK;
             } else {
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/receipt_flat.tcl b/src/registry2.0/receipt_flat.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 85c8254..4c488e9 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/receipt_flat.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/receipt_flat.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -600,13 +600,18 @@ proc open_file_map {{readonly 0}} {
</span> # open the file map if required.
 #
 # - file       the file to test
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# - cs          boolean value indicating a case-sensitive search
</span> # return the 0 if the file is not registered, the name of the port otherwise.
 #
<span style='display:block; white-space:pre;background:#ffe0e0;'>-proc file_registered {file} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc file_registered {file cs} {
</span>   variable file_map
 
        open_file_map 1
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {$cs} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           ui_warn "Case-sensitive search not implemented."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>   if {[::filemap exists file_map $file]} {
                return [::filemap get file_map $file]
        } else {
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/receipt_sqlite.tcl b/src/registry2.0/receipt_sqlite.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index b6797c1..7adc2cb 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/receipt_sqlite.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/receipt_sqlite.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -123,10 +123,12 @@ proc entry_exists_for_name {name} {
</span> #
 # @param file
 #        The full path to the file to be tested.
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# @param cs
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#        Boolean value indicating a case-sensitive check.
</span> # @return 0 if the file is not registered to any port. The name of the port
 #         otherwise.
<span style='display:block; white-space:pre;background:#ffe0e0;'>-proc file_registered {file} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    set port [registry::entry owner $file]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc file_registered {file cs} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set port [registry::entry owner $file $cs]
</span>     if {$port ne ""} {
         return [$port name]
     } else {
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/registry.tcl b/src/registry2.0/registry.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 6da2448..0bfb2bd 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/registry.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/registry.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -38,6 +38,7 @@ package require receipt_sqlite 1.0
</span> package require portimage 2.0
 package require registry_uninstall 2.0
 package require msgcat
<span style='display:block; white-space:pre;background:#e0ffe0;'>+package require Pextlib 1.0
</span> 
 namespace eval registry {
     variable lockfd
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -236,7 +237,14 @@ proc open_file_map {args} {
</span> 
 proc file_registered {file} {
        global macports::registry.format
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        return [${macports::registry.format}::file_registered $file]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   set cs false
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if {[catch {fs_case_sensitive $file} cs]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           ui_debug "Unable to get file system case-sensitivity of file $file, assuming worst case (case-insensitive.)"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           set cs false
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   return [${macports::registry.format}::file_registered $file $cs]
</span> }
 
 proc port_registered {name} {
</pre><pre style='margin:0'>

</pre>