/[hurd]/hurd/trans/fakeroot.c
ViewVC logotype

Diff of /hurd/trans/fakeroot.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.15 by roland, Mon May 13 22:34:29 2002 UTC revision 1.16 by roland, Sat May 18 21:18:08 2002 UTC
# Line 36  char *netfs_server_name = "fakeroot"; Line 36  char *netfs_server_name = "fakeroot";
36  char *netfs_server_version = HURD_VERSION;  char *netfs_server_version = HURD_VERSION;
37  int netfs_maxsymlinks = 16;     /* arbitrary */  int netfs_maxsymlinks = 16;     /* arbitrary */
38    
39    static auth_t fakeroot_auth_port;
40    
41  struct netnode  struct netnode
42  {  {
43    void **idport_locp;           /* easy removal pointer in idport ihash */    void **idport_locp;           /* easy removal pointer in idport ihash */
# Line 56  struct mutex idport_ihash_lock = MUTEX_I Line 58  struct mutex idport_ihash_lock = MUTEX_I
58  struct ihash idport_ihash;  struct ihash idport_ihash;
59    
60    
61    /* Make a new virtual node.  Always consumes the ports.  */
62  static error_t  static error_t
63  new_node (file_t file, mach_port_t idport, int openmodes, struct node **np)  new_node (file_t file, mach_port_t idport, int locked, int openmodes,
64              struct node **np)
65  {  {
66    error_t err;    error_t err;
67    struct netnode *nn = calloc (1, sizeof *nn);    struct netnode *nn = calloc (1, sizeof *nn);
# Line 66  new_node (file_t file, mach_port_t idpor Line 70  new_node (file_t file, mach_port_t idpor
70        mach_port_deallocate (mach_task_self (), file);        mach_port_deallocate (mach_task_self (), file);
71        if (idport != MACH_PORT_NULL)        if (idport != MACH_PORT_NULL)
72          mach_port_deallocate (mach_task_self (), idport);          mach_port_deallocate (mach_task_self (), idport);
73          if (locked)
74            mutex_unlock (&idport_ihash_lock);
75        return ENOMEM;        return ENOMEM;
76      }      }
77    nn->file = file;    nn->file = file;
# Line 76  new_node (file_t file, mach_port_t idpor Line 82  new_node (file_t file, mach_port_t idpor
82      {      {
83        int fileno;        int fileno;
84        mach_port_t fsidport;        mach_port_t fsidport;
85          assert (!locked);
86        err = io_identity (file, &nn->idport, &fsidport, &fileno);        err = io_identity (file, &nn->idport, &fsidport, &fileno);
87        if (err)        if (err)
88          {          {
# Line 86  new_node (file_t file, mach_port_t idpor Line 93  new_node (file_t file, mach_port_t idpor
93      }      }
94    *np = netfs_make_node (nn);    *np = netfs_make_node (nn);
95    if (*np == 0)    if (*np == 0)
96      err = ENOMEM;      {
97          if (locked)
98            mutex_unlock (&idport_ihash_lock);
99          err = ENOMEM;
100        }
101    else    else
102      {      {
103        mutex_lock (&idport_ihash_lock);        if (!locked)
104            mutex_lock (&idport_ihash_lock);
105        err = ihash_add (&idport_ihash, nn->idport, *np, &nn->idport_locp);        err = ihash_add (&idport_ihash, nn->idport, *np, &nn->idport_locp);
106          if (!err)
107            netfs_nref (*np);       /* Return a reference to the caller.  */
108        mutex_unlock (&idport_ihash_lock);        mutex_unlock (&idport_ihash_lock);
109      }      }
110    if (err)    if (err)
# Line 143  netfs_node_norefs (struct node *np) Line 157  netfs_node_norefs (struct node *np)
157    free (np);    free (np);
158  }  }
159    
160    /* Given an existing node, make sure it has NEWMODES in its openmodes.
161       If not null, FILE is a port with those openmodes.  */
162    static error_t
163    check_openmodes (struct netnode *nn, int newmodes, file_t file)
164    {
165      error_t err = 0;
166    
167      if (newmodes &~ nn->openmodes)
168        {
169          /* The user wants openmodes we haven't tried before.  */
170    
171          if (file != MACH_PORT_NULL && (nn->openmodes & ~newmodes))
172            {
173              /* Intersecting sets.
174                 We need yet another new peropen on this node.  */
175              mach_port_deallocate (mach_task_self (), file);
176              file = MACH_PORT_NULL;
177            }
178          if (file == MACH_PORT_NULL);
179            {
180              enum retry_type bad_retry;
181              char bad_retryname[1024];     /* XXX */
182              if (file != MACH_PORT_NULL)
183              err = dir_lookup (nn->file, "", nn->openmodes | newmodes, 0,
184                                &bad_retry, bad_retryname, &file);
185              if (!err && (bad_retry != FS_RETRY_NORMAL
186                           || bad_retryname[0] != '\0'))
187                {
188                  mach_port_deallocate (mach_task_self (), file);
189                  err = EGRATUITOUS;
190                }
191            }
192          if (! err)
193            {
194              /* The new port has more openmodes than
195                 the old one.  We can just use it now.  */
196              mach_port_deallocate (mach_task_self (), nn->file);
197              nn->file = file;
198              nn->openmodes = newmodes;
199            }
200        }
201      else if (file != MACH_PORT_NULL)
202        mach_port_deallocate (mach_task_self (), file);
203    
204      return err;
205    }
206    
207    /* This is called by netfs_S_fsys_getroot.  */
208    error_t
209    netfs_check_open_permissions (struct iouser *user, struct node *np,
210                                  int flags, int newnode)
211    {
212      return check_openmodes (np->nn, flags & (O_RDWR|O_EXEC), MACH_PORT_NULL);
213    }
214    
215    error_t
216    netfs_S_dir_lookup (struct protid *diruser,
217                        char *filename,
218                        int flags,
219                        mode_t mode,
220                        retry_type *do_retry,
221                        char *retry_name,
222                        mach_port_t *retry_port,
223                        mach_msg_type_name_t *retry_port_type)
224    {
225      struct node *dnp, *np;
226      error_t err;
227      struct protid *newpi;
228      struct iouser *user;
229      mach_port_t file;
230      mach_port_t idport, fsidport;
231      int fileno;
232    
233      if (!diruser)
234        return EOPNOTSUPP;
235    
236      dnp = diruser->po->np;
237      err = dir_lookup (dnp->nn->file, filename,
238                        O_NOLINK | (flags
239                                    & (O_RDWR|O_EXEC|O_CREAT|O_EXCL|O_NONBLOCK)),
240                        mode, do_retry, retry_name, &file);
241      if (err)
242        return err;
243    
244      switch (*do_retry)
245        {
246        case FS_RETRY_REAUTH:
247          {
248            mach_port_t ref = mach_reply_port ();
249            err = io_reauthenticate (file, ref, MACH_MSG_TYPE_MAKE_SEND);
250            if (! err)
251              {
252                mach_port_deallocate (mach_task_self (), file);
253                err = auth_user_authenticate (fakeroot_auth_port, ref,
254                                              MACH_MSG_TYPE_MAKE_SEND,
255                                              retry_port);
256              }
257            mach_port_destroy (mach_task_self (), ref);
258            if (err)
259              return err;
260          }
261          *do_retry = FS_RETRY_NORMAL;
262          /*FALLTHROUGH*/
263    
264        case FS_RETRY_NORMAL:
265        case FS_RETRY_MAGICAL:
266        default:
267          if (file == MACH_PORT_NULL)
268            {
269              *retry_port = MACH_PORT_NULL;
270              *retry_port_type = MACH_MSG_TYPE_COPY_SEND;
271              return 0;
272            }
273          break;
274        }
275    
276      /* We have a new port to an underlying node.
277         Find or make our corresponding virtual node.  */
278    
279      np = 0;
280      err = io_identity (file, &idport, &fsidport, &fileno);
281      if (err)
282        mach_port_deallocate (mach_task_self (), file);
283      else
284        {
285          mach_port_deallocate (mach_task_self (), fsidport);
286          if (fsidport == netfs_fsys_identity)
287            {
288              /* Talking to ourselves!  We just looked up one of our
289                 own nodes.  Find the node and return it.  */
290              struct protid *cred
291                = ports_lookup_port (netfs_port_bucket, file,
292                                     netfs_protid_class);
293              mach_port_deallocate (mach_task_self (), idport);
294              mach_port_deallocate (mach_task_self (), file);
295              if (cred == 0)
296                return EGRATUITOUS;
297              np = cred->po->np;
298              netfs_nref (np);
299              ports_port_deref (cred);
300            }
301          else
302            {
303              mutex_lock (&idport_ihash_lock);
304              np = ihash_find (&idport_ihash, idport);
305              if (np != 0)
306                {
307                  /* We already know about this node.  */
308                  mach_port_deallocate (mach_task_self (), idport);
309                  mutex_lock (&np->lock);
310                  err = check_openmodes (np->nn, (flags & (O_RDWR|O_EXEC)), file);
311                  if (!err)
312                    netfs_nref (np);
313                  mutex_unlock (&np->lock);
314                  mutex_unlock (&idport_ihash_lock);
315                }
316              else
317                err = new_node (file, idport, 1, flags, &np);
318            }
319        }
320      if (err)
321        return err;
322    
323      if (retry_name[0] == '\0' && *do_retry == FS_RETRY_NORMAL)
324        flags &= ~(O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS|O_NONBLOCK);
325      else
326        flags = 0;
327    
328      err = iohelp_dup_iouser (&user, diruser->user);
329      if (!err)
330        {
331          newpi = netfs_make_protid (netfs_make_peropen (np, flags, diruser->po),
332                                     user);
333          if (! newpi)
334            {
335              iohelp_free_iouser (user);
336              err = errno;
337            }
338          else
339            {
340              *retry_port = ports_get_right (newpi);
341              *retry_port_type = MACH_MSG_TYPE_MAKE_SEND;
342              ports_port_deref (newpi);
343            }
344        }
345    
346      netfs_nrele (np);
347      return err;
348    }
349    
350    /* These callbacks are used only by the standard netfs_S_dir_lookup,
351       which we do not use.  But the shared library requires us to define them.  */
352    error_t
353    netfs_attempt_lookup (struct iouser *user, struct node *dir,
354                          char *name, struct node **np)
355    {
356      assert (! "should not be here");
357      return EIEIO;
358    }
359    
360    error_t
361    netfs_attempt_create_file (struct iouser *user, struct node *dir,
362                               char *name, mode_t mode, struct node **np)
363    {
364      assert (! "should not be here");
365      return EIEIO;
366    }
367    
368  /* Make sure that NP->nn_stat is filled with the most current information.  /* Make sure that NP->nn_stat is filled with the most current information.
369     CRED identifies the user responsible for the operation. NP is locked.  */     CRED identifies the user responsible for the operation. NP is locked.  */
370  error_t  error_t
# Line 321  netfs_attempt_syncfs (struct iouser *cre Line 543  netfs_attempt_syncfs (struct iouser *cre
543    return 0;    return 0;
544  }  }
545    
 /* Lookup NAME in DIR (which is locked) for USER; set *NP to the found name  
    upon return.  If the name was not found, then return ENOENT.  On any  
    error, clear *NP.  (*NP, if found, should be locked and a reference to  
    it generated.  This call should unlock DIR no matter what.)  */  
 error_t  
 netfs_attempt_lookup (struct iouser *user, struct node *dir,  
                       char *name, struct node **np)  
 {  
   error_t err;  
   int flags;  
   const file_t dirfile = dir->nn->file;  
   file_t file;  
   
   /* We must unlock the directory before making RPCs to the underlying  
      filesystem in case they somehow wind up trying to refer back to one of  
      our nodes.  The DIRFILE port will not change or die as long as DIR  
      lives, and our caller holds a reference keeping it alive.  */  
   mutex_unlock (&dir->lock);  
   
   flags = O_RDWR|O_EXEC;  
   file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0);  
   if (file == MACH_PORT_NULL && (errno == EACCES || errno == EOPNOTSUPP  
                                  || errno == EROFS || errno == EISDIR))  
     {  
       flags = O_RDWR;  
       file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0);  
     }  
   if (file == MACH_PORT_NULL && (errno == EACCES || errno == EOPNOTSUPP  
                                  || errno == EROFS || errno == EISDIR))  
     {  
       flags = O_READ|O_EXEC;  
       file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0);  
     }  
   if (file == MACH_PORT_NULL && (errno == EACCES || errno == EOPNOTSUPP  
                                  || errno == EISDIR))  
     {  
       flags = O_READ;  
       file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0);  
     }  
   if (file == MACH_PORT_NULL && (errno == EACCES || errno == EOPNOTSUPP  
                                  || errno == EISDIR))  
     {  
       flags = 0;  
       file = file_name_lookup_under (dirfile, name, flags | O_NOLINK, 0);  
     }  
   *np = 0;  
   if (file == MACH_PORT_NULL)  
     err = errno;  
   else  
     {  
       mach_port_t idport, fsidport;  
       int fileno;  
       err = io_identity (file, &idport, &fsidport, &fileno);  
       if (err)  
         mach_port_deallocate (mach_task_self (), file);  
       else  
         {  
           mach_port_deallocate (mach_task_self (), fsidport);  
           if (fsidport == netfs_fsys_identity)  
             {  
               /* Talking to ourselves!  We just looked up one of our own nodes.  
                  Find the node and return it.  */  
               struct protid *cred = ports_lookup_port (netfs_port_bucket, file,  
                                                        netfs_protid_class);  
               mach_port_deallocate (mach_task_self (), idport);  
               mach_port_deallocate (mach_task_self (), file);  
               if (cred == 0)  
                 return EGRATUITOUS;  
               *np = cred->po->np;  
               netfs_nref (*np);  
               ports_port_deref (cred);  
             }  
           else  
             {  
               mutex_lock (&idport_ihash_lock);  
               *np = ihash_find (&idport_ihash, idport);  
               if (*np != 0)  
                 {  
                   /* We already know about this node.  */  
                   mach_port_deallocate (mach_task_self (), idport);  
                   mach_port_deallocate (mach_task_self (), file);  
                   netfs_nref (*np);  
                   mutex_unlock (&idport_ihash_lock);  
                 }  
               else  
                 {  
                   mutex_unlock (&idport_ihash_lock);  
                   err = new_node (file, idport, flags, np);  
                 }  
             }  
         }  
     }  
   
   if (*np)  
     mutex_lock (&(*np)->lock);  
   return err;  
 }  
   
