Sync
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 22 Jun 2006 10:12:26 +0000 (10:12 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 22 Jun 2006 10:12:26 +0000 (10:12 +0000)
org.gridsite.core/interface/gridsite.h
org.gridsite.core/src/Makefile
org.gridsite.core/src/grst_err.c [new file with mode: 0644]
org.gridsite.core/src/grst_gacl.c
org.gridsite.core/src/grst_x509.c
org.gridsite.core/src/grst_xacml.c
org.gridsite.core/src/mod_gridsite.c
org.gridsite.core/src/slashgrid.c
org.gridsite.core/src/slashgrid.init

index caa3a14..0fa2640 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2002-5, Andrew McNab, University of Manchester
+   Copyright (c) 2002-6, Andrew McNab, University of Manchester
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or
 /// No such file or directory
 #define GRST_RET_NO_SUCH_FILE  1003
 
+
+// #define GRSTerrorLog(GRSTerrorLevel, GRSTerrorFmt, ...) if (GRSTerrorLogFunc != NULL) (GRSTerrorLogFunc)(__FILE__, __LINE__, GRSTerrorLevel, GRSTerrorFmt, __VA_ARGS__)
+
+#define GRSTerrorLog(GRSTerrorLevel, ...) if (GRSTerrorLogFunc != NULL) (GRSTerrorLogFunc)(__FILE__, __LINE__, GRSTerrorLevel, __VA_ARGS__)
+
+void (*GRSTerrorLogFunc)(char *, int, int, char *, ...);
+
+/* these levels are the same as Unix syslog() and Apache ap_log_error() */
+
+#define GRST_LOG_EMERG   0
+#define GRST_LOG_ALERT   1
+#define GRST_LOG_CRIT    2
+#define GRST_LOG_ERR     3
+#define GRST_LOG_WARNING 4
+#define GRST_LOG_NOTICE  5
+#define GRST_LOG_INFO    6
+#define GRST_LOG_DEBUG   7
+
 typedef struct { char                      *name;
                  char                      *value;
                  void                      *next;  } GRSTgaclNamevalue;
@@ -94,14 +112,14 @@ typedef struct { GRSTgaclCred *firstcred;
 #define GRST_PERM_ALL   31
 
 /* DO NOT USE PermIsNone!! */
-#define GRSTgaclPermIsNone(perm)    (perm == 0)
+#define GRSTgaclPermIsNone(perm)    ((perm) == 0)
 
-#define GRSTgaclPermHasNone(perm)    (perm == 0)
-#define GRSTgaclPermHasRead(perm)  ((perm & GRST_PERM_READ ) != 0)
-#define GRSTgaclPermHasExec(perm)  ((perm & GRST_PERM_EXEC ) != 0)
-#define GRSTgaclPermHasList(perm)  ((perm & GRST_PERM_LIST ) != 0)
-#define GRSTgaclPermHasWrite(perm) ((perm & GRST_PERM_WRITE) != 0)
-#define GRSTgaclPermHasAdmin(perm) ((perm & GRST_PERM_ADMIN) != 0)
+#define GRSTgaclPermHasNone(perm)    ((perm) == 0)
+#define GRSTgaclPermHasRead(perm)  (((perm) & GRST_PERM_READ ) != 0)
+#define GRSTgaclPermHasExec(perm)  (((perm) & GRST_PERM_EXEC ) != 0)
+#define GRSTgaclPermHasList(perm)  (((perm) & GRST_PERM_LIST ) != 0)
+#define GRSTgaclPermHasWrite(perm) (((perm) & GRST_PERM_WRITE) != 0)
+#define GRSTgaclPermHasAdmin(perm) (((perm) & GRST_PERM_ADMIN) != 0)
 
 #define GRST_ACTION_ALLOW 0
 #define GRST_ACTION_DENY  1
@@ -127,6 +145,7 @@ struct GRSTasn1TagList { char treecoords[GRST_ASN1_MAXCOORDLEN+1];
 #define GRST_HTTP_PORT         777
 #define GRST_HTTPS_PORT                488
 #define GRST_HTCP_PORT         777
+#define GRST_GSIFTP_PORT       2811
                          
 #define GRSThtcpNOPop 0
 #define GRSThtcpTSTop 1
index 026b9f5..a847bdb 100644 (file)
@@ -65,12 +65,21 @@ build-lib: libgridsite_globus.so.$(VERSION) libgridsite_globus.a \
 
 # First, normal versions using system OpenSSL rather than Globus OpenSSL
 
-libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o
+libgridsite.so.$(VERSION): grst_err.o grst_x509.o grst_gacl.o grst_xacml.o \
+                           grst_http.o grst_asn1.o grst_htcp.o
        gcc -shared -Wl,-soname,libgridsite.so.$(MINOR_VERSION) \
-         -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o
+         -o libgridsite.so.$(PATCH_VERSION) -lcrypto `xml2-config --libs` \
+         grst_err.o grst_x509.o grst_gacl.o grst_xacml.o grst_http.o \
+         grst_asn1.o grst_htcp.o 
+       ln -sf libgridsite.so.$(VERSION) libgridsite.so
+       ln -sf libgridsite.so.$(VERSION) libgridsite.so.$(MINOR_VERSION)
 
-libgridsite.a: grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o
-       ar src libgridsite.a grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o
+libgridsite.a: grst_err.o grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o
+       ar src libgridsite.a grst_err.o grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o grst_htcp.o
+
+grst_err.o: grst_err.c ../interface/gridsite.h
+       gcc -g $(MYCFLAGS) \
+           -c grst_err.c
 
 grst_x509.o: grst_x509.c ../interface/gridsite.h
        gcc -g $(MYCFLAGS) \
@@ -100,16 +109,23 @@ grst_htcp.o: grst_htcp.c ../interface/gridsite.h
 
 ifdef OPENSSL_GLOBUS_LIBS
 
-libgridsite_globus.so.$(VERSION): \
+libgridsite_globus.so.$(VERSION): grst_err_globus.o \
                grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o \
-               grst_asn1_globus.o grst_xacml_globus.o grst_htcp_globus.o
+               grst_asn1_globus.o grst_xacml_globus.o grst_htcp_globus.o 
        gcc -shared -Wl,-soname,libgridsite_globus.so.$(MINOR_VERSION) \
          -o libgridsite_globus.so.$(PATCH_VERSION) \
-         grst_x509_globus.o grst_gacl_globus.o grst_xacml_globus.o grst_http_globus.o grst_asn1_globus.o
+         grst_err.o grst_x509_globus.o grst_gacl_globus.o grst_xacml_globus.o \
+         grst_http_globus.o grst_asn1_globus.o
+       ln -sf libgridsite_globus.so.$(VERSION) libgridsite_globus.so
 
-libgridsite_globus.a: grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o
+libgridsite_globus.a: grst_err_globus.o grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o
        ar src libgridsite_globus.a \
-               grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o
+               grst_err_globus.o grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o
+
+grst_err_globus.o: grst_err.c ../interface/gridsite.h
+       gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \
+           -c grst_err.c \
+           -o grst_err_globus.o
 
 grst_x509_globus.o: grst_x509.c ../interface/gridsite.h
        gcc -g $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \
@@ -158,19 +174,22 @@ gsexec:   gsexec.c gsexec.h
 urlencode: urlencode.c libgridsite.a
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
             -o urlencode urlencode.c -L. \
-            -I/usr/kerberos/include -lgridsite
+            -I/usr/kerberos/include \
+            -lgridsite
 
 htcp: htcp.c libgridsite.a
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
            -o htcp htcp.c -L. \
            -I/usr/kerberos/include \
-            `curl-config --cflags` `curl-config --libs` -lgridsite
+            `curl-config --cflags` `curl-config --libs` \
+            -lgridsite
 
 gridsite-copy.cgi: gridsite-copy.c libgridsite.a
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
            -o gridsite-copy.cgi gridsite-copy.c -L. \
            -I/usr/kerberos/include \
-            `curl-config --cflags` `curl-config --libs` -lgridsite
+            `curl-config --cflags` `curl-config --libs` \
+            -lgridsite
 
 mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.a
        gcc -g $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \
@@ -200,13 +219,15 @@ showx509exts: showx509exts.c libgridsite.a
             -I/usr/kerberos/include \
             -lgridsite \
             -lssl -lcrypto -lxml2 -lz -lm
+
+
  
-slashgrid: slashgrid.c
+slashgrid: slashgrid.c libgridsite.so.$(VERSION)
        gcc -g -o slashgrid -lfuse -lpthread slashgrid.c \
+          $(MYCFLAGS) $(MYLDFLAGS) `xml2-config --cflags` \
           -D_FILE_OFFSET_BITS=64 -D_REENTRANT -DFUSE_USE_VERSION=22 \
-          $(MYCFLAGS) $(MYLDFLAGS) \
           -I/usr/kerberos/include `curl-config --cflags` \
-          `curl-config --libs` -lgridsite -lxml2
+          -L. `curl-config --libs` -lgridsite
 
 apidoc:
        date
diff --git a/org.gridsite.core/src/grst_err.c b/org.gridsite.core/src/grst_err.c
new file mode 100644 (file)
index 0000000..5c541b5
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+   Copyright (c) 2002-6, Andrew McNab, University of Manchester
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or
+   without modification, are permitted provided that the following
+   conditions are met:
+
+   o Redistributions of source code must retain the above
+     copyright notice, this list of conditions and the following
+     disclaimer. 
+   o Redistributions in binary form must reproduce the above
+     copyright notice, this list of conditions and the following
+     disclaimer in the documentation and/or other materials
+     provided with the distribution. 
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+
+   ---------------------------------------------------------------
+    For more information about GridSite: http://www.gridsite.org/
+   ---------------------------------------------------------------
+*/ 
+
+#define _GNU_SOURCE
+
+#include "gridsite.h"
+
+/* Little piece of GRSTerror in GRSTgacl */
+
+void (*GRSTerrorLogFunc)(char *, int, int, char *, ...) = NULL;
+
index 336c853..667d5d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-   Copyright (c) 2002-3, Andrew McNab, University of Manchester
+   Copyright (c) 2002-6, Andrew McNab, University of Manchester
    All rights reserved.
 
    Redistribution and use in source and binary forms, with or
@@ -53,7 +53,7 @@
 #include "gridsite.h"
 
 /*                                                                      *
- * Global variables, shared by all GACL functions by private to libgacl *
+ * Global variables, shared by all GACL functions but private to libgacl *
  *                                                                      */
  
 char     *grst_perm_syms[] =  { "none",
@@ -572,8 +572,9 @@ static GRSTgaclCred *GRSTgaclCredParse(xmlNodePtr cur)
   
   for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
      {
-       GRSTgaclCredAddValue(cred, (char *) cur2->name, 
-                           (char *) xmlNodeGetContent(cur2));     
+       if (!xmlIsBlankNode(cur2))
+        GRSTgaclCredAddValue(cred, (char *) cur2->name, 
+                             (char *) xmlNodeGetContent(cur2));     
      }
 
   return cred;
@@ -599,21 +600,32 @@ static GRSTgaclEntry *GRSTgaclEntryParse(xmlNodePtr cur)
   
   while (cur != NULL)
        {
-         if (xmlStrcmp(cur->name, (const xmlChar *) "allow") == 0)
+         if (xmlIsBlankNode(cur))
+           {
+             cur=cur->next;
+             continue;
+           }
+         else if (xmlStrcmp(cur->name, (const xmlChar *) "allow") == 0)
            {
              for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
-              for (i=0; grst_perm_syms[i] != NULL; ++i)
-               if (xmlStrcmp(cur2->name, 
+                if (!xmlIsBlankNode(cur2))
+                  {                
+                    for (i=0; grst_perm_syms[i] != NULL; ++i)
+                     if (xmlStrcmp(cur2->name, 
                              (const xmlChar *) grst_perm_syms[i]) == 0)
-                     GRSTgaclEntryAllowPerm(entry, grst_perm_vals[i]);
+                       GRSTgaclEntryAllowPerm(entry, grst_perm_vals[i]);
+                  }
            }
          else if (xmlStrcmp(cur->name, (const xmlChar *) "deny") == 0)
            {
              for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
-              for (i=0; grst_perm_syms[i] != NULL; ++i)
-               if (xmlStrcmp(cur2->name, 
+                if (!xmlIsBlankNode(cur2))
+                  {
+                    for (i=0; grst_perm_syms[i] != NULL; ++i)
+                     if (xmlStrcmp(cur2->name, 
                              (const xmlChar *) grst_perm_syms[i]) == 0)
-                     GRSTgaclEntryDenyPerm(entry, grst_perm_vals[i]);
+                       GRSTgaclEntryDenyPerm(entry, grst_perm_vals[i]);
+                  }
            }
          else if ((cred = GRSTgaclCredParse(cur)) != NULL) 
            {
@@ -642,22 +654,37 @@ GRSTgaclAcl *GRSTgaclAclLoadFile(char *filename)
   xmlNodePtr  cur;
   GRSTgaclAcl    *acl;
 
+  GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile() starting");
+
+  if (filename == NULL) 
+    {
+      GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile() cannot open a NULL filename");
+      return NULL;
+    }
+
   doc = xmlParseFile(filename);
-  if (doc == NULL) return NULL;
+  if (doc == NULL) 
+    {
+      GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile failed to open ACL file %s", filename);
+      return NULL;
+    }
 
   cur = xmlDocGetRootElement(doc);
   if (cur == NULL) 
     {
-      xmlFreeDoc(doc);      
+      xmlFreeDoc(doc);
+      GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile failed to parse root of ACL file %s", filename);
       return NULL;
     }
 
   if (!xmlStrcmp(cur->name, (const xmlChar *) "Policy")) 
     { 
+      GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile parsing XACML");
       acl=GRSTxacmlAclParse(doc, cur, acl);
     }
   else if (!xmlStrcmp(cur->name, (const xmlChar *) "gacl")) 
     {
+      GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile parsing GACL");
       acl=GRSTgaclAclParse(doc, cur, acl);
     }
   else /* ACL format not recognised */
@@ -680,15 +707,18 @@ GRSTgaclAcl *GRSTgaclAclParse(xmlDocPtr doc, xmlNodePtr cur, GRSTgaclAcl *acl)
 
   while (cur != NULL)
        {
-         entry = GRSTgaclEntryParse(cur);
-         if (entry == NULL)
+         if (!xmlIsBlankNode(cur))
            {
-             GRSTgaclAclFree(acl);
-             xmlFreeDoc(doc);
-             return NULL;
-           }
+             entry = GRSTgaclEntryParse(cur);
+             if (entry == NULL)
+               {
+                 GRSTgaclAclFree(acl);
 
-         GRSTgaclAclAddEntry(acl, entry);
+                 return NULL;
+               }
+
+             GRSTgaclAclAddEntry(acl, entry);
+           }
 
          cur=cur->next;
        }
index af871ae..31a89c9 100644 (file)
@@ -76,7 +76,8 @@ int GRSTx509NameCmp(char *a, char *b)
  *  would ideally be done with OIDs/values. In particular, we equate
  *  "/Email=" == "/emailAddress=" to deal with this important change
  *  between OpenSSL 0.9.6 and 0.9.7. 
- *  Other than that, it is currently the same as ordinary strcmp(3).
+ *  Other than that, it is currently the same as ordinary strcasecmp(3)
+ *  (for consistency with EDG/LCG/EGEE gridmapdir case insensitivity.)
  */
 {
    int   ret;
@@ -96,7 +97,7 @@ int GRSTx509NameCmp(char *a, char *b)
           p[1] = 'E';
         }
 
-   ret = strcmp(aa, bb);
+   ret = strcasecmp(aa, bb);
 
    free(aa);
    free(bb);
index c38424f..c4c88ee 100644 (file)
@@ -231,7 +231,7 @@ static GRSTgaclEntry *GRSTxacmlEntryParse(xmlNodePtr cur)
 
 GRSTgaclAcl *GRSTxacmlAclLoadFile(char *filename)
 {
-xmlDocPtr   doc;
+  xmlDocPtr   doc;
   xmlNodePtr  cur;
   GRSTgaclAcl    *acl;
 
@@ -245,7 +245,7 @@ xmlDocPtr   doc;
   else if (!xmlStrcmp(cur->name, (const xmlChar *) "gacl")) {acl=GRSTgaclAclParse(doc, cur, acl);}
   else /* ACL format not recognised */
     {
-      free(doc);
+      xmlFreeDoc(doc);
       free(cur);
       return NULL;
     }
@@ -283,7 +283,6 @@ GRSTgaclAcl *GRSTxacmlAclParse(xmlDocPtr doc, xmlNodePtr cur, GRSTgaclAcl *acl)
       if (entry == NULL)
       {
         GRSTgaclAclFree(acl);
-        xmlFreeDoc(doc);
         return NULL;
       }
       else GRSTgaclAclAddEntry(acl, entry);
index 1321eec..328c807 100644 (file)
@@ -112,12 +112,13 @@ struct sitecast_group
 #define GRST_SITECAST_ALIASES 32
    
 struct sitecast_alias
-   { const char *sitecast_url; const char *local_path; server_rec *server; };
+   { const char *sitecast_url; const char *scheme; int port; 
+     const char *local_path; server_rec *server; };
 
 /* Globals, defined by main server directives in httpd.conf  
    These are assigned default values in create_gridsite_srv_config() */
 
-int                    gridhttpport = 0;
+int gridhttpport = 0; /* set by create_gridsite_srv_config, used as flag */
 char                    *sessionsdir = NULL;
 char                   *sitecastdnlists = NULL;
 struct sitecast_group  sitecastgroups[GRST_SITECAST_GROUPS+1];
@@ -1421,7 +1422,8 @@ static void *create_gridsite_srv_config(apr_pool_t *p, server_rec *s)
 {
     int i;
 
-    if (!(s->is_virtual))
+    /* only run once (in base server) */
+    if (!(s->is_virtual) && (gridhttpport == 0))
       {
         gridhttpport = GRST_HTTP_PORT;
       
@@ -1438,14 +1440,17 @@ static void *create_gridsite_srv_config(apr_pool_t *p, server_rec *s)
                                       /* GridSiteCastUniPort udp-port */
 
         for (i=1; i <= GRST_SITECAST_GROUPS; ++i)
-                   sitecastgroups[i].port = 0;
-                                      /* GridSiteCastGroup mcast-list */
+           {
+             sitecastgroups[i].port = 0; /* GridSiteCastGroup mcast-list */
+           }
 
         for (i=1; i <= GRST_SITECAST_ALIASES; ++i)
            {
              sitecastaliases[i].sitecast_url = NULL;
+             sitecastaliases[i].port         = 0;
+             sitecastaliases[i].scheme       = NULL;
              sitecastaliases[i].local_path   = NULL;
-             sitecastaliases[i].server       = NULL;                   
+             sitecastaliases[i].server       = NULL;
            }                              /* GridSiteCastAlias url path */
       }
 
@@ -1824,7 +1829,8 @@ static const char *mod_gridsite_take1_cmds(cmd_parms *a, void *cfg,
 static const char *mod_gridsite_take2_cmds(cmd_parms *a, void *cfg,
                                        const char *parm1, const char *parm2)
 {
-    int i;
+    int   i;
+    char *p, *q;
     
     if (strcasecmp(a->cmd->name, "GridSiteUserGroup") == 0)
     {
@@ -1864,9 +1870,34 @@ static const char *mod_gridsite_take2_cmds(cmd_parms *a, void *cfg,
          {
            if (sitecastaliases[i].sitecast_url == NULL)
              {
-               sitecastaliases[i].sitecast_url  = parm1;
-               sitecastaliases[i].local_path    = parm2;
-               sitecastaliases[i].server        = a->server;              
+               sitecastaliases[i].scheme = apr_pstrdup(a->pool, parm1);
+
+               if (((p = index(sitecastaliases[i].scheme, ':')) == NULL)
+                   || (p[1] != '/') || (p[2] != '/'))
+                 return "GridSiteCastAlias URL must begin with scheme (http/https/gsiftp/...) and ://";
+
+               *p = '\0';
+               ++p;
+               while (*p == '/') ++p;
+             
+               if ((q = index(p, '/')) == NULL)
+                return "GridSiteCastAlias URL must be of form scheme://domain:port/dirs";
+
+               *q = '\0';
+
+               p = index(p, ':');
+               if (p == NULL)
+                 {
+                   return "GridSiteCastAlias URL must include the port number";
+                 }
+
+               if (sscanf(p, ":%d", &(sitecastaliases[i].port)) != 1)
+                 return "Unable to parse numeric port number in GridSiteCastAlias";
+
+               sitecastaliases[i].sitecast_url  = apr_pstrdup(a->pool, parm1);
+               sitecastaliases[i].local_path    = apr_pstrdup(a->pool, parm2);
+               sitecastaliases[i].server        = a->server;
+
                break;
              }
          }
@@ -2735,42 +2766,13 @@ void sitecast_handle_TST_GET(server_rec *main_server,
                              GRSThtcpMessage *htcp_mesg, int igroup,
                              struct sockaddr_in *client_addr_ptr)
 {
-  int             i, outbuf_len, ialias, port;
+  int             i, outbuf_len, ialias;
   char            *filename, *outbuf, *location, *local_uri = NULL;
   struct stat     statbuf;
-  SSLSrvConfigRec *ssl_srv;
   
-  /* check sanity of requested uri */
-
-  if (strncmp(htcp_mesg->uri->text, "http://", 7) == 0)
-    {
-      for (i=7; i < GRSThtcpCountstrLen(htcp_mesg->uri); ++i)
-         if (htcp_mesg->uri->text[i] == '/') 
-           {
-             local_uri = &(htcp_mesg->uri->text[i]);
-             break;
-           }
-    }
-  else if (strncmp(htcp_mesg->uri->text, "https://", 8) == 0)
-    {
-      for (i=8; i < GRSThtcpCountstrLen(htcp_mesg->uri); ++i)
-         if (htcp_mesg->uri->text[i] == '/') 
-           {
-             local_uri = &(htcp_mesg->uri->text[i]);
-             break;
-           }
-    }
-
-  if (local_uri == NULL)
-    {
-      ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
-              "SiteCast responder only handles http(s):// (%*s requested by %s:%d)",
-                        GRSThtcpCountstrLen(htcp_mesg->uri),
-                        htcp_mesg->uri->text,
-                        inet_ntoa(client_addr_ptr->sin_addr),
-                        ntohs(client_addr_ptr->sin_port));      
-      return;
-    }
+  ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
+        "SiteCast responder received TST GET with uri %s", 
+        htcp_mesg->uri->text, GRSThtcpCountstrLen(htcp_mesg->uri));
 
   /* find if any GridSiteCastAlias lines match */
 
@@ -2796,9 +2798,9 @@ void sitecast_handle_TST_GET(server_rec *main_server,
       
       return; /* no match */
     }
-
+    
   /* convert URL to filename, using alias mapping */
-  
+
   asprintf(&filename, "%s%*s", 
            sitecastaliases[ialias].local_path,
            GRSThtcpCountstrLen(htcp_mesg->uri) 
@@ -2806,19 +2808,12 @@ void sitecast_handle_TST_GET(server_rec *main_server,
            &(htcp_mesg->uri->text[strlen(sitecastaliases[ialias].sitecast_url)]) );
 
   if (stat(filename, &statbuf) == 0) /* found file */
-    { 
-      ssl_srv = (SSLSrvConfigRec *)
-       ap_get_module_config(sitecastaliases[ialias].server->module_config,
-                                                             &ssl_module);
-
-      port = sitecastaliases[ialias].server->addrs->host_port;
-      if (port == 0) port = ((ssl_srv != NULL) && (ssl_srv->enabled))
-                                 ? GRST_HTTPS_PORT : GRST_HTTP_PORT;
-                
-      asprintf(&location, "Location: http%s://%s:%d%s\r\n",
-                  ((ssl_srv != NULL) && (ssl_srv->enabled)) ? "s" : "",
-                  sitecastaliases[ialias].server->server_hostname, port,
-                  local_uri);
+    {
+      asprintf(&location, "Location: %s://%s:%d/%s\r\n",
+                  sitecastaliases[ialias].scheme,
+                  sitecastaliases[ialias].server->server_hostname,
+                  sitecastaliases[ialias].port,
+      &(htcp_mesg->uri->text[strlen(sitecastaliases[ialias].sitecast_url)]) );
 
       ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
             "SiteCast finds %*s at %s, redirects with %s",
@@ -2954,6 +2949,9 @@ void sitecast_responder(server_rec *main_server)
 
   /* initialise multicast listener sockets next */
 
+   ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
+          "SiteCast UDP Responder group [1].port %d", sitecastgroups[1].port);
+
   for (i=1; (i <= GRST_SITECAST_GROUPS) && 
             (sitecastgroups[i].port != 0); ++i)
      {
@@ -2994,6 +2992,17 @@ void sitecast_responder(server_rec *main_server)
         sitecastgroups[i].quad3, sitecastgroups[i].quad4, sitecastgroups[i].port);
      }
 
+  for (i=0; i < GRST_SITECAST_ALIASES ; ++i)
+     {
+       ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
+                          "SiteCast alias for %s (%s,%d) to %s (%s)",
+                          sitecastaliases[i].sitecast_url,
+                          sitecastaliases[i].scheme,
+                          sitecastaliases[i].port,
+                          sitecastaliases[i].local_path,
+                          sitecastaliases[i].server->server_hostname);
+     }
+
   while (1) /* **** main listening loop **** */
        {
          /* set up bitmasks for select */
@@ -3152,7 +3161,7 @@ static void mod_gridsite_child_init(apr_pool_t *pPool, server_rec *pServer)
 
    /* expire old ssl creds files */
                                     
-   if (sc != NULL) // && sc->enabled)
+   if (sc != NULL)
      {
        cutoff_time = apr_time_now() 
                       - apr_time_from_sec(sc->session_cache_timeout);
index 5e6518f..1a7cbc0 100644 (file)
@@ -53,6 +53,9 @@
 #include <malloc.h>
 #include <curl/curl.h>
 #include <pthread.h>
+#include <pwd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 #include <fuse.h>
 
@@ -136,7 +139,10 @@ struct grst_handle { pthread_mutex_t       mutex;
  
 int debugmode         = 0;
 int number_of_tries   = 1, sitecast_domain_len = 0;
-char *sitecast_domain = NULL, *sitecast_groups = NULL;
+char *sitecast_domain = NULL, *sitecast_groups = NULL, *local_root = NULL,
+     *gridmapdir = NULL;
+uid_t local_uid = 0;
+gid_t local_gid = 0;
 
 size_t headers_callback(void *ptr, size_t size, size_t nmemb, void *p)
 /* Find the values of the return code, Content-Length, Last-Modified
@@ -854,7 +860,7 @@ struct grst_dir_list *index_to_dir_list(char *text, char *source)
                                         (p[i] != '\t') &&
                                         (p[i] != ')' ) &&
                                         (p[i] != '>' ) ; ++i) ; }
-               if (i > namestart) 
+               if (i > namestart)
                  {
                    s = malloc(1 + i - namestart);
                    memcpy(s, &p[namestart], i - namestart);
@@ -862,6 +868,14 @@ struct grst_dir_list *index_to_dir_list(char *text, char *source)
 
                    list[used].filename = canonicalise(s, source);
                    free(s);
+                   
+                   if ((list[used].filename != NULL) &&
+                       ((list[used].filename[0] == '\0') ||
+                        (strcmp(list[used].filename, "/") == 0)))
+                     {
+                       free(list[used].filename);
+                       list[used].filename = NULL;
+                     }
                  }
                  
                p = &p[i-1]; /* -1 since continue results in ++i */
@@ -945,6 +959,31 @@ static char *GRSThttpUrlMildencode(char *in)
 }
 #endif
 
+GRSTgaclPerm get_gaclPerm(struct fuse_context *fuse_ctx, char *path)
+{
+  GRSTgaclPerm perm = GRST_PERM_NONE; 
+  GRSTgaclCred *cred;
+  GRSTgaclUser *user;
+  GRSTgaclAcl  *acl;
+
+// eventually want a UID cache here...
+
+// will check gridmapdir for DN and create user in future...
+  user = NULL; // but just anonymous user for now
+  
+  acl  = GRSTgaclAclLoadforFile(path);
+  perm = GRSTgaclAclTestUser(acl, user);
+  GRSTgaclAclFree(acl);
+  GRSTgaclUserFree(user);
+  
+perm = 255;
+
+  if (debugmode) syslog(LOG_DEBUG, "get_gaclPerm returns perm=%d", perm);
+
+  return perm;            
+}
+
 int read_headers_from_cache(struct fuse_context *fuse_ctx, char *filename, 
                             off_t *length, time_t *modified)
 {
@@ -1100,10 +1139,10 @@ static int slashgrid_readdir(const char *path, void *buf,
   (void) offset;
   (void) fi;
 
-  int          anyerror = 0, thiserror, i, ilast;
+  int          anyerror = 0, thiserror, i, ilast, len, isdir;
   const char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
                             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-  char        *s, *url, errorbuffer[CURL_ERROR_SIZE+1] = "";
+  char        *s, *url, errorbuffer[CURL_ERROR_SIZE+1] = "", *dirname, *p;
   struct       grst_body_text  rawindex;
   struct       grst_dir_list   *list;
   struct       grst_request request_data;
@@ -1111,12 +1150,78 @@ static int slashgrid_readdir(const char *path, void *buf,
   struct       stat             stat_tmp;
   time_t                        now;
   struct fuse_context fuse_ctx;
+  struct dirent **dirlist;
+  GRSTgaclPerm  perm;
   
   memcpy(&fuse_ctx, fuse_get_context(), sizeof(struct fuse_context));
 
   if (debugmode) syslog(LOG_DEBUG, "in slashgrid_readdir");
 
-  if (strncmp(path, "/http/", 6) == 0)
+  if (strcmp(path, "/") == 0)
+    {
+      filler(buf, ".",     NULL, 0);
+      filler(buf, "..",    NULL, 0);
+      filler(buf, "http",  NULL, 0);
+      filler(buf, "https", NULL, 0);
+      return 0;
+    }
+    
+  if ((strcmp(path, "/http") == 0) || (strcmp(path, "/https") == 0))
+    {
+      filler(buf, ".",     NULL, 0);
+      filler(buf, "..",    NULL, 0);
+
+      asprintf(&dirname, "%s/%d%s", GRST_SLASH_HEADERS, fuse_ctx.uid, path);
+      ilast = scandir(dirname, &dirlist, 0, alphasort) - 1;
+
+      for (i=0; i <= ilast; ++i)
+         {
+           if (dirlist[i]->d_name[0] != '.')
+                 filler(buf, dirlist[i]->d_name, NULL, 0);
+           free(dirlist[i]);
+         }
+         
+      free(dirlist);      
+      free(dirname);
+    
+      return 0;
+    }
+  else if ((local_root != NULL) &&
+           ((strcmp(path, "/local") == 0) || 
+            (strncmp(path, "/local/", 7) == 0)))
+    {
+      asprintf(&dirname, "%s%s/", local_root, &path[6]);
+
+  if (debugmode) syslog(LOG_DEBUG, "in slashgrid_readdir, dirname=%s", dirname);
+      
+      perm = get_gaclPerm(&fuse_ctx, dirname);
+
+      if (!GRSTgaclPermHasList(perm))
+        {
+          free(dirname);
+          return -EACCES;
+        }
+        
+      ilast = scandir(dirname, &dirlist, 0, alphasort) - 1;
+      free(dirname);
+
+      if (ilast < 0) return -ENOENT;
+              
+      filler(buf, ".",     NULL, 0);
+      filler(buf, "..",    NULL, 0);
+
+      for (i=0; i <= ilast; ++i)
+         {
+           if (dirlist[i]->d_name[0] != '.')
+                 filler(buf, dirlist[i]->d_name, NULL, 0);
+           free(dirlist[i]);
+         }
+         
+      free(dirlist);      
+
+      return 0;
+    }
+  else if (strncmp(path, "/http/", 6) == 0)
     asprintf(&url, "http://%s/", &path[6]);
   else if (strncmp(path, "/https/", 7) == 0)
     asprintf(&url, "https://%s/", &path[7]);
@@ -1163,13 +1268,32 @@ static int slashgrid_readdir(const char *path, void *buf,
 
            rawindex.text[rawindex.used] = '\0';
 
+// we need to get this out of headers cache instead iff still valid
+
            list  = index_to_dir_list(rawindex.text, url);
            ilast = -1;
 
            for (i=0; list[i].filename != NULL; ++i)
               {
+                if (debugmode) syslog(LOG_DEBUG, 
+                         "in slashgrid_readdir, list[%d].filename=%s",
+                         i, list[i].filename);
+              
                 if (strncmp(list[i].filename, "mailto:", 7) == 0) continue;
 
+                len = strlen(list[i].filename);
+                if (list[i].filename[len-1] == '/')
+                  {
+                    isdir = 1;
+                    list[i].filename[len-1] = '\0';
+                  }
+                else 
+                  {
+                    isdir = 0;
+                    
+                    if ((p = index(list[i].filename, '?')) != NULL) *p = '\0';
+                  }
+                
                 /* skip over duplicates */
                 
                 if ((ilast >= 0) && 
@@ -1177,34 +1301,45 @@ static int slashgrid_readdir(const char *path, void *buf,
                                                                  continue;
                 ilast=i; /* last distinct entry */
                 
+                if (debugmode) syslog(LOG_DEBUG, 
+                         "in slashgrid_readdir, list[%d].filename=%s not dup",
+                         i, list[i].filename);
+
                 asprintf(&s, "%s/%s", path, list[i].filename);
                 write_headers_to_cache(&fuse_ctx, s, list[i].length, 
                                        list[i].modified);
                 free(s);
            
                 bzero(&stat_tmp, sizeof(struct stat));
+
                 stat_tmp.st_size  = list[i].length;
                 stat_tmp.st_mtime = list[i].modified;
                 stat_tmp.st_ctime = list[i].modified;
                 stat_tmp.st_atime = now;
-                stat_tmp.st_mode  = 0666;
-            
+                stat_tmp.st_mode  = isdir ? 0777 : 0666;
                 filler(buf, list[i].filename, &stat_tmp, 0);
+
+                if (debugmode) syslog(LOG_DEBUG, 
+                         "in slashgrid_readdir, filler list[%d].filename=%s %lu %lu",
+                         i, list[i].filename, stat_tmp.st_size, stat_tmp.st_mtime);
               }
          }
      
+  if (debugmode) syslog(LOG_DEBUG, 
+                         "in slashgrid_readdir, return 0");
   return 0;
 }
 
 static int slashgrid_getattr(const char *rawpath, struct stat *stbuf)
 {
-  int          anyerror = 0, thiserror, i, ilast, len;
-  char        *s, *url, *path, errorbuffer[CURL_ERROR_SIZE+1] = "";
+  int          anyerror = 0, thiserror, i, ilast, len, ret;
+  char        *s, *url, *path, errorbuffer[CURL_ERROR_SIZE+1] = "", *p;
   struct       grst_dir_list   *list;
   struct       grst_request request_data;
   struct       tm               modified_tm;
   struct       stat             stat_tmp;
   time_t                        now;
+  GRSTgaclPerm dirperm, perm;
 
   struct fuse_context fuse_ctx;
 
@@ -1220,11 +1355,12 @@ static int slashgrid_getattr(const char *rawpath, struct stat *stbuf)
   
   if ((strcmp(rawpath, "/")      == 0) ||
       (strcmp(rawpath, "/http")  == 0) ||
-      (strcmp(rawpath, "/https") == 0))
+      (strcmp(rawpath, "/https") == 0) ||
+      ((local_root != NULL) && (strcmp(rawpath, "/local") == 0)))
     {
       stbuf->st_mode = S_IFDIR | 0755;
               
-      return 0; /* The empty top level directory: OK */
+      return 0; /* Empty top level directories: OK */
     }
   else if (strncmp(rawpath, "/http/", 6) == 0)
     {
@@ -1256,6 +1392,75 @@ static int slashgrid_getattr(const char *rawpath, struct stat *stbuf)
           path = strdup(rawpath);
         }
     }
+  else if ((local_root != NULL) && (strncmp(rawpath, "/local/", 7) == 0))
+    {      
+      asprintf(&path, "%s/%s", local_root, &rawpath[7]);
+      ret = lstat(path, &stat_tmp);
+
+      if (debugmode) syslog(LOG_DEBUG, "path=%s ret=%d", path, ret);
+
+      if ((ret == 0) && S_ISDIR(stat_tmp.st_mode))
+        {
+          dirperm = get_gaclPerm(&fuse_ctx, path);
+        
+          p = rindex(path, '/');
+          if (p != NULL) *p = '\0'; 
+          /* strip off directory name itself if a directory, 
+             so get the GACL of the parent directory */
+
+          perm = get_gaclPerm(&fuse_ctx, path);
+        }
+      else
+        {      
+          perm = get_gaclPerm(&fuse_ctx, path);
+          dirperm = perm;
+        }
+
+      if (!GRSTgaclPermHasRead(perm)) ret = -EACCES;
+      else if (ret == 0)
+        {
+          stbuf->st_nlink   = 1;
+          stbuf->st_uid     = fuse_ctx.uid;
+          stbuf->st_gid     = fuse_ctx.gid;
+          stbuf->st_size    = stat_tmp.st_size;
+          stbuf->st_blksize = stat_tmp.st_blksize;
+          stbuf->st_blocks  = stat_tmp.st_blocks;
+          stbuf->st_atime   = stat_tmp.st_atime;
+          stbuf->st_mtime   = stat_tmp.st_mtime;
+          stbuf->st_ctime   = stat_tmp.st_ctime;
+        
+          if (S_ISDIR(stat_tmp.st_mode))
+            {
+              stbuf->st_mode = S_IFDIR;
+            
+              if (GRSTgaclPermHasWrite(dirperm)) 
+                                        stbuf->st_mode |= S_IWUSR;
+
+              if (GRSTgaclPermHasList(dirperm)) 
+                                        stbuf->st_mode |= S_IRUSR | S_IXUSR;
+            }
+          else
+            {
+              stbuf->st_mode = S_IFREG;
+
+              if (GRSTgaclPermHasWrite(perm)) 
+                                        stbuf->st_mode |= S_IWUSR;
+
+              if (GRSTgaclPermHasRead(perm)) 
+                                        stbuf->st_mode |= S_IRUSR;
+            }          
+            
+          
+        }  
+      else ret = -ENOENT;
+      
+      free(path);
+
+      if (debugmode) syslog(LOG_DEBUG, "slashgrid_getattr returns %d for %s",
+                                       ret, rawpath);
+      return ret;
+    }
   else return -ENOENT;
   
   time(&now);
@@ -1370,7 +1575,6 @@ static int slashgrid_getattr(const char *rawpath, struct stat *stbuf)
   return 0;
 }
 
-
 int write_block_to_cache(struct fuse_context *fuse_ctx, char *filename,  
                          off_t start, off_t finish)
 {
@@ -1458,8 +1662,8 @@ int write_block_to_cache(struct fuse_context *fuse_ctx, char *filename,
        if (*p == '\0') break;
      }
 
-  asprintf(&new_filename, "%s/%d%s/%ld-%ld", 
-       GRST_SLASH_BLOCKS, fuse_ctx->uid, encoded_filename, (long) start, (long) finish);
+  asprintf(&new_filename, "%s/%d%s/%ld-%ld", GRST_SLASH_BLOCKS, fuse_ctx->uid,
+                           encoded_filename, (long) start, (long) finish);
 
   free(encoded_filename);
   
@@ -1520,13 +1724,14 @@ static int slashgrid_read(const char *path, char *buf,
   (void) fi;
 
   int          anyerror = 0, thiserror, i, ilast, fd;
-  char        *s, *url, *disk_filename, *encoded_filename;
+  char        *s, *url, *disk_filename, *encoded_filename, *localpath;
   off_t        block_start, block_finish, block_i, len;
   struct       grst_body_text   rawbody;
   struct       grst_request request_data;
   struct       tm               modified_tm;
   struct       stat             statbuf;
   time_t                        now;
+  GRSTgaclPerm perm;
   struct fuse_context fuse_ctx;
 
   memcpy(&fuse_ctx, fuse_get_context(), sizeof(struct fuse_context));
@@ -1534,6 +1739,28 @@ static int slashgrid_read(const char *path, char *buf,
   if (debugmode) syslog(LOG_DEBUG, "in slashgrid_read size=%ld offset=%ld",
                                     (long) size, (long) offset);
 
+  if ((local_root != NULL) && (strncmp(path, "/local/", 7) == 0))
+    {
+      asprintf(&localpath, "%s/%s", local_root, &path[7]);
+      
+      perm = get_gaclPerm(&fuse_ctx, localpath);
+      
+      if (GRSTgaclPermHasRead(perm))
+        {
+          fd = open(localpath, O_RDONLY);
+
+          if (lseek(fd, offset, SEEK_SET) < 0) size = -1;
+          else size = read(fd, buf, size);
+
+          close(fd);                  
+        }
+      else size = -1;
+      
+      free(localpath);
+      
+      return size;
+    }
+
   if ((strncmp(path, "/http/",  6) != 0) &&
       (strncmp(path, "/https/", 7) != 0)) return -ENOENT;
 
@@ -1600,7 +1827,8 @@ static int slashgrid_write(const char *path, const char *buf,
                            struct fuse_file_info *fi)
 {
   int          anyerror = 0, thiserror, i, fd;
-  char        *s, *url, *p, errorbuffer[CURL_ERROR_SIZE+1] = "";
+  char        *s, *url, *p, errorbuffer[CURL_ERROR_SIZE+1] = "", *localpath;
+  GRSTgaclPerm perm;
 
   struct grst_read_data read_data;
   struct grst_request request_data;
@@ -1608,6 +1836,32 @@ static int slashgrid_write(const char *path, const char *buf,
   
   memcpy(&fuse_ctx, fuse_get_context(), sizeof(struct fuse_context));  
 
+  if (debugmode) syslog(LOG_DEBUG, "in slashgrid_write, path=%s, UID=%d\n",
+                                   path, fuse_ctx.uid);
+                         
+  if ((local_root != NULL) && (strncmp(path, "/local/", 7) == 0))
+    {
+      asprintf(&localpath, "%s/%s", local_root, &path[7]);
+      
+      perm = get_gaclPerm(&fuse_ctx, localpath);
+      
+      if (GRSTgaclPermHasWrite(perm))
+        {
+          fd = open(localpath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+
+          if (lseek(fd, offset, SEEK_SET) < 0) size = -1;
+          else size = write(fd, buf, size);
+
+          fchown(fd, local_uid, local_gid);
+          close(fd);                  
+        }
+      else size = -1;
+      
+      free(localpath);
+      
+      return size;
+    }
+
   if (strncmp(path, "/http/", 6) == 0)
     asprintf(&url, "http://%s", &path[6]);
   else if (strncmp(path, "/https/", 7) == 0)
@@ -1794,6 +2048,8 @@ int slashgrid_rmdir(const char *path)
 int slashgrid_mknod(const char *path, mode_t mode, dev_t dev)
 {
   int ret;
+
+  if (debugmode) syslog(LOG_DEBUG, "slashgrid_mknod called for %s", path);
   
   ret = slashgrid_write(path, "", 0, 0, NULL);
 
@@ -1826,8 +2082,9 @@ int slashgrid_chmod(const char *path, mode_t mode)
 
 int slashgrid_truncate(const char *path, off_t offset)
 {
-  int          anyerror = 0, thiserror, i, fd;
-  char        *s, *url, *p, errorbuffer[CURL_ERROR_SIZE+1] = "";
+  int   anyerror = 0, thiserror, i, fd, ret;
+  char *s, *url, *p, errorbuffer[CURL_ERROR_SIZE+1] = "", *localpath;
+  GRSTgaclPerm perm;
 
   struct grst_read_data read_data;
   struct fuse_context fuse_ctx;
@@ -1835,10 +2092,30 @@ int slashgrid_truncate(const char *path, off_t offset)
 
   memcpy(&fuse_ctx, fuse_get_context(), sizeof(struct fuse_context));
 
+  if (debugmode) syslog(LOG_DEBUG, "slashgrid_truncate, for %s (%d)",
+                                  path, offset);
+
   if (strncmp(path, "/http/", 6) == 0)
     asprintf(&url, "http://%s", &path[6]);
   else if (strncmp(path, "/https/", 7) == 0)
     asprintf(&url, "https://%s", &path[7]);
+  else if ((local_root != NULL) && (strncmp(path, "/local/", 7) == 0))
+    {
+      asprintf(&localpath, "%s/%s", local_root, &path[7]);
+      
+      perm = get_gaclPerm(&fuse_ctx, localpath);
+      
+      if (GRSTgaclPermHasWrite(perm))
+        {
+          ret = truncate(localpath, offset);
+          free(localpath);
+          
+          return (ret == 0) ? 0 : -ENOENT;
+        }
+
+      free(localpath);
+      return -EACCES;
+    }
   else return -ENOENT;
 
   read_data.buf     = "";
@@ -1882,7 +2159,12 @@ int slashgrid_truncate(const char *path, off_t offset)
 
 int slashgrid_statfs(const char *path, struct statfs *fs)
 {
-  return statfs(GRST_SLASH_BLOCKS, fs);
+  /* statfs() on /local not used in practice, since not mounted separately */
+
+  if ((strncmp(path, "/local/", 7) == 0) ||
+      (strcmp(path, "/local") == 0))
+       return statfs(local_root, fs);
+  else return statfs(GRST_SLASH_BLOCKS, fs);
 }
 
 void *slashgrid_init(void)
@@ -1921,15 +2203,39 @@ static struct fuse_operations slashgrid_oper = {
   .destroy     = slashgrid_destroy
 };
 
+void slashgrid_logfunc(char *file, int line, int level, char *fmt, ...)
+{
+  char *mesg;
+  va_list ap;
+
+  va_start(ap, fmt);
+  vasprintf(&mesg, fmt, ap);
+  va_end(ap);
+  
+  syslog(level, "%s(%d) %s", file, line, mesg);
+  
+  free(mesg);
+}
+
 int main(int argc, char *argv[])
 {
-#define FUSE_ARGC 4
-  char *fuse_argv[FUSE_ARGC] = { "slashgrid", "/grid", "-o", "allow_other" };
-  int   i, ret;
+  char *fuse_argv[] = { "slashgrid", "/grid", "-o", "allow_other",
+                        "-s", "-d" };
+  int   i, ret, fuse_argc = 4; /* by default, ignore the final 2 args */
+  struct passwd *pw;
+  struct rlimit unlimited = { RLIM_INFINITY, RLIM_INFINITY };
   
   for (i=1; i < argc; ++i)
      {
-       if (strcmp(argv[i], "--debug") == 0) debugmode = 1;
+       if (strcmp(argv[i], "--debug") == 0) 
+         {
+           debugmode = 1;
+         }
+       else if (strcmp(argv[i], "--foreground") == 0) 
+         {
+           debugmode = 1;
+           fuse_argc = 6;
+         }
        else if ((strcmp(argv[i], "--domain") == 0) && (i + 1 < argc))
          {
            sitecast_domain = argv[i+1];
@@ -1941,7 +2247,42 @@ int main(int argc, char *argv[])
            sitecast_groups = argv[i+1];
            ++i;
          }          
-     }                 
+       else if ((strcmp(argv[i], "--local-root") == 0) && (i + 1 < argc))
+         {
+           local_root = argv[i+1];
+           ++i;
+         }          
+       else if ((strcmp(argv[i], "--local-user") == 0) && (i + 1 < argc))
+         {
+           if ((pw = getpwnam(argv[i+1])) == NULL)
+             {
+               fprintf(stderr, "unable to find user %s\n", argv[i+1]);
+               return 1;
+             }
+            
+           local_uid = pw->pw_uid;
+           local_gid = pw->pw_gid;
+           ++i;           
+         }
+       else if ((strcmp(argv[i], "--gridmapdir") == 0) && (i + 1 < argc))
+         {
+           gridmapdir = argv[i+1];
+           ++i;
+         }          
+       else
+         {
+           fprintf(stderr, "argument %s not recognised\n", argv[i]);
+           return 1;
+         }
+     }              
+
+  if ((local_root != NULL) && 
+      ((local_uid == 0) || (local_gid == 0)))
+    {
+      fprintf(stderr, "if --local-root is given, "
+                "--local-user must be given too and not be the root user\n");
+      return 1;
+    }
 
   openlog("slashgrid", 0, LOG_DAEMON);
     
@@ -1955,7 +2296,17 @@ int main(int argc, char *argv[])
        handles[i].last_used   = 0;
      }
 
-  ret = fuse_main(FUSE_ARGC, fuse_argv, &slashgrid_oper);
+  if (debugmode) 
+    {
+      chdir("/var/tmp");
+      setrlimit(RLIMIT_CORE, &unlimited);
+    }
+
+//  GRSTerrorLogFunc = slashgrid_logfunc;
+  GRSTgaclInit();
+  ret = fuse_main(fuse_argc, fuse_argv, &slashgrid_oper);
 
   return ret;
 }
index 44a12ad..f83b43e 100755 (executable)
@@ -30,6 +30,7 @@ RETVAL=0
 start() {
         echo -n $"Starting $prog: "
         modprobe fuse
+        sleep 1
         daemon $slashgrid $OPTIONS
         RETVAL=$?
         echo