#include <atalk/afp.h>
#include <atalk/util.h>
#include <atalk/logger.h>
+#include <atalk/globals.h>
+#include <atalk/netatalk_conf.h>
+#include <atalk/unix.h>
+#include <atalk/bstrlib.h>
+#include <atalk/errchk.h>
+
#include "volume.h"
#include "directory.h"
#include "fork.h"
-#include "globals.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(bdata(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 ( chmod_acl( modbuf, (DIRBITS | mode)) < 0 && errno != EPERM ) {
+ LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
+ }
+ } else if ( chmod_acl( modbuf, mode & ~EXEC_MODE ) < 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 ( chmod_acl( deskp->d_name, (DIRBITS | mode)) < 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 ( chmod_acl(bdata(dtpath), (DIRBITS | mode)) < 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(bdata(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(bdata(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;
+ struct stat st;
+ char *cmd_argv[4];
+
+ olddtpath = bfromcstr(vol->v_path);
+ bcatcstr(olddtpath, "/" APPLEDESKTOP);
+
+ dtpath = bfromcstr(vol->v_dbpath);
+ bcatcstr(dtpath, "/" APPLEDESKTOP);
+
+ if (lstat(bdata(dtpath), &st) != 0) {
+
+ become_root();
+
+ if (lstat(bdata(olddtpath), &st) == 0) {
+ cmd_argv[0] = "mv";
+ cmd_argv[1] = bdata(olddtpath);
+ cmd_argv[2] = bdata(dtpath);
+ cmd_argv[3] = NULL;
+ 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);
+ }
+ } else {
+ mkdir(bdata(dtpath), 0777);
+ }
+
+ unbecome_root();
+ }
+
+ bdestroy(dtpath);
+ bdestroy(olddtpath);
+}
int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct vol *vol;
- u_int16_t vid;
+ uint16_t vid;
ibuf += 2;
return( AFPERR_PARAM );
}
+ create_appledesktop_folder(vol);
+
memcpy( rbuf, &vid, sizeof(vid));
*rbuflen = sizeof(vid);
return( AFP_OK );
u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
int itype, cc = AFP_OK, iovcnt = 0;
size_t buflen;
- u_int32_t ftype, itag;
- u_int16_t bsize, rsize, vid;
+ uint32_t ftype, itag;
+ uint16_t bsize, rsize, vid;
buflen = *rbuflen;
*rbuflen = 0;
*/
addicon_err:
if ( cc < 0 ) {
- if (obj->proto == AFPPROTO_DSI) {
- dsi_writeinit(obj->handle, rbuf, buflen);
- dsi_writeflush(obj->handle);
- }
+ dsi_writeinit(obj->dsi, rbuf, buflen);
+ dsi_writeflush(obj->dsi);
return cc;
}
- switch (obj->proto) {
- case AFPPROTO_DSI:
- {
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
- iovcnt = dsi_writeinit(dsi, rbuf, buflen);
+ iovcnt = dsi_writeinit(dsi, rbuf, buflen);
- /* add headers at end of file */
- if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
- LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
- dsi_writeflush(dsi);
- return AFPERR_PARAM;
- }
+ /* add headers at end of file */
+ if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
+ LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
+ dsi_writeflush(dsi);
+ return AFPERR_PARAM;
+ }
- if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
- LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
- dsi_writeflush(dsi);
- return AFPERR_PARAM;
- }
+ if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
+ LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
+ dsi_writeflush(dsi);
+ return AFPERR_PARAM;
+ }
- while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
- if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
- LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
- dsi_writeflush(dsi);
- return AFPERR_PARAM;
- }
- }
+ while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
+ if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
+ LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
+ dsi_writeflush(dsi);
+ return AFPERR_PARAM;
}
- break;
}
close( si.sdt_fd );
int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct vol *vol;
- u_char fcreator[ 4 ], ih[ 12 ];
- u_int16_t vid, iindex, bsize;
+ unsigned char fcreator[ 4 ], ih[ 12 ];
+ uint16_t vid, iindex, bsize;
*rbuflen = 0;
ibuf += 2;
off_t offset;
ssize_t rc, buflen;
u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
- u_int16_t vid, bsize, rsize;
+ uint16_t vid, bsize, rsize;
buflen = *rbuflen;
*rbuflen = 0;
#define min(a,b) ((a)<(b)?(a):(b))
rc = min( bsize, rsize );
- if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
- DSI *dsi = obj->handle;
+ if (buflen < rc) {
+ DSI *dsi = obj->dsi;
struct stat st;
off_t size;
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 (!obj->options.flags & OPTION_DEBUG) {
- if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
- switch (errno) {
- case ENOSYS:
- case EINVAL: /* there's no guarantee that all fs support sendfile */
- break;
- default:
- goto geticon_exit;
- }
- }
- else {
- dsi_readdone(dsi);
- return AFP_OK;
+ 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 */
+ break;
+ default:
+ goto geticon_exit;
}
}
+ else {
+ dsi_readdone(dsi);
+ return AFP_OK;
+ }
#endif
buflen = read(si.sdt_fd, rbuf, *rbuflen);
if (buflen < 0)
char *p;
unsigned int i;
- strcpy( path, vol->v_path );
- strcat( path, "/.AppleDesktop/" );
+ strcpy( path, vol->v_dbpath );
+ strcat( path, "/" APPLEDESKTOP "/" );
for ( p = path; *p != '\0'; p++ )
;
char *m, *u;
size_t inplen;
size_t outlen;
- u_int16_t flags;
+ uint16_t flags;
if ( *mpath == '\0' ) {
strcpy(upath, ".");
{
static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
char *m, *u;
- u_int16_t flags;
+ uint16_t flags;
size_t outlen;
m = mpath;
}
/* ------------------------- */
-static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
+static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
{
struct ofork *of;
char *name, *upath;
clen = min( clen, 199 );
upath = path->u_name;
- if (check_access(upath, OPENACC_WR ) < 0) {
+ if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
}
isadir = path_isadir(path);
if (isadir || !(of = of_findname(path))) {
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ ad_init(&ad, vol);
adp = &ad;
} else
adp = of->of_ad;
if (ad_open(adp, upath,
- ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0),
- O_CREAT | O_RDWR,
+ ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
0666) < 0 ) {
return( AFPERR_ACCESS );
}
memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
ad_flush( adp );
}
- ad_close_metadata( adp);
+ ad_close(adp, ADFLAGS_HF);
return( AFP_OK );
}
/* ----------------------------- */
-int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
+int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *vol;
struct dir *dir;
struct path *path;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
ibuf++;
}
- return ad_addcomment(vol, path, ibuf);
+ return ad_addcomment(obj, vol, path, ibuf);
}
/* -------------------- */
upath = path->u_name;
isadir = path_isadir(path);
if (isadir || !(of = of_findname(path))) {
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ ad_init(&ad, vol);
adp = &ad;
} else
adp = of->of_ad;
}
if (!ad_getentryoff(adp, ADEID_COMMENT)) {
- ad_close_metadata( adp );
+ ad_close(adp, ADFLAGS_HF);
return AFPERR_NOITEM;
}
/*
*/
if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
- ad_close_metadata( adp );
+ ad_close(adp, ADFLAGS_HF);
return( AFPERR_NOITEM );
}
*rbuf++ = clen;
memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
*rbuflen = clen + 1;
- ad_close_metadata( adp);
+ ad_close(adp, ADFLAGS_HF);
return( AFP_OK );
}
struct vol *vol;
struct dir *dir;
struct path *s_path;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
}
/* ----------------------- */
-static int ad_rmvcomment(struct vol *vol, struct path *path)
+static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
{
struct adouble ad, *adp;
struct ofork *of;
char *upath;
upath = path->u_name;
- if (check_access(upath, OPENACC_WR ) < 0) {
+ if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
}
isadir = path_isadir(path);
if (isadir || !(of = of_findname(path))) {
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ ad_init(&ad, vol);
adp = &ad;
} else
adp = of->of_ad;
- if ( ad_open(adp, upath, ADFLAGS_HF | (isadir) ? ADFLAGS_DIR : 0, 0) < 0 ) {
+ if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
switch ( errno ) {
case ENOENT :
return( AFPERR_NOITEM );
ad_setentrylen( adp, ADEID_COMMENT, 0 );
ad_flush( adp );
}
- ad_close_metadata( adp);
+ ad_close(adp, ADFLAGS_HF);
return( AFP_OK );
}
struct vol *vol;
struct dir *dir;
struct path *s_path;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
return get_afp_errno(AFPERR_NOOBJ);
}
- return ad_rmvcomment(vol, s_path);
+ return ad_rmvcomment(obj, vol, s_path);
}