]> arthur.barton.de Git - netatalk.git/blob - libatalk/vfs/unix.c
Extended Attributes support via files in .AppleDouble.
[netatalk.git] / libatalk / vfs / unix.c
1 /*
2  * $Id: unix.c,v 1.1 2009-10-02 09:32:41 franklahm Exp $
3  *
4  * Copyright (c) 1990,1993 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  *
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif /* HAVE_CONFIG_H */
12
13 #include <unistd.h>
14 #include <errno.h>
15 #include <sys/param.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <string.h>
19
20 #include <atalk/afp.h>
21 #include <atalk/util.h>
22 #include <atalk/directory.h>
23 #include <atalk/volume.h>
24 #include <atalk/logger.h>
25
26 /* -----------------------------
27    a dropbox is a folder where w is set but not r eg:
28    rwx-wx-wx or rwx-wx-- 
29    rwx----wx (is not asked by a Mac with OS >= 8.0 ?)
30 */
31 int stickydirmode(const char *name, const mode_t mode, const int dropbox, const mode_t v_umask)
32 {
33     int retval = 0;
34
35 #ifdef DROPKLUDGE
36     /* Turn on the sticky bit if this is a drop box, also turn off the setgid bit */
37     if ((dropbox & AFPVOL_DROPBOX)) {
38         int uid;
39
40         if ( ( (mode & S_IWOTH) && !(mode & S_IROTH)) ||
41              ( (mode & S_IWGRP) && !(mode & S_IRGRP)) )
42         {
43             uid=geteuid();
44             if ( seteuid(0) < 0) {
45                 LOG(log_error, logtype_afpd, "stickydirmode: unable to seteuid root: %s", strerror(errno));
46             }
47             if ( (retval=chmod( name, ( (DIRBITS | mode | S_ISVTX) & ~v_umask) )) < 0) {
48                 LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) );
49             } else {
50                 LOG(log_debug, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(retval) );
51             }
52             seteuid(uid);
53             return retval;
54         }
55     }
56 #endif /* DROPKLUDGE */
57
58     /*
59      *  Ignore EPERM errors:  We may be dealing with a directory that is
60      *  group writable, in which case chmod will fail.
61      */
62     if ( (chmod( name, (DIRBITS | mode) & ~v_umask ) < 0) && errno != EPERM && 
63                 !(errno == ENOENT && (dropbox & AFPVOL_NOADOUBLE)) )  
64     {
65         LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) );
66         retval = -1;
67     }
68
69     return retval;
70 }
71
72 /* ------------------------- */
73 int dir_rx_set(mode_t mode)
74 {
75     return (mode & (S_IXUSR | S_IRUSR)) == (S_IXUSR | S_IRUSR);
76 }
77
78 /* --------------------- */
79 int setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
80 {
81 struct stat sb;
82 mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO;  /* rwx for owner group and other, by default */
83
84     if (!st) {
85         if (stat(name, &sb) != 0)
86             return -1;
87         st = &sb;
88     }
89    
90    mode |= st->st_mode & ~mask; /* keep other bits from previous mode */
91    if ( chmod( name,  mode & ~v_umask ) < 0 && errno != EPERM ) {
92        return -1;
93    }
94    return 0;
95 }
96
97 /* -------------------
98    system rmdir with afp error code.
99    ENOENT is not an error.
100  */
101 int netatalk_rmdir(const char *name)
102 {
103     if (rmdir(name) < 0) {
104         switch ( errno ) {
105         case ENOENT :
106             break;
107         case ENOTEMPTY : 
108             return AFPERR_DIRNEMPT;
109         case EPERM:
110         case EACCES :
111             return AFPERR_ACCESS;
112         case EROFS:
113             return AFPERR_VLOCK;
114         default :
115             return AFPERR_PARAM;
116         }
117     }
118     return AFP_OK;
119 }
120
121 /* -------------------
122    system unlink with afp error code.
123    ENOENT is not an error.
124  */
125 int netatalk_unlink(const char *name)
126 {
127     if (unlink(name) < 0) {
128         switch (errno) {
129         case ENOENT :
130             break;
131         case EROFS:
132             return AFPERR_VLOCK;
133         case EPERM:
134         case EACCES :
135             return AFPERR_ACCESS;
136         default :
137             return AFPERR_PARAM;
138         }
139     }
140     return AFP_OK;
141 }
142
143 char *fullpathname(const char *name)
144 {
145     static char wd[ MAXPATHLEN + 1];
146
147     if ( getcwd( wd , MAXPATHLEN) ) {
148         strlcat(wd, "/", MAXPATHLEN);
149         strlcat(wd, name, MAXPATHLEN);
150     }
151     else {
152         strlcpy(wd, name, MAXPATHLEN);
153     }
154     return wd;
155 }