Exemplo n.º 1
0
int appledouble_getattr(struct afp_volume * volume, 
	const char * path, struct stat *stbuf)
{
	unsigned int resource;
	char * newpath;
	int ret;

	resource = extra_translate(volume, path, &newpath);
	switch(resource) {
		case AFP_META_RESOURCE:
			ll_getattr(volume,newpath,stbuf,1);
			goto okay;
		case AFP_META_APPLEDOUBLE:
			stbuf->st_mode = 0700 | S_IFDIR;
			goto okay;
		case AFP_META_FINDERINFO:
			ll_getattr(volume,newpath,stbuf,0);
			stbuf->st_mode |= S_IFREG;
			stbuf->st_size=32;
			goto okay;
		case AFP_META_COMMENT: {
			unsigned int did;
			char basename[AFP_MAX_PATH];

			ret=ll_getattr(volume,newpath,stbuf,0);
			if (ret<0) 
				goto error;

			ret=get_dirid(volume,newpath,basename,&did);
			if (ret<0) 
				goto error;

			ret=get_comment_size(volume,basename,did);
			if (ret<0) 
				goto error;

			stbuf->st_mode |= S_IFREG;
			stbuf->st_size=ret;
			goto okay;
		}
		case AFP_META_SERVER_ICON:
			stbuf->st_mode = S_IFREG | 0444;
			stbuf->st_size=256;
			goto okay;
	}
	return 0;
okay:
	free(newpath);
	return 1;
error:
	free(newpath);
	return ret;

}
Exemplo n.º 2
0
int ml_getattr(struct afp_volume * volume, const char *path, struct stat *stbuf)
{
	char converted_path[AFP_MAX_PATH];
	int ret;

	memset(stbuf, 0, sizeof(struct stat));

	if (convert_path_to_afp(volume->server->path_encoding,
		converted_path,(char *) path,AFP_MAX_PATH)) {
		return -EINVAL;
	}

	/* If this is a fake file (comment, finderinfo, rsrc), continue since
	 * we'll use the permissions of the real file */

	ret = appledouble_getattr(volume,converted_path, stbuf);

	if (ret<0) return ret;
	if (ret>0) return 0;

	return ll_getattr(volume,path,stbuf,0);
}
Exemplo n.º 3
0
int ml_chown(struct afp_volume * vol, const char * path, 
	uid_t uid, gid_t gid) 
{
	int ret;
	struct afp_file_info fp;
	int rc;
	unsigned int dirid;
	char basename[AFP_MAX_PATH];
	char converted_path[AFP_MAX_PATH];

	if (convert_path_to_afp(vol->server->path_encoding,
		converted_path,(char *) path,AFP_MAX_PATH))
		return -EINVAL;

	if (invalid_filename(vol->server,converted_path)) 
		return -ENAMETOOLONG;

	if (volume_is_readonly(vol))
		return -EACCES;

	ret=appledouble_chown(vol,path,uid,gid);
	if (ret<0) return ret;
	if (ret==1) return 0;

	/* There's no way to do this in AFP < 3.0 */
	if (~ vol->extra_flags & VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX) {

		if (vol->extra_flags & VOLUME_EXTRA_FLAGS_IGNORE_UNIXPRIVS) {
			struct stat stbuf;
			/* See if the file exists */
			ret=ll_getattr(vol,path,&stbuf,0);
			return ret;
		}

		return -ENOSYS;
	};

	get_dirid(vol,converted_path,basename,&dirid );

	if ((rc=get_unixprivs(vol,
		dirid,basename, &fp)))
		return rc;

#if 0
FIXME
	set_uidgid(volume,&fp,uid,gid);
THIS IS the wrong set of returns to check...
#endif
	rc=set_unixprivs(vol, dirid, basename, &fp);

	switch(rc) {
	case -ENOSYS:
		return -ENOSYS;
	case kFPNoErr:
		break;
	case kFPAccessDenied:
		return -EACCES;
	case kFPObjectNotFound:
		return -ENOENT;
	case kFPBitmapErr:
	case kFPMiscErr:
	case kFPObjectTypeErr:
	case kFPParamErr:
	default:
		break;

	}

	return 0;
}
Exemplo n.º 4
0
int ml_chmod(struct afp_volume * vol, const char * path, mode_t mode) 
{
/*
chmod has an interesting story to it.  

It is known to work with Darwin 10.3.9 (AFP 3.1), 10.4.2 and 10.5.x (AFP 3.2).

chmod will not work properly in the following situations:

- AFP 2.2, this needs some more verification but I don't see how it is possible

- netatalk 2.0.3 and probably earlier:

  . netatalk will only enable it at all if you have "options=upriv" 
    set for that volume.

  . netatalk will never be able to chmod the execute bit and some others on 
    files; this is hard coded in unix.c's setfilemode() in 2.0.3.  It's like
    it has 2.2 behaviour even though it is trying to speak 3.1.

  . The only bits allowed are
        S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP |S_IROTH | S_IWOTH;
    There's probably a reason for this, I don't know what it is.

  . afpfs-ng's behaviour's the same as the Darwin client.

The right way to see if a volume supports chmod is to check the attributes
found with getvolparm or volopen, then to test chmod the first time.

*/

	int ret=0,rc;
	struct afp_file_info fp;
	unsigned int dirid;
	char basename[AFP_MAX_PATH];
	char converted_path[AFP_MAX_PATH];
	uid_t uid; gid_t gid;

	if (invalid_filename(vol->server,path)) 
		return -ENAMETOOLONG;

	if (volume_is_readonly(vol))
		return -EACCES;


	/* There's no way to do this in AFP < 3.0 */
	if (~ vol->extra_flags & VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX) {

		if (vol->extra_flags & VOLUME_EXTRA_FLAGS_IGNORE_UNIXPRIVS) {
			struct stat stbuf;
			/* See if the file exists */
			ret=ll_getattr(vol,path,&stbuf,0);
			return ret;
		}

		return -ENOSYS;
	};

	if (convert_path_to_afp(vol->server->path_encoding,
		converted_path,(char *) path,AFP_MAX_PATH)) {
		return -EINVAL;
	}

	ret=appledouble_chmod(vol,path,mode);
	if (ret<0) return ret;
	if (ret==1) return 0;

	get_dirid(vol,converted_path,basename,&dirid );

	if ((rc=get_unixprivs(vol,
		dirid,basename, &fp))) 
		return rc;

	mode&=(~S_IFDIR);

	/* Don't bother updating it if it's already the same */
	if ((fp.unixprivs.permissions&(~S_IFDIR))==mode)
		return 0;

	/* Check to make sure that we can; some servers (at least netatalk)
	   don't report an error when you try to setfileparm when you don't
	   own the file.  */

	/* Try to guess if the operation is possible */

	uid=fp.unixprivs.uid;
	gid=fp.unixprivs.gid;
	if (translate_uidgid_to_client(vol, &uid,&gid))
		return -EIO;

	if ((gid!=getgid()) && (uid!=geteuid())) {
		return -EPERM;
	}
	
	fp.unixprivs.permissions=mode;

	rc=set_unixprivs(vol, dirid,basename, &fp);
	if (rc==-ENOSYS) {
		return -ENOSYS;
	}



	return -ret;
}