546  error_t  error_t
547  netfs_attempt_mkdir (struct iouser *user, struct node *dir,  netfs_attempt_mkdir (struct iouser *user, struct node *dir,
548                       char *name, mode_t mode)                       char *name, mode_t mode)
# Line 468  netfs_attempt_mkfile (struct iouser *use Line 592  netfs_attempt_mkfile (struct iouser *use
592    file_t newfile;    file_t newfile;
593    error_t err = dir_mkfile (dir->nn->file, O_RDWR|O_EXEC,    error_t err = dir_mkfile (dir->nn->file, O_RDWR|O_EXEC,
594                              real_from_fake_mode (mode), &newfile);                              real_from_fake_mode (mode), &newfile);
   if (err == 0)  
     err = new_node (newfile, MACH_PORT_NULL, O_RDWR|O_EXEC, np);  
595    mutex_unlock (&dir->lock);    mutex_unlock (&dir->lock);
596      if (err == 0)
597        err = new_node (newfile, MACH_PORT_NULL, 0, O_RDWR|O_EXEC, np);
598    return err;    return err;
599  }  }
600    
601  error_t  error_t
 netfs_attempt_create_file (struct iouser *user, struct node *dir,  
                            char *name, mode_t mode, struct node **np)  
 {  
   file_t newfile = file_name_lookup_under (dir->nn->file, name,  
                                            O_CREAT|O_RDWR|O_EXEC,  
                                            real_from_fake_mode (mode));  
   mutex_unlock (&dir->lock);  
   if (newfile == MACH_PORT_NULL)  
     return errno;  
   return new_node (newfile, MACH_PORT_NULL, O_RDWR|O_EXEC, np);  
 }  
   
 error_t  
