예제 #1
0
파일: FS.c 프로젝트: BhaaLseN/sneek
s32 FS_DeleteFile( char *Path )
{
#ifdef USEATTR
	//delete attribute file
	char *AttrFile = (char*)heap_alloc_aligned( 0, 0x80, 0x40 );

	_sprintf( AttrFile, "%s.attr", Path );
	f_unlink( AttrFile );
	heap_free( 0, AttrFile );
#endif
	switch( f_unlink( Path ) )
	{
		case FR_DENIED:	//Folder is not empty and can't be removed without deleting the content first	
			return FS_Delete( Path );

		case FR_OK:
			return FS_SUCCESS;

		case FR_EXIST:
			return FS_EEXIST2;

		case FR_NO_FILE:
		case FR_NO_PATH:
			return FS_ENOENT2;
		default:
			break;
	}

	return FS_EFATAL;
}
예제 #2
0
파일: FS.c 프로젝트: BhaaLseN/sneek
s32 FS_Delete( char *Path )
{
//	dbgprintf("FS_Delete(\"%s\")\n", Path );

	char *FilePath = (char*)heap_alloc_aligned( 0, 0x80, 0x40 );

	//normal clean up
	DIR d;
	if( f_opendir( &d, Path ) == FR_OK )
	{
		FILINFO FInfo;
		
		s32 res = f_readdir( &d, &FInfo );

		if( res != FR_OK )
		{
			heap_free( 0, FilePath );
			return FS_EFATAL;
		}

		while( res == FR_OK )
		{
			memset32( FilePath, 0, 0x40 );
			strcpy( FilePath, Path );

			//insert slash
			FilePath[strlen(Path)] = '/';

			if( FInfo.lfsize )
			{
				//dbgprintf("\"%s\"\n", FInfo.lfname );
				memcpy( FilePath+strlen(Path)+1, FInfo.lfname, strlen(FInfo.lfname) );
			} else {
				//dbgprintf("\"%s\"\n", FInfo.fname );
				memcpy( FilePath+strlen(Path)+1, FInfo.fname, strlen(FInfo.fname) );
			}

			res = f_unlink( FilePath );
			if( res  != FR_OK )
			{
				//dbgprintf("\"%s\":%d\n", FilePath, res );
				if( FInfo.fattrib&AM_DIR )
				{
					FS_Delete( FilePath );
					f_unlink( FilePath );
				} else {
					heap_free( 0, FilePath );
					return FS_EFATAL;
				}
			}

			res = f_readdir( &d, &FInfo );
		}
	}

	heap_free( 0, FilePath );

	return FS_SUCCESS;
}
예제 #3
0
void *malloca( u32 size, u32 align )
{
	if(size <= 0)
	{
#ifdef DEBUG_ALLOC_ERROR
		dbgprintf("ES:WARNING malloca: req size is 0!\n");
#endif
		return NULL;
	}
	
	void *ptr = heap_alloc_aligned( 0, size, align );
	if( ptr == NULL )
	{
#ifdef DEBUG_ALLOC_ERROR
		dbgprintf("ES:malloca:%p Size:%08X Alignment:%d FAILED\n", ptr, size, align);
#endif
		while(1);
	}
	return ptr;
}
예제 #4
0
파일: NAND.c 프로젝트: BhaaLseN/sneek
u8 *NANDLoadFile( char *path, u32 *Size )
{
	s32 fd = IOS_Open( path, 1 );
	if( fd < 0 )
	{
		//dbgprintf("ES:NANDLoadFile->IOS_Open(\"%s\", 1 ):%d\n", path, fd );
		*Size = fd;
		return (u8*)NULL;
	}
	//dbgprintf("ES:NANDLoadFile->IOS_Open(\"%s\", 1 ):%d\n", path, fd );

	*Size = IOS_Seek( fd, 0, SEEK_END );
	//dbgprintf("ES:NANDLoadFile->Size:%d\n", *Size );

	IOS_Seek( fd, 0, 0 );

	u8 *data = (u8*)heap_alloc_aligned( 0, *Size, 0x40 );
	if( data == NULL )
	{
		//dbgprintf("ES:NANDLoadFile(\"%s\")->Failed to alloc %d bytes!\n", path, status->Size );
		IOS_Close( fd );
		return (u8*)NULL;
	}

	s32 r = IOS_Read( fd, data, *Size );
	//dbgprintf("ES:NANDLoadFile->IOS_Read():%d\n", r );
	if( r < 0 )
	{
		//dbgprintf("ES:NANDLoadFile->IOS_Read():%d\n", r );
		*Size = r;
		IOS_Close( fd );
		return (u8*)NULL;
	}

	IOS_Close( fd );

	return data;
}
예제 #5
0
파일: NAND.c 프로젝트: BhaaLseN/sneek
/*
	This creates the file in the TMP dir and then moves it to the destination overwriting it!
	
	To work correctly on the real nand we must have the same filename for the
	source and destination!
*/
s32 NANDWriteFileSafe( char *pathdst, void *data, u32 size )
{
	char *path = (char*)heap_alloc_aligned( 0, 0x40, 32 );
	s32 i=0;

//Extract filename

	//search backwards for slash
	for( i=strlen(pathdst); i > 0; --i )
		if( pathdst[i] == '/' )
			break;

	_sprintf( path, "/tmp%s", pathdst + i );

	s32 r = ISFS_CreateFile( path, 0, 3, 3, 3 );
	if( r == FS_EEXIST2 )
	{
		ISFS_Delete( path );
		r = ISFS_CreateFile( path, 0, 3, 3, 3 );
		if( r < 0 )
		{
			//dbgprintf("ISFS_CreateFile(%s):%d\n",path,r);
			heap_free( 0, path );
			return r;
		}
	} else {
		if( r < 0 )
		{
			//dbgprintf("ISFS_CreateFile(%s):%d\n",path,r);
			heap_free( 0, path );
			return r;
		}
	}

	s32 fd = IOS_Open( path, 2 );
	if( fd < 0 )
	{
		//dbgprintf("IOS_Open(%s):%d\n",path,r);
		heap_free( 0, path );
		return r;
	}

	r = IOS_Write( fd, data, size );
	if( r < 0 || r != size )
	{
		//dbgprintf("IOS_Write():%d\n",r);
		IOS_Close( fd );
		heap_free( 0, path );
		return r;
	}

	IOS_Close( fd );

	r = ISFS_Rename( path, pathdst );
	if( r < 0 )
	{
		//dbgprintf("ISFS_Rename(%s,%s):%d\n",path,pathdst,r);
		heap_free( 0, path );
		return r;
	}

	heap_free( 0, path );
	return r;
}
예제 #6
0
파일: test_heap.c 프로젝트: saumzy/clib
int main (int argc, char * argv[])
{
  word i, j, k, n, seed, check_mask;
  u32 * h = 0;
  uword * objects = 0;
  uword * handles = 0;
  uword objects_used;
  uword align, fixed_size;

  n = 10;
  seed = getpid ();
  check_mask = 0;
  fixed_size = 0;

  if (argc > 1)
    {
      n = atoi (argv[1]);
      verbose = 1;
    }
  if (argc > 2)
    {
      word i = atoi (argv[2]);
      if (i)
	seed = i;
    }
  if (argc > 3)
    check_mask = atoi (argv[3]);

  align = 0;
  if (argc > 4)
    align = 1 << atoi (argv[4]);

  if_verbose   ("testing %wd iterations seed %wd\n", n, seed);

  srandom (seed);

  if (verbose) fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);

  vec_resize (objects, 1000);
  memset (objects, ~0, vec_bytes (objects));
  vec_resize (handles, vec_len (objects));

  objects_used = 0;

  if (fixed_size)
    {
      uword max_len = 1024 * 1024;
      void * memory = clib_mem_alloc (max_len * sizeof (h[0]));
      h = heap_create_from_memory (memory, max_len, sizeof (h[0]));
    }

  for (i = 0; i < n; i++)
    {
      while (1)
	{
	  j = random () % vec_len (objects);
	  if (objects[j] != ~0 || i + objects_used < n)
	    break;
	}

      if (objects[j] != ~0)
	{
	  heap_dealloc (h, handles[j]);
	  objects_used--;
	  objects[j] = ~0;
	}
      else
	{
	  u32 * data;
	  uword size;

	  size = 1 + (random () % 100);
	  objects[j] = heap_alloc_aligned (h, size, align, handles[j]);
	  objects_used++;

	  if (align)
	    ASSERT (0 == (objects[j] & (align - 1)));
	  ASSERT (objects[j] < vec_len (h));
	  ASSERT (size <= heap_len (h, handles[j]));

	  /* Set newly allocated object with test data. */
	  if (check_mask & 2)
	    {
	      data = h + objects[j];

	      for (k = 0; k < size; k++)
		data[k] = objects[j] + k;
	    }
	}

      if (check_mask & 1)
	heap_validate (h);

      if (check_mask & 4)
	{
	  /* Duplicate heap at each iteration. */
	  u32 * h1 = heap_dup (h);
	  heap_free (h);
	  h = h1;
	}

      /* Verify that all used objects have correct test data. */
      if (check_mask & 2)
	{
	  for (j = 0; j < vec_len (objects); j++)
	    if (objects[j] != ~0)
	      {
		u32 * data = h + objects[j];
		for (k = 0; k < heap_len (h, handles[j]); k++)
		  ASSERT(data[k] == objects[j] + k);
	      }
	}
    }

  if (verbose) fformat (stderr, "%U\n", format_heap, h, 1);

  {
    u32 * h1 = heap_dup (h);
    if (verbose) fformat (stderr, "%U\n", format_heap, h1, 1);
    heap_free (h1);
  }

  heap_free (h);
  if (verbose) fformat (stderr, "%U\n", format_heap, h, 1);
  ASSERT (objects_used == 0);

  vec_free (objects);
  vec_free (handles);

  if (fixed_size)
    vec_free_h (h, sizeof (heap_header_t));

  if (verbose) fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);

  return 0;
}
예제 #7
0
파일: FS.c 프로젝트: BhaaLseN/sneek
s32 FS_GetUsage( char *path, u32 *FileCount, u32 *TotalSize )
{
	char *file = heap_alloc_aligned( 0, 0x40, 0x40 );

	DIR d;
	FILINFO FInfo;
	s32 res=0;

	switch( f_opendir( &d, path ) )
	{
		case FR_INVALID_NAME:
		case FR_NO_FILE:
		case FR_NO_PATH:
			return FS_ENOENT2;
		default:
			return FS_EFATAL;
		case FR_OK:
			break;
	}

	while( (res = f_readdir( &d, &FInfo )) == FR_OK )
	{
#ifdef USEATTR
		if( FInfo.lfsize )
		{
			if( strstr( FInfo.lfname, ".attr" ) != NULL )
				continue;
		} else{
			if( strstr( FInfo.fname, ".attr" ) != NULL )
				continue;
		}
#endif
		if( FInfo.fattrib & AM_DIR )
		{
			memset32( file, 0, 0x40 );
			memcpy( file, path, strlen(path) );

			//insert slash
			file[strlen(path)] = '/';

			if( FInfo.lfsize )
			{
				memcpy( file+strlen(path)+1, FInfo.lfname, strlen(FInfo.lfname) );
			} else {
				memcpy( file+strlen(path)+1, FInfo.fname, strlen(FInfo.fname) );
			}


			res = FS_GetUsage( file, FileCount, TotalSize );
			if( res != FS_SUCCESS )
			{
				heap_free( 0, file );
				return res;
			}
		} else {
			*FileCount = *FileCount + 1;
			*TotalSize = *TotalSize + FInfo.fsize;
		}
	}

	heap_free( 0, file );
	return FS_SUCCESS;
}
예제 #8
0
파일: FS.c 프로젝트: BhaaLseN/sneek
void FFS_Ioctlv(struct IPCMessage *msg)
{
	u32 InCount		= msg->ioctlv.argc_in;
	u32 OutCount	= msg->ioctlv.argc_io;
	vector *v		= (vector*)(msg->ioctlv.argv);
	s32 ret=0;

#ifdef EDEBUG
	dbgprintf("FFS:IOS_Ioctlv( %d, 0x%x 0x%x 0x%x 0x%p )\n", msg->fd, msg->ioctl.command, InCount, OutCount, msg->ioctlv.argv );
#endif

	//for( ret=0; ret<InCount+OutCount; ++ret)
	//{
	//	if( ((vu32)(v[ret].data)>>24) == 0 )
	//		dbgprintf("FFS:in:0x%08x\tout:0x%08x\n", v[ret].data, v[ret].data );
	//}

	switch(msg->ioctl.command)
	{
		case 0x60:
		{
			HAXHandle = FS_Open( (char*)(v[0].data), (u32)(v[1].data) );
#ifdef DEBUG
			dbgprintf("FS_Open(%s, %02X):%d\n", (char*)(v[0].data), (u32)(v[1].data), HAXHandle );
#endif
			ret = HAXHandle;
		} break;
		case IOCTL_READDIR:
		{
			if( InCount == 1 && OutCount == 1 )
			{
				ret = FS_ReadDir( (char*)(v[0].data), (u32*)(v[1].data), NULL );

			} else if( InCount == 2 && OutCount == 2 ) {

				char *buf = heap_alloc_aligned( 0, v[2].len, 0x40 );
				memset32( buf, 0, v[2].len );

				ret = FS_ReadDir( (char*)(v[0].data), (u32*)(v[3].data), buf );

				memcpy( (char*)(v[2].data), buf, v[2].len );

				heap_free( 0, buf );

			} else {
				ret = FS_EFATAL;
			}

#ifdef DEBUG
			dbgprintf("FFS:ReadDir(\"%s\"):%d FileCount:%d\n", (char*)(v[0].data), ret, *(u32*)(v[1].data) );
#endif
		} break;
		
		case IOCTL_GETUSAGE:
		{
			if( memcmp( (char*)(v[0].data), "/title/00010001", 16 ) == 0 )
			{
				*(u32*)(v[1].data) = 23;			// size is size/0x4000
				*(u32*)(v[2].data) = 42;			// empty folders return a FileCount of 1
			} else if( memcmp( (char*)(v[0].data), "/title/00010005", 16 ) == 0 )		// DLC
			{
				*(u32*)(v[1].data) = 23;			// size is size/0x4000
				*(u32*)(v[2].data) = 42;			// empty folders return a FileCount of 1
			} else {

				*(u32*)(v[1].data) = 0;			// size is size/0x4000
				*(u32*)(v[2].data) = 1;			// empty folders return a FileCount of 1

				ret = FS_GetUsage( (char*)(v[0].data), (u32*)(v[2].data), (u32*)(v[1].data) );

				//Size is returned in BlockCount

				*(u32*)(v[1].data) = *(u32*)(v[1].data) / 0x4000;
			}

#ifdef DEBUG
			dbgprintf("FFS:FS_GetUsage(\"%s\"):%d FileCount:%d FileSize:%d\n", (char*)(v[0].data), ret, *(u32*)(v[2].data), *(u32*)(v[1].data) );
#endif
		} break;
		default:
		{
			//dbgprintf("FFS:IOS_Ioctlv( %d, 0x%x 0x%x 0x%x 0x%p )\n", msg->fd, msg->ioctl.command, InCount, OutCount, msg->ioctlv.argv );
			ret = -1017;
		} break;
	}
#ifdef DEBUG
	//dbgprintf("FFS:IOS_Ioctlv():%d\n", ret);
#endif
	mqueue_ack( (void *)msg, ret);
}
예제 #9
0
파일: FS.c 프로젝트: BhaaLseN/sneek
void FFS_Ioctl(struct IPCMessage *msg)
{
	FIL fil;
	u8  *bufin  = (u8*)msg->ioctl.buffer_in;
	u32 lenin   = msg->ioctl.length_in;
	u8  *bufout = (u8*)msg->ioctl.buffer_io;
	u32 lenout  = msg->ioctl.length_io;
	s32 ret;

	//if( ((((vu32)bufin>>24)==0)&&lenin) || ((((vu32)bufout>>24)==0)&&lenout) )
	//{
	//	dbgprintf("FFS:in:0x%p\tout:0x%p\n", bufin, bufout );
	//}
#ifdef EDEBUG
	dbgprintf("FFS:IOS_Ioctl( %d 0x%x 0x%p 0x%x 0x%p 0x%x )\n", msg->fd, msg->ioctl.command, bufin, lenin, bufout, lenout);
#endif
	
	ret = FS_SUCCESS;

	switch(msg->ioctl.command)
	{
		case IOCTL_IS_USB:
		{
			ret = FS_SUCCESS;
		} break;
		case IOCTL_NANDSTATS:
		{
			if( lenout < 0x1C )
				ret = -1017;
			else {
				NANDStat fs;
				
				//TODO: get real stats from SD CARD?
				fs.BlockSize	= 0x4000;
				fs.FreeBlocks	= 0x5DEC;
				fs.UsedBlocks	= 0x1DD4;
				fs.unk3			= 0x10;
				fs.unk4			= 0x02F0;
				fs.Free_INodes	= 0x146B;
				fs.unk5			= 0x0394;

				memcpy( bufout, &fs, sizeof(NANDStat) );
			}

			ret = FS_SUCCESS;
#ifdef DEBUG
			dbgprintf("FFS:GetNANDStats( %d, %p ):%d\n", msg->fd, msg->ioctl.buffer_io, ret );
#endif
		} break;

		case IOCTL_CREATEDIR:
		{
			ret = FS_CreateDir( (char*)(bufin+6) );
#ifdef USEATTR
			if( ret == FS_SUCCESS )
			{
				//create attribute file
				char *path = (char*)heap_alloc_aligned( 0, 0x40, 32 );
			
				_sprintf( path, "%s.attr", (char*)(bufin+6) );

				if( f_open( &fil, path, FA_CREATE_ALWAYS | FA_WRITE ) == FR_OK )
				{
					u32 wrote;

					f_lseek( &fil, 6 );
					f_write( &fil, bufin+0x46, 4, &wrote);
					f_close( &fil );
				}

				heap_free( 0, path );
			}
#endif
#ifdef DEBUG
			dbgprintf("FFS:CreateDir(\"%s\", %02X, %02X, %02X, %02X ):%d\n", (char*)(bufin+6), *(u8*)(bufin+0x46), *(u8*)(bufin+0x47), *(u8*)(bufin+0x48), *(u8*)(bufin+0x49), ret );
#endif
		} break;

		case IOCTL_SETATTR:
		{
			if( lenin != 0x4A && lenin != 0x4C )
			{
				ret = FS_EFATAL;
			} else {
				ret = FS_SetAttr( (char*)(bufin+6) );
			}
#ifdef USEATTR
			if( ret == FS_SUCCESS )
			{
				//create attribute file
				char *path = (char*)heap_alloc_aligned( 0, 0x40, 32 );
			
				_sprintf( path, "%s.attr", (char*)(bufin+6) );

				if( f_open( &fil, (char*)path, FA_CREATE_ALWAYS | FA_WRITE ) == FR_OK )
				{
					u32 wrote;

					if( lenin == 0x4A )
						f_write( &fil, bufin, 4+2, &wrote);
					else
						f_lseek( &fil, 6 );

					f_write( &fil, bufin+0x46, 4, &wrote);
					f_close( &fil );
				}

				heap_free( 0, path );
			}
#endif
#ifdef DEBUG
			dbgprintf("FFS:SetAttr(\"%s\", %08X, %04X, %02X, %02X, %02X, %02X):%d in:%X out:%X\n", (char*)(bufin+6), *(u32*)(bufin), *(u16*)(bufin+4), *(u8*)(bufin+0x46), *(u8*)(bufin+0x47), *(u8*)(bufin+0x48), *(u8*)(bufin+0x49), ret, lenin, lenout ); 
#endif

		} break;

		case IOCTL_GETATTR:
		{
			char *s=NULL;
			
			switch( lenin )
			{
				case 0x40:
					s = (char*)(bufin);
					ret= FS_SUCCESS;
				break;
				case 0x4A:
					hexdump( bufin, lenin );
					s = (char*)(bufin+6);
					ret= FS_SUCCESS;
				break;
				default:
					hexdump( bufin, lenin );
					ret = FS_EFATAL;
				break;
			}

			if( ret != FS_EFATAL )
			{
				if( f_open( &fil, s, FA_READ ) == FR_OK )
				{
					f_close( &fil );
					ret = FS_SUCCESS;
				} else {
					DIR d;
					if( f_opendir( &d, s ) == FR_OK )
					{
						ret = FS_SUCCESS;
					} else {
						ret = FS_ENOENT2;
					}
				}
#ifdef USEATTR
				//read attribute file
				char *path = (char*)heap_alloc_aligned( 0, 0x40, 32 );
			
				_sprintf( path, "%s.attr", s );

				if( f_open( &fil, path, FA_OPEN_EXISTING | FA_READ ) == FR_OK )
				{
					u32 read;
					f_read( &fil, bufout, 4+2, &read);
					f_read( &fil, bufout+0x46, 4, &read);
					f_close( &fil );
				}
				heap_free( 0, path );
#else
				*(u32*)(bufout) = 0x0000;
				*(u16*)(bufout) = 0x1000;
				*(u8*)(bufout+0x46) = 3;
				*(u8*)(bufout+0x47) = 3;
				*(u8*)(bufout+0x48) = 3;
				*(u8*)(bufout+0x49) = 3;

#endif
			}
#ifdef DEBUG
			dbgprintf("FFS:GetAttr(\"%s\", %02X, %02X, %02X, %02X ):%d in:%X out:%X\n", s, *(u8*)(bufout+0x46), *(u8*)(bufout+0x47), *(u8*)(bufout+0x48), *(u8*)(bufout+0x49), ret, lenin, lenout );
#endif
		} break;

		case IOCTL_DELETE:
		{
			ret = FS_DeleteFile( (char*)bufin ) ;
#ifdef DEBUG
			dbgprintf("FFS:Delete(\"%s\"):%d\n", (char*)bufin, ret );
#endif
		} break;
		case IOCTL_RENAME:
		{
			ret = FS_Move( (char*)bufin, (char*)(bufin + 0x40) );
#ifdef USEATTR
			if( ret == FS_SUCCESS )
			{
				//move attribute file
				char *src = (char*)heap_alloc_aligned( 0, 0x80, 32 );
				char *dst = (char*)heap_alloc_aligned( 0, 0x80, 32 );
			
				_sprintf( src, "%s.attr", (char*)bufin );
				_sprintf( dst, "%s.attr", (char*)(bufin + 0x40) );

				ret = FS_Move( src, dst );
				//dbgprintf("FFS:Rename(\"%s\", \"%s\"):%d\n", src, dst, ret );

				heap_free( 0, src );
				heap_free( 0, dst );
			}
#endif
#ifdef DEBUG
			dbgprintf("FFS:Rename(\"%s\", \"%s\"):%d\n", (char*)bufin, (char*)(bufin + 0x40), ret );
#endif
		} break;
		case IOCTL_CREATEFILE:
		{
			ret = FS_CreateFile( (char*)(bufin+6) );
#ifdef USEATTR
			if( ret == FS_SUCCESS )
			{
				//create attribute file
				char *path = (char*)heap_alloc_aligned( 0, 0x40, 32 );
			
				_sprintf( path, "%s.attr", (char*)(bufin+6) );

				if( f_open( &fil, path, FA_CREATE_ALWAYS | FA_WRITE ) == FR_OK )
				{
					u32 wrote;

					if( lenin == 0x4A )
						f_write( &fil, bufin, 4+2, &wrote);
					else
						f_lseek( &fil, 6 );

					f_write( &fil, bufin+0x46, 4, &wrote);
					f_close( &fil );
				}

				heap_free( 0, path );
			}
#endif
#ifdef DEBUG
			//if( ret != -105 )
				dbgprintf("FFS:CreateFile(\"%s\", %02X, %02X, %02X, %02X):%d\n", (char*)(bufin+6), *(u8*)(bufin+0x46), *(u8*)(bufin+0x47), *(u8*)(bufin+0x48), *(u8*)(bufin+0x49), ret );
#endif
		} break;

		case IOCTL_GETSTATS:
		{
		
			ret = FS_GetStats( msg->fd, (FDStat*)bufout );

#ifdef DEBUG
			dbgprintf("FFS:GetStats( %d, %d, %d ):%d\n", msg->fd, ((FDStat*)bufout)->file_length, ((FDStat*)bufout)->file_length, ret );
#endif
		} break;

		case IOCTL_SHUTDOWN:
			//dbgprintf("FFS:Shutdown()\n");
			//Close all open FS handles
			//u32 i;
			//for( i=0; i < MAX_FILE; ++i)
			//{
			//	if( fd_stack[i].fs != NULL )
			//		f_close( &fd_stack[i] );
			//}
			ret = FS_SUCCESS;
		break;

		default:
#ifdef EDEBUG
			dbgprintf("FFS:Unknown IOS_Ioctl( %d 0x%x 0x%p 0x%x 0x%p 0x%x )\n", msg->fd, msg->ioctl.command, bufin, lenin, bufout, lenout);
#endif
			ret = FS_EFATAL;
		break;
	}
	
#ifdef EDEBUG
	dbgprintf("FFS:IOS_Ioctl():%d\n", ret);
#endif

	mqueue_ack( (void *)msg, ret);
}