<commit_before>/**
 * This file is part of libsamsung-ipc.
 *
 * Copyright (C) 2011-2012 KB <<EMAIL>>
 *
 * Implemented as per the Mocha AP-CP protocol analysis done by <NAME>
 *
 * libsamsung-ipc is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libsamsung-ipc is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * TODO: Optimize this file
 * 		 Implement following functions properly:
 * 		 	FmMoveFile
 * 		 	FmGetFileAttributes
 * 		 	FmFGetFileAttributes
 * 		 	FmSetFileAttributes
 * 		 	FmTruncateFile
 *			FmOpenDir
 *			FmCloseDir
 * 		 	FmReadDir
 * 		 	FmRemoveDir
 * 		 	FmGetQuotaSpaceFile
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>
#include <getopt.h>

#include <fm.h>
#include <radio.h>
#include <dirent.h>
#include <errno.h>

#define LOG_TAG "Mocha-RIL-FM"
#include <utils/Log.h>

#define MAX_OPEN_DIRS 	10

#define PATH_MAX_LEN (92)
/* Has to be used with lock held! */
char nameBuf[PATH_MAX_LEN];

DIR* dirArray[MAX_OPEN_DIRS];
uint32_t dirIndex = 0;

#if defined(DEVICE_JET)
char *mochaRoot = "/KFAT0";
#elif defined(DEVICE_WAVE)
char *mochaRoot = "/mnt/bada_user/modem";
#endif

int32_t (*fileOps[MAX_FILE_OPS])(struct fmRequest *, struct fmResponse *) =
{
	&FmOpenFile,
	&FmCloseFile,
	&FmCreateFile,
	&FmReadFile,
	&FmWriteFile,
	&FmFlushFile,
	&FmSeekFile,
	&FmTellFile,
	&FmRemoveFile,
	&FmMoveFile,
	&FmGetFileAttributes,
	&FmFGetFileAttributes,
	&FmSetFileAttributes,
	&FmTruncateFile,
	&FmOpenDir,
	&FmCloseDir,
	&FmReadDir,
	&FmCreateDir,
	&FmRemoveDir,
	&FmGetQuotaSpace
};

int32_t FmGetLastError()
{
	int32_t ret;
	switch(errno)
	{
		case EACCES:
			ret = FM_PERMISSION_ERROR;
		break;
		case ENOENT:
			ret = FM_ENTRY_NOT_FOUND_ERROR;
		break;
		case EBADF:
			ret = FM_INVALID_FILE_HANDLE;
		break;
		case EEXIST:
		case ENOTDIR:
			ret = FM_INVALID_PATH_ERROR; /* FM_ENTRY_EXIST_ERROR might be more appropiate here, though Mocha appears to use INVALID_PATH */
		break;
		default:
			DEBUG_I("%s: Not handled errtype %d", __func__, errno);
			ret = 0xDEADFACE;
		break;
	}
	return ret;
}

int32_t FmOpenFile(struct fmRequest *rx_packet, struct fmResponse *tx_packet)
{
//	DEBUG_I("Inside FmOpenFile");
	int32_t retval = 0;
	int32_t mode;
	uint32_t flags = O_RDONLY;

	mode = *(int32_t *)(rx_packet->reqBuf);
	strcpy(nameBuf, mochaRoot);
	strcat(nameBuf, (const char *)(rx_packet->reqBuf + sizeof(mode)));
	DEBUG_I("%s: fName %s, mode = 0x%x", __func__, nameBuf, mode);

	/*if (!strcmp(fName, "/KFAT0/nvm/num/87_19"))
		lastOpen = 1;
*/
	if(mode & FM_CREATE)
		flags |= O_CREAT;
	if(mode & FM_WRITE)
		flags |= O_RDWR;
	if(mode & FM_TRUNCATE)
		flags |= O_TRUNC;
	if(mode & FM_APPEND)
		flags |= O_APPEND;
#if 0
	else if(mode & FM_NOSHARE)
		flags |= O_RDWR;
	else if(mode & FM_DIRECTIO)
		flags |= O_RDWR;
	else if(mode & FM_CONCRETE_WRITE)
		flags |= O_RDWR;
	else if(mode & FM_NOUPDATE_TIME)
		flags |= O_RDWR;
#endif
	retval = open(nameBuf, flags); //0777);

	if(retval < 0)
		DEBUG_I("%s: error! %s", __func__, strerror(errno));
	else
		retval |= 0x61000; /* These flags are always present in node returned by Mocha, 
							  we'll mask them out if CP use them anyway */
	tx_packet->funcRet = retval;
	tx_packet->errorVal = (retval < 0 ? (errno == ENOENT ? 0 : FmGetLastError()) : 0);
	/* For some reason Mocha doesn't set error code if there's no specified file, just returns -1 */

	tx_packet->header->packetLen = sizeof(tx_packet->errorVal) + sizeof(tx_packet->funcRet); //0x08; //0x100;
	tx_packet->respBuf = NULL;

	DEBUG_I("Leaving FmOpenFile fd = %d", retval);
	return 0;
}

