/* Copyright (c) 2012 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "handlers.h" #include #include #include #include #include "hello_nacl_mounts.h" #define MAX_OPEN_FILES 10 /** * A mapping from int -> FILE*, so the JavaScript messages can refer to an open * File. */ static FILE* g_OpenFiles[MAX_OPEN_FILES]; /** * Add the file to the g_OpenFiles map. * @param[in] file The file to add to g_OpenFiles. * @return int The index of the FILE in g_OpenFiles, or -1 if there are too many * open files. */ static int AddFileToMap(FILE* file) { int i; assert(file != NULL); for (i = 0; i < MAX_OPEN_FILES; ++i) { if (g_OpenFiles[i] == NULL) { g_OpenFiles[i] = file; return i; } } return -1; } /** * Remove the file from the g_OpenFiles map. * @param[in] i The index of the file handle to remove. */ static void RemoveFileFromMap(int i) { assert(i >= 0 && i < MAX_OPEN_FILES); g_OpenFiles[i] = NULL; } /** * Get a file handle from the g_OpenFiles map. * @param[in] i The index of the file handle to get. * @return the FILE*, or NULL of there is no open file with that handle. */ static FILE* GetFileFromMap(int i) { assert(i >= 0 && i < MAX_OPEN_FILES); return g_OpenFiles[i]; } /** * Get a file, given a string containing the index. * @param[in] s The string containing the file index. * @param[out] file_index The file index of this file. * @return The FILE* for this file, or NULL if the index is invalid. */ static FILE* GetFileFromIndexString(const char* s, int* file_index) { char* endptr; int result = strtol(s, &endptr, 10); if (endptr != s + strlen(s)) { /* Garbage at the end of the number...? */ return NULL; } if (file_index) *file_index = result; return GetFileFromMap(result); } /** * Handle a call to fopen() made by JavaScript. * * fopen expects 2 parameters: * 0: the path of the file to open * 1: the mode string * on success, fopen returns a result in |output| separated by \1: * 0: "fopen" * 1: the filename opened * 2: the file index * on failure, fopen returns an error string in |output|. * * @param[in] num_params The number of params in |params|. * @param[in] params An array of strings, parameters to this function. * @param[out] output A string to write informational function output to. * @return An errorcode; 0 means success, anything else is a failure. */ int HandleFopen(int num_params, char** params, char** output) { FILE* file; int file_index; const char* filename; const char* mode; if (num_params != 2) { *output = PrintfToNewString("Error: fopen takes 2 parameters."); return 1; } filename = params[0]; mode = params[1]; file = fopen(filename, mode); if (!file) { *output = PrintfToNewString("Error: fopen returned a NULL FILE*."); return 2; } file_index = AddFileToMap(file); if (file_index == -1) { *output = PrintfToNewString( "Error: Example only allows %d open file handles.", MAX_OPEN_FILES); return 3; } *output = PrintfToNewString("fopen\1%s\1%d", filename, file_index); return 0; } /** * Handle a call to fwrite() made by JavaScript. * * fwrite expects 2 parameters: * 0: The index of the file (which is mapped to a FILE*) * 1: A string to write to the file * on success, fwrite returns a result in |output| separated by \1: * 0: "fwrite" * 1: the file index * 2: the number of bytes written * on failure, fwrite returns an error string in |output|. * * @param[in] num_params The number of params in |params|. * @param[in] params An array of strings, parameters to this function. * @param[out] output A string to write informational function output to. * @return An errorcode; 0 means success, anything else is a failure. */ int HandleFwrite(int num_params, char** params, char** output) { FILE* file; const char* file_index_string; const char* data; size_t data_len; size_t bytes_written; if (num_params != 2) { *output = PrintfToNewString("Error: fwrite takes 2 parameters."); return 1; } file_index_string = params[0]; file = GetFileFromIndexString(file_index_string, NULL); data = params[1]; data_len = strlen(data); if (!file) { *output = PrintfToNewString("Error: Unknown file handle %s.", file_index_string); return 2; } bytes_written = fwrite(data, 1, data_len, file); *output = PrintfToNewString("fwrite\1%s\1%d", file_index_string, bytes_written); return 0; } /** * Handle a call to fread() made by JavaScript. * * fread expects 2 parameters: * 0: The index of the file (which is mapped to a FILE*) * 1: The number of bytes to read from the file. * on success, fread returns a result in |output| separated by \1: * 0: "fread" * 1: the file index * 2: the data read from the file * on failure, fread returns an error string in |output|. * * @param[in] num_params The number of params in |params|. * @param[in] params An array of strings, parameters to this function. * @param[out] output A string to write informational function output to. * @return An errorcode; 0 means success, anything else is a failure. */ int HandleFread(int num_params, char** params, char** output) { FILE* file; const char* file_index_string; char* buffer; size_t data_len; size_t bytes_read; if (num_params != 2) { *output = PrintfToNewString("Error: fread takes 2 parameters."); return 1; } file_index_string = params[0]; file = GetFileFromIndexString(file_index_string, NULL); data_len = strtol(params[1], NULL, 10); if (!file) { *output = PrintfToNewString("Error: Unknown file handle %s.", file_index_string); return 2; } buffer = (char*)malloc(data_len + 1); bytes_read = fread(buffer, 1, data_len, file); buffer[bytes_read] = 0; *output = PrintfToNewString("fread\1%s\1%s", file_index_string, buffer); free(buffer); return 0; } /** * Handle a call to fseek() made by JavaScript. * * fseek expects 3 parameters: * 0: The index of the file (which is mapped to a FILE*) * 1: The offset to seek to * 2: An integer representing the whence parameter of standard fseek. * whence = 0: seek from the beginning of the file * whence = 1: seek from the current file position * whence = 2: seek from the end of the file * on success, fseek returns a result in |output| separated by \1: * 0: "fseek" * 1: the file index * 2: The new file position * on failure, fseek returns an error string in |output|. * * @param[in] num_params The number of params in |params|. * @param[in] params An array of strings, parameters to this function. * @param[out] output A string to write informational function output to. * @return An errorcode; 0 means success, anything else is a failure. */ int HandleFseek(int num_params, char** params, char** output) { FILE* file; const char* file_index_string; long offset; int whence; int result; if (num_params != 3) { *output = PrintfToNewString("Error: fseek takes 3 parameters."); return 1; } file_index_string = params[0]; file = GetFileFromIndexString(file_index_string, NULL); offset = strtol(params[1], NULL, 10); whence = strtol(params[2], NULL, 10); if (!file) { *output = PrintfToNewString("Error: Unknown file handle %s.", file_index_string); return 2; } result = fseek(file, offset, whence); if (result) { *output = PrintfToNewString("Error: fseek returned error %d.", result); return 3; } offset = ftell(file); if (offset < 0) { *output = PrintfToNewString( "Error: fseek succeeded, but ftell returned error %d.", offset); return 4; } *output = PrintfToNewString("fseek\1%s\1%d", file_index_string, offset); return 0; } /** * Handle a call to fclose() made by JavaScript. * * fclose expects 1 parameter: * 0: The index of the file (which is mapped to a FILE*) * on success, fclose returns a result in |output| separated by \1: * 0: "fclose" * 1: the file index * on failure, fclose returns an error string in |output|. * * @param[in] num_params The number of params in |params|. * @param[in] params An array of strings, parameters to this function. * @param[out] output A string to write informational function output to. * @return An errorcode; 0 means success, anything else is a failure. */ int HandleFclose(int num_params, char** params, char** output) { FILE* file; int file_index; const char* file_index_string; int result; if (num_params != 1) { *output = PrintfToNewString("Error: fclose takes 1 parameters."); return 1; } file_index_string = params[0]; file = GetFileFromIndexString(file_index_string, &file_index); if (!file) { *output = PrintfToNewString("Error: Unknown file handle %s.", file_index_string); return 2; } result = fclose(file); if (result) { *output = PrintfToNewString("Error: fclose returned error %d.", result); return 3; } RemoveFileFromMap(file_index); *output = PrintfToNewString("fclose\1%s", file_index_string); return 0; }