source: trunk/athena/lib/locker/detach.c @ 12783

Revision 12783, 5.8 KB checked in by danw, 26 years ago (diff)
record zephyr subscriptions, but don't actually make any libzephyr calls unless the caller explicitly asks for the subscription list to be processed.
Line 
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This file is part of liblocker. It implements detaching lockers. */
17
18static const char rcsid[] = "$Id: detach.c,v 1.2 1999-03-29 17:33:21 danw Exp $";
19
20#include <errno.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <hesiod.h>
25
26#include "locker.h"
27#include "locker_private.h"
28
29static int detach_attachent(locker_context context,
30                            locker_attachent *at, int options);
31static void del_owner(locker_context context, locker_attachent *at,
32                      uid_t user);
33static void clean_owners(locker_context context, locker_attachent *at);
34
35
36int locker_detach(locker_context context, char *filesystem, char *mountpoint,
37                  int options, locker_attachent **atp)
38{
39  int status;
40  locker_attachent *at;
41
42  status = locker__lookup_attachent(context, filesystem, mountpoint, 0, &at);
43  if (status)
44    return status;
45
46  status = locker_detach_attachent(context, at, options);
47  if (LOCKER_DETACH_SUCCESS(status) && atp)
48    *atp = at;
49  else
50    locker_free_attachent(context, at);
51  return status;
52}
53
54int locker_detach_explicit(locker_context context, char *type,
55                           char *desc, char *mountpoint, int options,
56                           locker_attachent **atp)
57{
58  int status;
59  locker_attachent *at;
60
61  status = locker__lookup_attachent_explicit(context, type, desc,
62                                             mountpoint, 1, &at);
63  if (status)
64    return status;
65
66  status = locker_detach_attachent(context, at, options);
67  if (LOCKER_DETACH_SUCCESS(status) && atp)
68    *atp = at;
69  else
70    locker_free_attachent(context, at);
71  return status;
72}
73
74int locker_detach_attachent(locker_context context,
75                            locker_attachent *at, int options)
76{
77  int status = LOCKER_SUCCESS;
78  locker_attachent *ai;
79
80  if (!context->trusted)
81    {
82      if (options & LOCKER_DETACH_OPT_UNLOCK)
83        {
84          locker__error(context, "%s: You are not authorized to use the "
85                        "unlock option.\n", at->name);
86          return LOCKER_EPERM;
87        }
88
89      if (options & LOCKER_DETACH_OPT_OVERRIDE)
90        {
91          locker__error(context, "%s: You are not authorized to use the "
92                        "override option.\n", at->name);
93          return LOCKER_EPERM;
94        }
95    }
96
97  /* If this is a MUL locker, detach sublockers first. */
98  for (ai = at->next; ai && status == LOCKER_SUCCESS; ai = ai->next)
99    status = detach_attachent(context, ai, options);
100
101  if (!LOCKER_DETACH_SUCCESS(status))
102    {
103      locker__error(context, "%s: MUL detach failed.\n", at->name);
104      return status;
105    }
106
107  status = detach_attachent(context, at, options);
108
109  return status;
110}
111
112/* This is the routine that does all of the work of attaching a single
113 * filesystem.
114 */
115static int detach_attachent(locker_context context,
116                            locker_attachent *at, int options)
117{
118  int status, dstatus;
119
120  if (!context->trusted)
121    {
122      /* Don't allow a user to detach something he couldn't attach. */
123      if (!locker__fs_ok(context, context->allow, at->fs, at->name))
124        {
125          locker__error(context, "%s: You are not allowed to detach this "
126                        "locker.\n", at->name);
127          return LOCKER_EPERM;
128        }
129      if (strcmp(at->fs->name, "MUL") &&
130          !locker__fs_ok(context, context->mountpoint, at->fs, at->mountpoint))
131        {
132          locker__error(context, "%s: You are not allowed to detach a "
133                        "locker from %s.\n", at->name, at->mountpoint);
134          return LOCKER_EPERM;
135        }
136    }
137
138  /* Check locking. */
139  if (at->flags & LOCKER_FLAG_LOCKED &&
140      !(options & LOCKER_DETACH_OPT_UNLOCK))
141    {
142      locker__error(context, "%s: filesystem is locked.\n", at->name);
143      return LOCKER_EPERM;
144    }
145
146  del_owner(context, at, context->user);
147  if (options & LOCKER_DETACH_OPT_CLEAN)
148    {
149      clean_owners(context, at);
150      if (at->nowners)
151        {
152          locker__update_attachent(context, at);
153          return LOCKER_SUCCESS;
154        }
155    }
156
157  if (at->nowners && (context->ownercheck ||
158                      (options & LOCKER_DETACH_OPT_OWNERCHECK)) &&
159      !(options & LOCKER_DETACH_OPT_OVERRIDE))
160    {
161      locker__error(context, "%s: Locker is wanted by others. Not detached.\n",
162                    at->name);
163      dstatus = LOCKER_EINUSE;
164    }
165  else
166    {
167      if (!(at->flags & LOCKER_FLAG_KEEP))
168        {
169          /* Detach the locker. */
170          dstatus = at->fs->detach(context, at);
171          if (!LOCKER_DETACH_SUCCESS(dstatus))
172            return dstatus;
173
174          /* Remove any mountpoint components we created. */
175          status = locker__remove_mountpoint(context, at);
176          if (status != LOCKER_SUCCESS && status != LOCKER_EMOUNTPOINTBUSY)
177            return status;
178        }
179      else
180        dstatus = LOCKER_SUCCESS;
181
182      /* Mark the locker detached. */
183      at->attached = 0;
184    }
185  locker__update_attachent(context, at);
186
187  /* Unauthenticate. */
188  if (options & LOCKER_DETACH_OPT_UNAUTH)
189    at->fs->auth(context, at, LOCKER_AUTH_DEFAULT, LOCKER_AUTH_UNAUTHENTICATE);
190
191  /* Record zephyr unsubscriptions. */
192  if (options & LOCKER_DETACH_OPT_UNZEPHYR)
193    at->fs->zsubs(context, at);
194
195  return dstatus;
196}
197
198static void del_owner(locker_context context, locker_attachent *at,
199                      uid_t user)
200{
201  int i;
202
203  for (i = 0; i < at->nowners; i++)
204    {
205      if (at->owners[i] == user)
206        {
207          at->owners[i] = at->owners[--at->nowners];
208          return;
209        }
210    }
211}
212
213static void clean_owners(locker_context context, locker_attachent *at)
214{
215  int i;
216
217  for (i = 0; i < at->nowners; )
218    {
219      if (!getpwuid(at->owners[i]))
220        at->owners[i] = at->owners[--at->nowners];
221      else
222        i++;
223    }
224}
Note: See TracBrowser for help on using the repository browser.