int32_t FmCloseFile(struct fmRequest *rx_packet, struct fmResponse *tx_packet)
{
//	DEBUG_I("Inside FmCloseFile");
	int32_t retval = 0;
	int32_t fd;

	fd = *(int32_t *)(rx_packet->reqBuf);

	retval = close(fd);
	
	if(retval < 0)
		DEBUG_I("%s: error! %s", __func__, strerror(errno));
	
	tx_packet->errorVal = (retval < 0 ? FmGetLastError() : 0); //0; //retval;
	tx_packet->funcRet = (retval < 0 ? 0 : 1); /* returns true on success */

	tx_packet->header->packetLen = sizeof(tx_packet->errorVal) + sizeof(tx_packet->funcRet);
	tx_packet->respBuf = NULL;

	DEBUG_I("Leaving FmCloseFile fd = %d", fd);
	return 0;
}

int32_t FmCreateFile(struct fmRequest *rx_packet, struct fmResponse *tx_packet)
{<commit_msg>Fixed FmCloseFile flags masking out, and FmCreateFile flags adding.<commit_after>/**
 * This file is part of libsamsung-ipc.
 *
 * Copyright (C) 2011-2012 KB <<EMAIL>>
 *
 * Implemented as per the Mocha AP-CP protocol analysis done by <NAME>
 *
 * libsamsung-ipc is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libsamsung-ipc is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * TODO: Optimize this file
 * 		 Implement following functions properly:
 * 		 	FmMoveFile
 * 		 	FmGetFileAttributes
 * 		 	FmFGetFileAttributes
 * 		 	FmSetFileAttributes
 * 		 	FmTruncateFile
 *			FmOpenDir
 *			FmCloseDir
 * 		 	FmReadDir
 * 		 	FmRemoveDir
 * 		 	FmGetQuotaSpaceFile
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>
#include <getopt.h>

#include <fm.h>
#include <radio.h>
#include <dirent.h>
#include <errno.h>

#define LOG_TAG "Mocha-RIL-FM"
#include <utils/Log.h>

#define MAX_OPEN_DIRS 	10

#define PATH_MAX_LEN (92)
/* Has to be used with lock held! */
char nameBuf[PATH_MAX_LEN];

DIR* dirArray[MAX_OPEN_DIRS];
uint32_t dirIndex = 0;

#if defined(DEVICE_JET)
char *mochaRoot = "/KFAT0";
#elif defined(DEVICE_WAVE)
char *mochaRoot = "/mnt/bada_user/modem";
#endif

int32_t (*fileOps[MAX_FILE_OPS])(struct fmRequest *, struct fmResponse *) =
{
	&FmOpenFile,
	&FmCloseFile,
	&FmCreateFile,
	&FmReadFile,
	&FmWriteFile,
	&FmFlushFile,
	&FmSeekFile,
	&FmTellFile,
	&FmRemoveFile,
	&FmMoveFile,
	&FmGetFileAttributes,
	&FmFGetFileAttributes,
	&FmSetFileAttributes,
	&FmTruncateFile,
	&FmOpenDir,
	&FmCloseDir,
	&FmReadDir,
	&FmCreateDir,
	&FmRemoveDir,
	&FmGetQuotaSpace
};

int32_t FmGetLastError()
{
	int32_t ret;
	switch(errno)
	{
		case EACCES:
			ret = FM_PERMISSION_ERROR;
		break;
		case ENOENT:
			ret = FM_ENTRY_NOT_FOUND_ERROR;
		break;
		case EBADF:
			ret = FM_INVALID_FILE_HANDLE;
		break;
		case EEXIST:
		case ENOTDIR:
			ret = FM_INVALID_PATH_ERROR; /* FM_ENTRY_EXIST_ERROR might be more appropiate here, though Mocha appears to use INVALID_PATH */
		break;
		default:
			DEBUG_I("%s: Not handled errtype %d", __func__, errno);
			ret = 0xDEADFACE;
		break;
	}
	return ret;
}

int32_t FmOpenFile(struct fmRequest *rx_packet, struct fmResponse *tx_packet)
{
//	DEBUG_I("Inside FmOpenFile");
	int32_t retval = 0;
	int32_t mode;
	uint32_t flags = O_RDONLY;

	mode = *(int32_t *)(rx_packet->reqBuf);
	strcpy(nameBuf, mochaRoot);
	strcat(nameBuf, (const char *)(rx_packet->reqBuf + sizeof(mode)));
	DEBUG_I("%s: fName %s, mode = 0x%x", __func__, nameBuf, mode);

	/*if (!strcmp(fName, "/KFAT0/nvm/num/87_19"))
		lastOpen = 1;
*/
	if(mode & FM_CREATE)
		flags |= O_CREAT;
	if(mode & FM_WRITE)
		flags |= O_RDWR;
	if(mode & FM_TRUNCATE)
		flags |= O_TRUNC;
	if(mode & FM_APPEND)
		flags |= O_APPEND;
#if 0
	else if(mode & FM_NOSHARE)
		flags |= O_RDWR;
	else if(mode & FM_DIRECTIO)
		flags |= O_RDWR;
	else if(mode & FM_CONCRETE_WRITE)
		flags |= O_RDWR;
	else if(mode & FM_NOUPDATE_TIME)
		flags |= O_RDWR;
#endif
	retval = open(nameBuf, flags); //0777);

	if(retval < 0)
		DEBUG_I("%s: error! %s", __func__, strerror(errno));
	else
		retval |= 0x61000; /* These flags are always present in node returned by Mocha, 
							  we'll mask them out if CP use them anyway */
	tx_packet->funcRet = retval;
	tx_packet->errorVal = (retval < 0 ? (errno == ENOENT ? 0 : FmGetLastError()) : 0);
	/* For some reason Mocha doesn't set error code if there's no specified file, just returns -1 */

	tx_packet->header->packetLen = sizeof(tx_packet->errorVal) + sizeof(tx_packet->funcRet); //0x08; //0x100;
	tx_packet->respBuf = NULL;

	DEBUG_I("Leaving FmOpenFile fd = %d", retval);
	return 0;
}

int32_t FmCloseFile(struct fmRequest *rx_packet, struct fmResponse *tx_packet)
{
//	DEBUG_I("Inside FmCloseFile");
	int32_t retval = 0;
	int32_t fd;

	fd = *(int32_t *)(rx_packet->reqBuf);
	fd &= 0xFFF;
	
	retval = close(fd);
	
	if(retval < 0)
		DEBUG_I("%s: error! %s", __func__, strerror(errno));
	else
		retval |= 0x61000; /* These flags are always present in node returned by Mocha, 
							  we'll mask them out if CP use them anyway */
	
	tx_packet->errorVal = (retval < 0 ? FmGetLastError() : 0); //0; //retval;
	tx_packet->funcRet = (retval < 0 ? 0 : 1); /* returns true on success */

	tx_packet->header->packetLen = sizeof(tx_packet->errorVal) + sizeof(tx_packet->funcRet);
	tx_packet->respBuf = NULL;

	DEBUG_I("Leaving FmCloseFile fd = %d", fd);
	return 0;
}

int32_t FmCreateFile(struct fmRequest *rx_packet, struct fmResponse *tx_packet)
{
{'fraction_non_alphanumeric': 0.12734082397003746, 'fraction_numerical': 0.01744529863985807, 'mean_word_length': 4.169128884360672, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7126463', 'n_tokens_mistral': 4242, 'n_tokens_neox': 3942, 'n_words': 1026}