Hello,

I have written a libtrivfs-based translator (the source code is
supplied in the attachment), however I have problems with stacking it
upon itself. I compile it using the following command:

  gcc -Wall -g -ltrivfs -lfshelp mangle.c -o mangle -DDEBUG -DMANGLE

Then I stack it upon an untranslated node foo, which is a text file
containing the text: 'Hello'. I use the following command:

  settrans -a foo mangle

If I now try to stack mangle upon foo again, using the command:

  settrans -L foo mangle

I receive the following error message:

  settrans: foo: Operation not supported

I also tried settrans -aL foo mangle (not sure if this matters), but I
obtain the same result. When I try fsysopts on the translated node foo
in the following way:

  fsysopts foo

I get a similar error:

  fsysopts: foo: Operation not supported

As you can see from mangle.c, I print a message in a log file
whenever any of libtrivfs callbacks is called. After the two
invocations of settrans, this file still contains the greeting message
only (i.e. "Log session started").

Could you please tell me what I am doing wrong?

scolobb
/*----------------------------------------------------------------------------*/
/*mangle.c*/
/*----------------------------------------------------------------------------*/
/*A simple translator which mangles the underlying file*/
/*----------------------------------------------------------------------------*/
/*Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
  Written by Sergiu Ivanov <[EMAIL PROTECTED]>.

  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 <hurd/trivfs.h>
#include <stdlib.h>
#include <error.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*--------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*/
/*---------------------------------------------------------------------------*/

Reply via email to