602  netfs_attempt_readlink (struct iouser *user, struct node *np, char *buf)  netfs_attempt_readlink (struct iouser *user, struct node *np, char *buf)
603  {  {
604    char transbuf[sizeof _HURD_SYMLINK + np->nn_stat.st_size + 1];    char transbuf[sizeof _HURD_SYMLINK + np->nn_stat.st_size + 1];
# Line 512  netfs_attempt_readlink (struct iouser *u Line 623  netfs_attempt_readlink (struct iouser *u
623  }  }
624    
625  error_t  error_t
 netfs_check_open_permissions (struct iouser *user, struct node *np,  
                               int flags, int newnode)  
 {  
   return (flags & (O_READ|O_WRITE|O_EXEC) & ~np->nn->openmodes) ? EACCES : 0;  
 }  
   
 error_t  
626  netfs_attempt_read (struct iouser *cred, struct node *np,  netfs_attempt_read (struct iouser *cred, struct node *np,
627                      off_t offset, size_t *len, void *data)                      off_t offset, size_t *len, void *data)
628  {  {
# Line 776  any user to open nodes regardless of per Line 880  any user to open nodes regardless of per
880    /* Parse our command line arguments (all none of them).  */    /* Parse our command line arguments (all none of them).  */
881    argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);    argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
882    
883      fakeroot_auth_port = getauth ();
884    
885    task_get_bootstrap_port (mach_task_self (), &bootstrap);    task_get_bootstrap_port (mach_task_self (), &bootstrap);
886    netfs_init ();    netfs_init ();
887    
888    /* Get our underlying node (we presume it's a directory) and use    /* Get our underlying node (we presume it's a directory) and use
889       that to make the root node of the filesystem.  */       that to make the root node of the filesystem.  */
890    err = new_node (netfs_startup (bootstrap, O_READ), MACH_PORT_NULL, O_READ,    err = new_node (netfs_startup (bootstrap, O_READ), MACH_PORT_NULL, 0, O_READ,
891                    &netfs_root_node);                    &netfs_root_node);
892    if (err)    if (err)
893      error (5, err, "Cannot create root node");      error (5, err, "Cannot create root node");

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26