/*----------------------------------------------------------------------------*/ /*mangle.c*/ /*----------------------------------------------------------------------------*/ /*A simple translator which mangles the underlying file*/ /*----------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. Written by Sergiu Ivanov . This program 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 2 of the License, or * (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ #define _GNU_SOURCE 1 /*----------------------------------------------------------------------------*/ #include #include #include #include #include #include #include /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ /*--------Macros--------------------------------------------------------------*/ #ifdef DEBUG # define LOG_MSG(msg, args...) {fprintf(fDbg, msg"\n", ##args); fflush(fDbg);} #else # define LOG_MSG(msg, args...) #endif /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ /*--------Global Variables----------------------------------------------------*/ /*The type of this server*/ int trivfs_fstype = FSTYPE_MISC; /*generic trivfs server*/ /*----------------------------------------------------------------------------*/ /*The ID of the current filesystem*/ int trivfs_fsid = 0; /*----------------------------------------------------------------------------*/ /*Type of access published by the translator*/ int trivfs_allow_open = O_READ; /*----------------------------------------------------------------------------*/ /*Actually supported access modes*/ int trivfs_support_read = 1; int trivfs_support_write = 0; int trivfs_support_exec = 0; /*----------------------------------------------------------------------------*/ /*The port to the underlying node of the translator*/ mach_port_t underlying; /*----------------------------------------------------------------------------*/ #ifdef DEBUG /*The file for debug ouput*/ FILE * fDbg; #endif /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ /*--------Functions-----------------------------------------------------------*/ /*Modifies the stat information of the underlying node*/ void trivfs_modify_stat ( struct trivfs_protid * cred, io_statbuf_t * st ) { LOG_MSG("trivfs_modify_stat"); error_t err; /*Stat the underlying node and return the result*/ err = io_stat(underlying, st); }/*trivfs_modify_stat*/ /*----------------------------------------------------------------------------*/ /*Frees the resources*/ error_t trivfs_goaway ( struct trivfs_control * cntl, int flags ) { LOG_MSG("trivfs_goaway"); /*Close the debug file*/ #ifdef DEBUG fclose(fDbg); #endif /*Die peacefully*/ exit(EXIT_SUCCESS); }/*trivfs_goaway*/ /*----------------------------------------------------------------------------*/ /*Reads the specified number of bytes from the specified offset*/ kern_return_t trivfs_S_io_read ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t reply_type, data_t * data, mach_msg_type_number_t * data_len, loff_t offs, vm_size_t amount ) { LOG_MSG("trivfs_S_io_read"); /*Stop if no credentials are specified*/ if(!cred) return EOPNOTSUPP; /*Stop if this file was not opened for reading*/ if(!(cred->po->openmodes & O_READ)) return EBADF; /*If we are not actually asked to read anything*/ if(amount <= 0) { /*read nothing and stop successfully*/ *data_len = 0; return 0; } error_t err; /*Try to read the data from the underlying file into the supplied buffer*/ err = io_read(underlying, data, data_len, offs, *data_len); if(err) return err; size_t i; /*If we have to mangle*/ #ifdef MANGLE /*Go through the read buffer and shift the values in the bytes forward*/ for(i = 0; i < *data_len; ++(*data)[i++]); /*If we have to demangle*/ #elif defined(DEMANGLE) /*Go through the read buffer and shift the values in the bytes backward*/ for(i = 0; i < *data_len; --(*data)[i++]); #endif /*Return success*/ return 0; }/*trivfs_S_io_read*/ /*----------------------------------------------------------------------------*/ /*Writes the specified number of bytes at the specified offset*/ kern_return_t trivfs_S_io_write ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, data_t data, mach_msg_type_number_t datalen, loff_t offs, mach_msg_type_number_t * amount ) { LOG_MSG("trivfs_S_io_write"); /*Stop, if credentials are bad*/ if(!cred) return EOPNOTSUPP; /*Sorry, we are readonly*/ return EROFS; }/*trivfs_S_io_write*/ /*----------------------------------------------------------------------------*/ /*How much data we can offer at the moment*/ kern_return_t trivfs_S_io_readable ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, mach_msg_type_number_t * amount ) { LOG_MSG("trivfs_S_io_readable"); /*Stop, if credentials are bad*/ if(!cred) return EOPNOTSUPP; error_t err; /*Ask how much can be read from the underlying file*/ err = io_readable(underlying, amount); /*Return the result of operations*/ return err; }/*trivfs_S_io_readable*/ /*---------------------------------------------------------------------------*/ /*We are wanted truncated to the given size*/ kern_return_t trivfs_S_file_set_size ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, loff_t size ) { LOG_MSG("trivfs_S_file_set_size"); /*Stop if credentials are bad*/ if(!cred) return EOPNOTSUPP; /*Sorry, we are readonly*/ return EROFS; }/*trivfs_S_file_set_size*/ /*---------------------------------------------------------------------------*/ /*Change current read/write offset*/ kern_return_t trivfs_S_io_seek ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t reply_type, loff_t offs, int whence, loff_t * new_offs ) { LOG_MSG("trivfs_S_io_seek"); /*Stop if credentials are bad*/ if(!cred) return EOPNOTSUPP; error_t err; /*Try to seek as required*/ err = io_seek(underlying, offs, whence, new_offs); /*Return the result of performing the operations*/ return err; }/*trivfs_S_io_seek*/ /*---------------------------------------------------------------------------*/ /*Wait until the specified type of IO can done quickly*/ kern_return_t trivfs_S_io_select ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, int * type ) { LOG_MSG("trivfs_S_io_select"); /*Stop if credentials are bad*/ if(!cred) return EOPNOTSUPP; /*If not allowed operations are requested*/ if ( ((*type & SELECT_READ ) && !(cred->po->openmodes & O_READ)) ) return EBADF; /*Reset the flag for URG*/ *type &= ~SELECT_URG; /*Everything OK*/ return 0; }/*trivfs_S_io_select*/ /*---------------------------------------------------------------------------*/ /*Four functions for controlling the access modes*/ kern_return_t trivfs_S_io_get_openmodes ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, int * bits ) { LOG_MSG("trivfs_S_io_get_openmodes"); /*Stop if credentials are bad*/ if(!cred) return EOPNOTSUPP; /*We do no restriction on open modes now*/ *bits = cred->po->openmodes; return 0; }/*trivfs_S_io_get_openmodes*/ /*---------------------------------------------------------------------------*/ error_t trivfs_S_io_set_all_openmodes ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, int mode ) { LOG_MSG("trivfs_S_io_set_all_openmodes"); /*Stop, if credentials are bad*/ if(!cred) return EOPNOTSUPP; /*Nothing to do here*/ return 0; }/*trivfs_S_io_set_all_openmodes*/ /*---------------------------------------------------------------------------*/ kern_return_t trivfs_S_io_set_some_openmodes ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, int bits ) { LOG_MSG("trivfs_S_io_set_some_openmodes"); /*Stop, if credentials are bad*/ if(!cred) return EOPNOTSUPP; /*Nothing to do here*/ return 0; }/*trivfs_S_io_set_some_openmodes*/ /*---------------------------------------------------------------------------*/ kern_return_t trivfs_S_io_clear_some_openmodes ( struct trivfs_protid * cred, mach_port_t reply, mach_msg_type_name_t replytype, int bits ) { LOG_MSG("trivfs_S_io_clear_some_openmodes"); /*Stop, if credentials are bad*/ if(!cred) return EOPNOTSUPP; /*Nothing to do here*/ return 0; }/*trivfs_S_io_clear_some_openmodes*/ /*---------------------------------------------------------------------------*/ /*Entry point*/ int main ( int argc, char ** argv ) { #ifdef DEBUG fDbg = fopen("/var/log/mangle.dbg", "wt"); #endif LOG_MSG("Log session started"); error_t err; /*The information about this translator*/ struct trivfs_control * fsys; /*The bootstrap port of the translator*/ mach_port_t bootstrap; /*Obtain the bootstrap port of the translator*/ task_get_bootstrap_port(mach_task_self(), &bootstrap); /*If we don't have a bootstrap port*/ if(bootstrap == MACH_PORT_NULL) error(EXIT_FAILURE, 0, "Must be started as a translator"); /*Try to startup the translator*/ err = trivfs_startup(bootstrap, O_READ, 0, 0, 0, 0, &fsys); /*Deallocate the bootstrap port*/ mach_port_deallocate(mach_task_self(), bootstrap); /*Stop, if the translator could not be launched*/ if(err) error(EXIT_FAILURE, err, "Could not startup the translator"); /*Store a copy of the port to the underlying node*/ underlying = fsys->underlying; /*Start the single-threaded server loop*/ ports_manage_port_operations_one_thread(fsys->pi.bucket, trivfs_demuxer, 0); /*Everything OK*/ return 0; }/*main*/ /*---------------------------------------------------------------------------*/