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