Esempio n. 1
0
int ml_symlink(struct afp_volume *vol, const char * path1, const char * path2) 
{

	int ret;
	struct afp_file_info fp;
	uint64_t written;
	int rc;
	unsigned int dirid2;
	char basename2[AFP_MAX_PATH];
	char converted_path1[AFP_MAX_PATH];
	char converted_path2[AFP_MAX_PATH];

	if (vol->server->using_version->av_number<30) {
		/* No symlinks for AFP 2.x. */
		ret=ENOSYS;
		goto error;
	}
	/* Yes, you can create symlinks for AFP >=30.  Tested with 10.3.2 */

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

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

	if (volume_is_readonly(vol))
		return -EACCES;

	ret=appledouble_symlink(vol,path1,path2);
	if (ret<0) return ret;
	if (ret==1) return 0;

	get_dirid(vol,converted_path2,basename2,&dirid2 );

	/* 1. create the file */
	rc=afp_createfile(vol,kFPHardCreate,dirid2,basename2);
	switch (rc) {
	case kFPAccessDenied:
		ret=EACCES;
		goto error;
	case kFPDiskFull:
		ret=ENOSPC;
		goto error;
	case kFPObjectExists:
		ret=EEXIST;
		goto error;
	case kFPObjectNotFound:
		ret=ENOENT;
		goto error;
	case kFPFileBusy:
	case kFPVolLocked:
		ret=EBUSY;
		goto error;
	case kFPNoErr:
		ret=0;
		break;
	default:
	case kFPParamErr:
	case kFPMiscErr:
		ret=EIO;
		goto error;
	}

	/* Open the fork */
	rc=afp_openfork(vol,0,
		dirid2,
		AFP_OPENFORK_ALLOWWRITE|AFP_OPENFORK_ALLOWREAD,
		basename2,&fp);
	switch (ret) {
	case kFPAccessDenied:
		ret=EACCES;
		goto error;
	case kFPObjectNotFound:
		ret=ENOENT;
		goto error;
	case kFPObjectLocked:
		ret=EROFS;
		goto error;
	case kFPObjectTypeErr:
		ret=EISDIR;
		goto error;
	case kFPParamErr:
		ret=EACCES;
		goto error;
	case kFPTooManyFilesOpen:
		ret=EMFILE;
		goto error;
	case 0:
		ret=0;
		break;
	case kFPVolLocked:
	case kFPDenyConflict:
	case kFPMiscErr:
	case kFPBitmapErr:
	case -1:
	default:
		ret=EFAULT;
		goto error;
	}

	add_opened_fork(vol, &fp);

	/* Write the name of the file to it */

	rc=afp_writeext(vol,fp.forkid,0,strlen(converted_path1),
		converted_path1,&written);

	switch(afp_closefork(vol,fp.forkid)) {
	case kFPNoErr:
		break;
	default:
	case kFPParamErr:
	case kFPMiscErr:
		ret=EIO;
		goto error;
	}

	remove_opened_fork(vol, &fp);

	/* And now for the undocumented magic */
	memset(&fp.finderinfo,0,32);
	fp.finderinfo[0]='s';
	fp.finderinfo[1]='l';
	fp.finderinfo[2]='n';
	fp.finderinfo[3]='k';
	fp.finderinfo[4]='r';
	fp.finderinfo[5]='h';
	fp.finderinfo[6]='a';
	fp.finderinfo[7]='p';

	rc=afp_setfiledirparms(vol,dirid2,basename2,
		kFPFinderInfoBit, &fp);
	switch (rc) {
	case kFPAccessDenied:
		ret=EPERM;
		goto error;
	case kFPBitmapErr:
		/* This is the case where it isn't supported */
		ret=ENOSYS;
		goto error;
	case kFPObjectNotFound:
		ret=ENOENT;
		goto error;
	case 0:
		ret=0;
		break;
	case kFPMiscErr:
	case kFPObjectTypeErr:
	case kFPParamErr:
	default:
		ret=EIO;
		goto error;
	}
error:
	return -ret;
};
Esempio n. 2
0
static int set_unixprivs(struct afp_volume * vol,
	unsigned int dirid, 
	const char * basename, struct afp_file_info * fp) 

