]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/unix.c
implemented config.h
[netatalk.git] / etc / afpd / unix.c
1 /*
2  * Copyright (c) 1990,1993 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/param.h>
15 #include <sys/stat.h>
16 #include <sys/syslog.h>
17 #include <netatalk/endian.h>
18 #include <dirent.h>
19 #include <limits.h>
20 #include <atalk/afp.h>
21 #include <string.h>
22 #include <fcntl.h>
23 #include "auth.h"
24 #include "directory.h"
25 #include "volume.h"
26 #include "unix.h"
27
28 /*
29  * Get the free space on a partition.
30  */
31 int ustatfs_getvolspace( vol, bfree, btotal, bsize )
32     const struct vol    *vol;
33     VolSpace    *bfree, *btotal;
34     u_int32_t   *bsize;
35 {
36 #ifdef ultrix
37     struct fs_data      sfs;
38 #else /*ultrix*/
39     struct statfs       sfs;
40 #endif /*ultrix*/
41
42     if ( statfs( vol->v_path, &sfs ) < 0 ) {
43         return( AFPERR_PARAM );
44     }
45
46 #ifdef ultrix
47     *bfree = (VolSpace) sfs.fd_req.bfreen * 1024;
48     *bsize = 1024;
49 #else
50     *bfree = (VolSpace) sfs.f_bavail * sfs.f_frsize;
51     *bsize = sfs.f_frsize;
52 #endif ultrix
53
54 #ifdef ultrix
55     *btotal = (VolSpace) 
56       ( sfs.fd_req.btot - ( sfs.fd_req.bfree - sfs.fd_req.bfreen )) * 1024;
57 #else ultrix
58     *btotal = (VolSpace) 
59       ( sfs.f_blocks - ( sfs.f_bfree - sfs.f_bavail )) * sfs.f_frsize;
60 #endif ultrix
61     return( AFP_OK );
62 }
63
64 static __inline__ int utombits( bits )
65     mode_t      bits;
66 {
67     int         mbits;
68
69     mbits = 0;
70
71     mbits |= ( bits & ( S_IREAD >> 6 )) ? AR_UREAD : 0;
72     mbits |= ( bits & ( S_IWRITE >> 6 )) ? AR_UWRITE : 0;
73     mbits |= ( bits & ( S_IEXEC >> 6) ) ? AR_USEARCH : 0;
74
75     return( mbits );
76 }
77
78 void utommode( stat, ma )
79     struct stat         *stat;
80     struct maccess      *ma;
81 {
82     mode_t              mode;
83
84     mode = stat->st_mode;
85
86     ma->ma_world = utombits( mode );
87     mode = mode >> 3;
88
89     ma->ma_group = utombits( mode );
90     mode = mode >> 3;
91
92     ma->ma_owner = utombits( mode );
93
94     if ( uuid == stat->st_uid ) {
95         ma->ma_user = ma->ma_owner | AR_UOWN;
96     } else if ( gmem( stat->st_gid )) {
97         ma->ma_user = ma->ma_group;
98     } else {
99         ma->ma_user = ma->ma_world;
100     }
101
102     /*
103      * There are certain things the mac won't try if you don't have
104      * the "owner" bit set, even tho you can do these things on unix wiht
105      * only write permission.  What were the things?
106      */
107     if ( ma->ma_user & AR_UWRITE ) {
108         ma->ma_user |= AR_UOWN;
109     }
110 }
111
112
113 int gmem( gid )
114     const gid_t gid;
115 {
116     int         i;
117
118     for ( i = 0; i < ngroups; i++ ) {
119         if ( groups[ i ] == gid ) {
120             return( 1 );
121         }
122     }
123     return( 0 );
124 }
125
126 static __inline__ mode_t mtoubits( bits )
127     u_char      bits;
128 {
129     mode_t      mode;
130
131     mode = 0;
132
133     mode |= ( bits & AR_UREAD ) ? ( S_IREAD >> 6 ) : 0;
134     mode |= ( bits & AR_UWRITE ) ? ( S_IWRITE >> 6 ) : 0;
135     mode |= ( bits & AR_USEARCH ) ? ( S_IEXEC >> 6 ) : 0;
136
137     return( mode );
138 }
139
140 mode_t mtoumode( ma )
141     struct maccess      *ma;
142 {
143     mode_t              mode;
144
145     mode = 0;
146     mode |= mtoubits( ma->ma_owner );
147     mode = mode << 3;
148
149     mode |= mtoubits( ma->ma_group );
150     mode = mode << 3;
151
152     mode |= mtoubits( ma->ma_world );
153
154     return( mode );
155 }
156
157
158 int setdeskmode( mode )
159     const mode_t        mode;
160 {
161     char                wd[ MAXPATHLEN + 1];
162     struct stat         st;
163     char                modbuf[ 12 + 1], *m;
164     struct dirent       *deskp, *subp;
165     DIR                 *desk, *sub;
166
167     if ( getcwd( wd , MAXPATHLEN) == NULL ) {
168         return( -1 );
169     }
170     if ( chdir( ".AppleDesktop" ) < 0 ) {
171         return( -1 );
172     }
173     if (( desk = opendir( "." )) == NULL ) {
174         if ( chdir( wd ) < 0 ) {
175             syslog( LOG_ERR, "setdeskmode: chdir %s: %m", wd );
176         }
177         return( -1 );
178     }
179     for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
180         if ( strcmp( deskp->d_name, "." ) == 0 ||
181                 strcmp( deskp->d_name, ".." ) == 0 || strlen( deskp->d_name ) > 2 ) {
182             continue;
183         }
184         strcpy( modbuf, deskp->d_name );
185         strcat( modbuf, "/" );
186         m = strchr( modbuf, '\0' );
187         if (( sub = opendir( deskp->d_name )) == NULL ) {
188             continue;
189         }
190         for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
191             if ( strcmp( subp->d_name, "." ) == 0 ||
192                     strcmp( subp->d_name, ".." ) == 0 ) {
193                 continue;
194             }
195             *m = '\0';
196             strcat( modbuf, subp->d_name );
197             /* XXX: need to preserve special modes */
198             if (stat(modbuf, &st) < 0) {
199                 syslog( LOG_DEBUG, "setdeskmode: stat %s: %m", modbuf );
200                 continue;
201             }       
202
203             if (S_ISDIR(st.st_mode)) {
204               if ( chmod( modbuf,  DIRBITS | mode ) < 0 ) {
205                 syslog( LOG_DEBUG, "setdeskmode: chmod %s: %m", modbuf );
206               }
207             } else if ( chmod( modbuf,  mode ) < 0 ) {
208                 syslog( LOG_DEBUG, "setdeskmode: chmod %s: %m", modbuf );
209             }
210
211         }
212         closedir( sub );
213         /* XXX: need to preserve special modes */
214         if ( chmod( deskp->d_name,  DIRBITS | mode ) < 0 ) {
215             syslog( LOG_DEBUG, "setdeskmode: chmod %s: %m", deskp->d_name );
216         }
217     }
218     closedir( desk );
219     if ( chdir( wd ) < 0 ) {
220         syslog( LOG_ERR, "setdeskmode: chdir %s: %m", wd );
221         return -1;
222     }
223     /* XXX: need to preserve special modes */
224     if ( chmod( ".AppleDesktop",  DIRBITS | mode ) < 0 ) {
225         syslog( LOG_DEBUG, "setdeskmode: chmod .AppleDesktop: %m" );
226     }
227     return( 0 );
228 }
229
230 int setdirmode( mode, noadouble )
231     const mode_t mode;
232     const int noadouble;
233 {
234     char                buf[ MAXPATHLEN + 1];
235     struct stat         st;
236     char                *m;
237     struct dirent       *dirp;
238     DIR                 *dir;
239
240     if (( dir = opendir( "." )) == NULL ) {
241         syslog( LOG_ERR, "setdirmode: opendir .: %m" );
242         return( -1 );
243     }
244
245     for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
246         if ( *dirp->d_name == '.' ) {
247             continue;
248         }
249         if ( stat( dirp->d_name, &st ) < 0 ) {
250             syslog( LOG_DEBUG, "setdirmode: stat %s: %m", dirp->d_name );
251             continue;
252         }
253
254         if (S_ISREG(st.st_mode)) {
255             /* XXX: need to preserve special modes */
256             if (S_ISDIR(st.st_mode)) {
257               if ( chmod( dirp->d_name, DIRBITS | mode ) < 0 ) {
258                 syslog( LOG_DEBUG, "setdirmode: chmod %s: %m", dirp->d_name );
259               }
260             } else if ( chmod( dirp->d_name, mode ) < 0 ) {
261                 syslog( LOG_DEBUG, "setdirmode: chmod %s: %m", dirp->d_name );
262             }
263         }
264     }
265     closedir( dir );
266     if (( dir = opendir( ".AppleDouble" )) == NULL ) {
267         if (noadouble)
268           goto setdirmode_noadouble;
269         syslog( LOG_ERR, "setdirmode: opendir .AppleDouble: %m" );
270         return( -1 );
271     }
272     strcpy( buf, ".AppleDouble" );
273     strcat( buf, "/" );
274     m = strchr( buf, '\0' );
275     for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
276         if ( strcmp( dirp->d_name, "." ) == 0 ||
277                 strcmp( dirp->d_name, ".." ) == 0 ) {
278             continue;
279         }
280         *m = '\0';
281         strcat( buf, dirp->d_name );
282
283         if ( stat( buf, &st ) < 0 ) {
284             syslog( LOG_DEBUG, "setdirmode: stat %s: %m", buf );
285             continue;
286         }
287
288         if (S_ISDIR(st.st_mode)) {
289           if ( chmod(buf,  DIRBITS | mode) < 0 ) {
290             syslog( LOG_DEBUG, "setdirmode: chmod %s: %m", buf );
291           }
292         } else if ( chmod(buf, mode) < 0 ) {
293             syslog( LOG_DEBUG, "setdirmode: chmod %s: %m", buf );
294         }
295     }
296     closedir( dir );
297
298     /* XXX: use special bits to tag directory permissions */
299       
300     /* XXX: need to preserve special modes */
301     if ( chmod( ".AppleDouble",  DIRBITS | mode ) < 0 ) {
302         syslog( LOG_ERR, "setdirmode: chmod .AppleDouble: %m" );
303         return( -1 );
304     }
305
306 setdirmode_noadouble:
307     /* XXX: need to preserve special modes */
308     if ( chmod( ".",  DIRBITS | mode ) < 0 ) {
309         syslog( LOG_ERR, "setdirmode: chmod .: %m" );
310         return( -1 );
311     }
312     return( 0 );
313 }
314
315 int setdeskowner( uid, gid )
316     const uid_t uid;
317     const gid_t gid;
318 {
319     char                wd[ MAXPATHLEN + 1];
320     char                modbuf[12 + 1], *m;
321     struct dirent       *deskp, *subp;
322     DIR                 *desk, *sub;
323
324     if ( getcwd( wd, MAXPATHLEN ) == NULL ) {
325         return( -1 );
326     }
327     if ( chdir( ".AppleDesktop" ) < 0 ) {
328         return( -1 );
329     }
330     if (( desk = opendir( "." )) == NULL ) {
331         if ( chdir( wd ) < 0 ) {
332             syslog( LOG_ERR, "setdeskowner: chdir %s: %m", wd );
333         }
334         return( -1 );
335     }
336     for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
337         if ( strcmp( deskp->d_name, "." ) == 0 ||
338              strcmp( deskp->d_name, ".." ) == 0 || 
339              strlen( deskp->d_name ) > 2 ) {
340             continue;
341         }
342         strcpy( modbuf, deskp->d_name );
343         strcat( modbuf, "/" );
344         m = strchr( modbuf, '\0' );
345         if (( sub = opendir( deskp->d_name )) == NULL ) {
346             continue;
347         }
348         for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
349             if ( strcmp( subp->d_name, "." ) == 0 ||
350                  strcmp( subp->d_name, ".." ) == 0 ) {
351                 continue;
352             }
353             *m = '\0';
354             strcat( modbuf, subp->d_name );
355             /* XXX: add special any uid, ignore group bits */
356             if ( chown( modbuf, uid, gid ) < 0 ) {
357                 syslog( LOG_DEBUG, "setdeskown: chown %s: %m", modbuf );
358             }
359         }
360         closedir( sub );
361         /* XXX: add special any uid, ignore group bits */
362         if ( chown( deskp->d_name, uid, gid ) < 0 ) {
363             syslog( LOG_DEBUG, "setdeskowner: chown %s: %m", deskp->d_name );
364         }
365     }
366     closedir( desk );
367     if ( chdir( wd ) < 0 ) {
368         syslog( LOG_ERR, "setdeskowner: chdir %s: %m", wd );
369         return -1;
370     }
371     if ( chown( ".AppleDesktop", uid, gid ) < 0 ) {
372         syslog( LOG_ERR, "setdeskowner: chown .AppleDesktop: %m" );
373     }
374     return( 0 );
375 }
376
377
378 /* uid/gid == 0 need to be handled as special cases. they really mean
379  * that user/group should inherit from other, but that doesn't fit
380  * into the unix permission scheme. we can get around this by
381  * co-opting some bits. */
382 int setdirowner( uid, gid, noadouble )
383     const uid_t uid;
384     const gid_t gid;
385     const int   noadouble;
386 {
387     char                buf[ MAXPATHLEN + 1];
388     struct stat         st;
389     char                *m;
390     struct dirent       *dirp;
391     DIR                 *dir;
392
393     if (( dir = opendir( "." )) == NULL ) {
394         return( -1 );
395     }
396     for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
397         if ( *dirp->d_name == '.' ) {
398             continue;
399         };
400         if ( stat( dirp->d_name, &st ) < 0 ) {
401             syslog( LOG_DEBUG, "setdirowner: stat %s: %m", dirp->d_name );
402             continue;
403         }
404         if (( st.st_mode & S_IFMT ) == S_IFREG ) {
405             if ( chown( dirp->d_name, uid, gid ) < 0 ) {
406                 syslog( LOG_DEBUG, "setdirowner: chown %s: %m", dirp->d_name );
407             }
408         }
409     }
410     closedir( dir );
411     if (( dir = opendir( ".AppleDouble" )) == NULL ) {
412       if (noadouble)
413         goto setdirowner_noadouble;
414       return( -1 );
415     }
416     strcpy( buf, ".AppleDouble" );
417     strcat( buf, "/" );
418     m = strchr( buf, '\0' );
419     for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
420         if ( strcmp( dirp->d_name, "." ) == 0 ||
421                 strcmp( dirp->d_name, ".." ) == 0 ) {
422             continue;
423         }
424         *m = '\0';
425         strcat( buf, dirp->d_name );
426         if ( chown( buf, uid, gid ) < 0 ) {
427             syslog( LOG_DEBUG, "setdirowner: chown %d/%d %s: %m",
428                     uid, gid, buf );
429         }
430     }
431     closedir( dir );
432
433     /*
434      * We cheat: we know that chown doesn't do anything.
435      */
436     if ( stat( ".AppleDouble", &st ) < 0 ) {
437         syslog( LOG_ERR, "setdirowner: stat .AppleDouble: %m" );
438         return( -1 );
439     }
440     if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 ) {
441         syslog( LOG_DEBUG, "setdirowner: chown %d/%d .AppleDouble: %m",
442                 uid, gid);
443     }
444
445 setdirowner_noadouble:
446     if ( stat( ".", &st ) < 0 ) {
447         return( -1 );
448     }
449     if ( gid && gid != st.st_gid && chown( ".", uid, gid ) < 0 ) {
450         syslog( LOG_DEBUG, "setdirowner: chown %d/%d .: %m",
451                 uid, gid);
452     }
453
454     return( 0 );
455 }