81ddc517bd6b1c3b0ee5af6bb438752ac3c716c3
chmalee
  Tue Apr 29 09:58:55 2025 -0700
Resolve tusdDataDir hg.conf setting because it may be a symlink, refs Jairo email

diff --git src/hg/lib/userdata.c src/hg/lib/userdata.c
index efcbe4b6b49..fa31df42c1e 100644
--- src/hg/lib/userdata.c
+++ src/hg/lib/userdata.c
@@ -29,54 +29,60 @@
 }
 
 char *emailForUserName(char *userName)
 /* Fetch the email for this user from gbMembers hgcentral table */
 {
 struct sqlConnection *sc = hConnectCentral();
 struct dyString *query = sqlDyStringCreate("select email from gbMembers where userName = '%s'", userName);
 char *email = sqlQuickString(sc, dyStringCannibalize(&query));
 hDisconnectCentral(&sc);
 // this should be freeMem'd:
 return email;
 }
 
 char *getDataDir(char *userName)
 /* Return the full path to the user specific data directory, can be configured via hg.conf
- * on hgwdev, this is /data/apache/userdata/hubspace/hash/userName/
- * on the RR, this is /userdata/hubspace/hash/userName/ */
+ * on hgwdev, this is /data/tusd */
 {
-char *userDataBaseDir = cfgOption("userDataDir");
-if (!userDataBaseDir  || isEmpty(userDataBaseDir))
-    errAbort("trying to save user file but no userDataDir defined in hg.conf");
-if (userDataBaseDir[0] != '/')
-    errAbort("config setting userDataDir must be an absolute path (starting with '/')");
+char *tusdDataBaseDir = cfgOption("tusdDataDir");
+if (!tusdDataBaseDir  || isEmpty(tusdDataBaseDir))
+    errAbort("trying to save user file but no tusdDataDir defined in hg.conf");
+if (tusdDataBaseDir[0] != '/')
+    errAbort("config setting tusdDataDir must be an absolute path (starting with '/')");
 
 char *encUserName = cgiEncode(userName);
 char *userPrefix = md5HexForString(encUserName);
 userPrefix[2] = '\0';
 
 struct dyString *newDataDir = dyStringNew(0);
 dyStringPrintf(newDataDir, "%s/%s/%s/", 
-    userDataBaseDir, userPrefix, encUserName);
+    tusdDataBaseDir, userPrefix, encUserName);
 
 return dyStringCannibalize(&newDataDir);
 }
 
 char *stripDataDir(char *fname, char *userName)
-/* Strips the getDataDir(userName) off of fname */
+/* Strips the getDataDir(userName) off of fname. The dataDir may be a symbolic
+ * link, we will resolve it here. NOTE that this relies on
+ * calling realpath(3) on the fname argument prior to calling stripDataDir() */
 {
-char *dataDir = getDataDir(userName);
+char *dataDir = realpath(getDataDir(userName), NULL);
+if (!dataDir)
+    {
+    // catch a realpath error
+    return NULL;
+    }
 int prefixSize = strlen(dataDir);
 if (startsWith(dataDir, fname))
     {
     char *ret = fname + prefixSize;
     return ret;
     }
 return NULL;
 }
 
 char *getHubDataDir(char *userName, char *hub)
 {
 char *dataDir = getDataDir(userName);
 return catTwoStrings(dataDir, cgiEncode(hub));
 }