{
#define TOCHECK_BITS \
	(S_IRUSR |S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | \
	 S_IROTH | S_IWOTH | S_IXOTH )

	int ret=0, rc;
	int rc2;
	struct afp_file_info fp2;

	fp->unixprivs.ua_permissions=0;

	if (!(vol->extra_flags & VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX))
		return 0;

	if (fp->isdir) {
		rc=afp_setdirparms(vol, dirid,basename,
			kFPUnixPrivsBit, fp);
	} else {

		/* For broken netatalk servers, strip out the extra bits. */
		if ((fp->unixprivs.permissions&~(AFP_CHMOD_ALLOWED_BITS_22)) && 
		(vol->server->server_type==AFPFS_SERVER_TYPE_NETATALK) &&
		(vol->extra_flags & VOLUME_EXTRA_FLAGS_VOL_CHMOD_KNOWN) &&
		(vol->extra_flags & VOLUME_EXTRA_FLAGS_VOL_CHMOD_BROKEN))
			fp->unixprivs.permissions&=AFP_CHMOD_ALLOWED_BITS_22; 

		rc=afp_setfiledirparms(vol,dirid,basename,
			kFPUnixPrivsBit, fp);
	}

	switch (rc) {
	case kFPAccessDenied:
		ret=EPERM;
		break;
	case kFPBitmapErr:
		ret=ENOSYS;
		break;
	case kFPObjectNotFound:
		ret=ENOENT;
		break;
	case 0:
		ret=0;
		break;
	case kFPMiscErr:
	case kFPObjectTypeErr:
	case kFPParamErr:
	default:
		ret=EIO;
		break;
	}

	/* If it is netatalk, check to see if that worked.  If not, 
	*            never try this bitset again. */
	if ((fp->unixprivs.permissions & ~(AFP_CHMOD_ALLOWED_BITS_22)) &&
		(!(vol->extra_flags & VOLUME_EXTRA_FLAGS_VOL_CHMOD_KNOWN)) &&
		(vol->server->server_type==AFPFS_SERVER_TYPE_NETATALK))
	{
		if ((rc2=get_unixprivs(vol, dirid, basename, &fp2)))
			return rc2;
		vol->extra_flags|=VOLUME_EXTRA_FLAGS_VOL_CHMOD_KNOWN;

		if ((fp2.unixprivs.permissions&TOCHECK_BITS)==
			(fp->unixprivs.permissions&TOCHECK_BITS)) {
				vol->extra_flags&=~VOLUME_EXTRA_FLAGS_VOL_CHMOD_BROKEN;
		} else {
			vol->extra_flags|=VOLUME_EXTRA_FLAGS_VOL_CHMOD_BROKEN;
			return -EFAULT;
		}
	}

	return -ret;
}
Esempio n. 3
0
int appledouble_write(struct afp_volume * volume, struct afp_file_info *fp,
                const char *data, size_t size, off_t offset, size_t *totalwritten)
{
	int ret;
	int towrite=size;
	unsigned int did;
	struct afp_file_info fp2;

	switch(fp->resource) {
		case AFP_META_RESOURCE:
			ret=ll_write(volume,data,size,offset,
				fp->forkid,totalwritten);
			return ret;
		case AFP_META_APPLEDOUBLE:
			return -EBADF;
		case AFP_META_FINDERINFO:
			if (offset>=32) return -EINVAL;
			if (towrite>(32-offset)) towrite=32-offset;

			/* Get the previous finderinfo */
			ret=ll_get_directory_entry(volume,fp->basename,fp->did,
				kFPFinderInfoBit,kFPFinderInfoBit,&fp2);
			if (ret<0) return ret;

			/* Copy in only the parts we got */
			memcpy(fp->finderinfo+offset,data,towrite);

			ret=afp_setfiledirparms(volume,
					fp->did,fp->basename,
					kFPFinderInfoBit, fp);
			switch(ret) {
				case kFPNoErr:
					break;
				case kFPAccessDenied:
					return -EACCES;
				case kFPObjectNotFound:
					return -ENOENT;
				case kFPBitmapErr:
				case kFPMiscErr:
				case kFPObjectTypeErr:
				case kFPParamErr:
				default:
					break;

			}
			*totalwritten=towrite;

			return 1;
		case AFP_META_COMMENT:
			switch(afp_addcomment(volume, fp->did,fp->basename,
				(char *)data,(uint64_t *) totalwritten)) {
			case kFPAccessDenied:
				return -EACCES;
			case kFPObjectNotFound:
				return -ENOENT;
			case kFPNoErr:
                		*totalwritten=size;
				return 1;
			case kFPMiscErr:
			default:
				return -EIO;
			}
		case AFP_META_SERVER_ICON:
			return -EPERM;

	}
	return 0;


}