#include <atalk/netatalk_conf.h>
#include <atalk/unix.h>
#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
+#include <atalk/errchk.h>
#include "volume.h"
#include "directory.h"
#include "desktop.h"
#include "mangle.h"
+#define EXEC_MODE (S_IXGRP | S_IXUSR | S_IXOTH)
+
+int setdeskmode(const struct vol *vol, const mode_t mode)
+{
+ EC_INIT;
+ char wd[ MAXPATHLEN + 1];
+ struct stat st;
+ char modbuf[ 12 + 1], *m;
+ struct dirent *deskp, *subp;
+ DIR *desk, *sub;
+
+ if (!dir_rx_set(mode)) {
+ /* want to remove read and search access to owner it will screw the volume */
+ return -1 ;
+ }
+ if ( getcwd( wd , MAXPATHLEN) == NULL ) {
+ return( -1 );
+ }
+
+ bstring dtpath = bfromcstr(vol->v_dbpath);
+ bcatcstr(dtpath, "/" APPLEDESKTOP);
+
+ EC_NEG1( chdir(cfrombstr(dtpath)) );
+
+ if (( desk = opendir( "." )) == NULL ) {
+ if ( chdir( wd ) < 0 ) {
+ LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) );
+ }
+ EC_FAIL;
+ }
+ for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
+ if ( strcmp( deskp->d_name, "." ) == 0 ||
+ strcmp( deskp->d_name, ".." ) == 0 || strlen( deskp->d_name ) > 2 ) {
+ continue;
+ }
+ strcpy( modbuf, deskp->d_name );
+ strcat( modbuf, "/" );
+ m = strchr( modbuf, '\0' );
+ if (( sub = opendir( deskp->d_name )) == NULL ) {
+ continue;
+ }
+ for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
+ if ( strcmp( subp->d_name, "." ) == 0 ||
+ strcmp( subp->d_name, ".." ) == 0 ) {
+ continue;
+ }
+ *m = '\0';
+ strcat( modbuf, subp->d_name );
+ /* XXX: need to preserve special modes */
+ if (lstat(modbuf, &st) < 0) {
+ LOG(log_error, logtype_afpd, "setdeskmode: stat %s: %s",fullpathname(modbuf), strerror(errno) );
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ if (ochmod(modbuf,
+ DIRBITS | mode,
+ &st,
+ vol_syml_opt(vol) | vol_chmod_opt(vol)
+ ) < 0 && errno != EPERM) {
+ LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
+ }
+ } else if (ochmod(modbuf,
+ mode & ~EXEC_MODE,
+ &st,
+ vol_syml_opt(vol) | vol_chmod_opt(vol)
+ ) < 0 && errno != EPERM) {
+ LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
+ }
+
+ }
+ closedir( sub );
+ /* XXX: need to preserve special modes */
+ if (ochmod(deskp->d_name,
+ DIRBITS | mode,
+ NULL,
+ vol_syml_opt(vol) | vol_chmod_opt(vol)
+ ) < 0 && errno != EPERM) {
+ LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) );
+ }
+ }
+ closedir( desk );
+ if ( chdir( wd ) < 0 ) {
+ LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) );
+ EC_FAIL;
+ }
+ /* XXX: need to preserve special modes */
+ if (ochmod(bdata(dtpath),
+ DIRBITS | mode,
+ NULL,
+ vol_syml_opt(vol) | vol_chmod_opt(vol)
+ ) < 0 && errno != EPERM) {
+ LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno));
+ }
+
+EC_CLEANUP:
+ bdestroy(dtpath);
+ EC_EXIT;
+}
+
+int setdeskowner(const struct vol *vol, uid_t uid, gid_t gid)
+{
+ EC_INIT;
+ char wd[ MAXPATHLEN + 1];
+ char modbuf[12 + 1], *m;
+ struct dirent *deskp, *subp;
+ DIR *desk, *sub;
+
+ if ( getcwd( wd, MAXPATHLEN ) == NULL ) {
+ return( -1 );
+ }
+
+ bstring dtpath = bfromcstr(vol->v_dbpath);
+ bcatcstr(dtpath, "/" APPLEDESKTOP);
+
+ EC_NEG1( chdir(cfrombstr(dtpath)) );
+
+ if (( desk = opendir( "." )) == NULL ) {
+ if ( chdir( wd ) < 0 ) {
+ LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
+ }
+ EC_FAIL;
+ }
+ for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
+ if ( strcmp( deskp->d_name, "." ) == 0 ||
+ strcmp( deskp->d_name, ".." ) == 0 ||
+ strlen( deskp->d_name ) > 2 ) {
+ continue;
+ }
+ strcpy( modbuf, deskp->d_name );
+ strcat( modbuf, "/" );
+ m = strchr( modbuf, '\0' );
+ if (( sub = opendir( deskp->d_name )) == NULL ) {
+ continue;
+ }
+ for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
+ if ( strcmp( subp->d_name, "." ) == 0 ||
+ strcmp( subp->d_name, ".." ) == 0 ) {
+ continue;
+ }
+ *m = '\0';
+ strcat( modbuf, subp->d_name );
+ /* XXX: add special any uid, ignore group bits */
+ if ( chown( modbuf, uid, gid ) < 0 && errno != EPERM ) {
+ LOG(log_error, logtype_afpd, "setdeskown: chown %s: %s", fullpathname(modbuf), strerror(errno) );
+ }
+ }
+ closedir( sub );
+ /* XXX: add special any uid, ignore group bits */
+ if ( chown( deskp->d_name, uid, gid ) < 0 && errno != EPERM ) {
+ LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s",
+ deskp->d_name, strerror(errno) );
+ }
+ }
+ closedir( desk );
+ if ( chdir( wd ) < 0 ) {
+ LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
+ EC_FAIL;
+ }
+ if (chown(cfrombstr(dtpath), uid, gid ) < 0 && errno != EPERM ) {
+ LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
+ }
+
+EC_CLEANUP:
+ bdestroy(dtpath);
+ EC_EXIT;
+}
+
static void create_appledesktop_folder(const struct vol * vol)
{
bstring olddtpath = NULL, dtpath = NULL;
dtpath = bfromcstr(vol->v_dbpath);
bcatcstr(dtpath, "/" APPLEDESKTOP);
- if (lstat(bdata(dtpath), &st) != 0) {
+ if (lstat(cfrombstr(dtpath), &st) != 0) {
become_root();
- if (lstat(bdata(olddtpath), &st) == 0) {
+ if (lstat(cfrombstr(olddtpath), &st) == 0) {
cmd_argv[0] = "mv";
cmd_argv[1] = bdata(olddtpath);
cmd_argv[2] = bdata(dtpath);
if (run_cmd("mv", cmd_argv) != 0) {
LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed",
bdata(olddtpath), bdata(dtpath));
- mkdir(bdata(dtpath), 0777);
+ mkdir(cfrombstr(dtpath), 0777);
}
} else {
- mkdir(bdata(dtpath), 0777);
+ mkdir(cfrombstr(dtpath), 0777);
}
unbecome_root();
return AFPERR_PARAM;
}
+#ifndef WITH_SENDFILE
if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
goto geticon_exit;
+#endif
*rbuflen = buflen;
/* do to the streaming nature, we have to exit if we encounter
* a problem. much confusion results otherwise. */
while (*rbuflen > 0) {
#ifdef WITH_SENDFILE
- if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
+ if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize, AFP_OK) < 0) {
switch (errno) {
case ENOSYS:
case EINVAL: /* there's no guarantee that all fs support sendfile */
}
isadir = path_isadir(path);
- if (isadir || !(of = of_findname(path))) {
+ if (isadir || !(of = of_findname(vol, path))) {
ad_init(&ad, vol);
adp = &ad;
} else
upath = path->u_name;
isadir = path_isadir(path);
- if (isadir || !(of = of_findname(path))) {
+ if (isadir || !(of = of_findname(vol, path))) {
ad_init(&ad, vol);
adp = &ad;
} else
}
isadir = path_isadir(path);
- if (isadir || !(of = of_findname(path))) {
+ if (isadir || !(of = of_findname(vol, path))) {
ad_init(&ad, vol);
adp = &ad;
} else