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