示例#1
0
文件: calls.c 项目: B-Rich/idl4
IDL4_INLINE CORBA_long directory_resolve_implementation(CORBA_Object _caller, CORBA_long objID, CORBA_long size, CORBA_char *name, l4_threadid_t *dsvrID, CORBA_long *dobjID, idl4_server_environment *_env)

{
  if (!mounted) return ESUPP;
  
  int file_length = get_length(objID); // length of the file
  char *buffer;
  
  read(objID,0,file_length,&buffer);

  // parsing buffer
  ext2_dir_entry *parse;
  parse = (ext2_dir_entry*)buffer;
  int count = 0;
  char str[80];
  name [size]=0;
  while (count <file_length){
    strncpy(str,parse->name,parse->name_length&0xff);

    if(!strcmp(str,name)){
      
      *dsvrID=l4_myself();
      *dobjID=parse->inode;
      return ESUCCESS;
    }
    count += (int)parse->rec_length;
    parse=(ext2_dir_entry*)(((char*)parse)+parse->rec_length); // really fine pointers
  }

  return ENOTFOUND;
}
示例#2
0
文件: main.c 项目: B-Rich/idl4
void init_global_data(void)

{
  l4_threadid_t dummyid = L4_INVALID_ID;
  dword_t foo = L4_INV;

  // *** this is the booter task, and the auxpager will be thread 1

  booter = l4_myself();

  auxpager = booter;
  auxpager.id.thread = 1;

  // *** use ex_regs to read the ID of my pager (should be sigma0)

  sigma0 = L4_INVALID_ID;
  l4_thread_ex_regs(booter, foo, foo, &dummyid, &sigma0, &foo, &foo, &foo);
  
  // *** initialize administrative structs
  
  for (int i=0;i<MAXTASKS;i++)
    task[i].active=0;

  for (int i=0;i<MAXBLOCKS;i++)
    block[i].active=0;
}  
示例#3
0
文件: calls.c 项目: BillTheBest/idl4
IDL4_INLINE CORBA_long creator_create_implementation(CORBA_Object _caller, const CORBA_long objID, const CORBA_long list_size, const CORBA_long *interface_list, l4_threadid_t *dsvrID, CORBA_long *dobjID, idl4_server_environment *_env)

{
    int x = 0;

    if ((objID<0) || (objID>=MAXTASKS) || (!task[objID].active))
        return ESUPP;

    for (int i=0; i<list_size; i++)
        if ((interface_list[i]!=GENERIC_API) &&
                (interface_list[i]!=TASK_API))
            return ESUPP;

    while ((x<MAXTASKS) && (task[x].active))
        x++;
    if (x==MAXTASKS)
        return EFULL;

    task[x].active=1;
    task[x].root.svr=root.svr;
    task[x].root.obj=root.obj;
    task[x].memory.svr.raw=0;
    task[x].memory.obj=0;
    task[x].cmdline[0]=0;
    task[x].task_id.raw=0;
    task[x].owner=_caller;

    *dsvrID=l4_myself();
    *dobjID=x;

    return ESUCCESS;
}
示例#4
0
static inline PRUint32
WritePrefix(char *buf, PRUint32 bufLen)
{
    l4_threadid_t my_id = l4_myself();
    return PR_snprintf(buf, bufLen, "[%u.%u] %s ",
                       static_cast<unsigned>(my_id.id.task),
                       static_cast<unsigned>(my_id.id.lthread),
                       ipcLogPrefix);
}
示例#5
0
l4_threadid_t
l4vfs_basic_name_server_thread_for_volume_component(
    CORBA_Object _dice_corba_obj,
    volume_id_t volume_id,
    CORBA_Server_Environment *_dice_corba_env)
{
    if (volume_id == FERRET_L4VFS_VOLUME_ID)
    {
        return l4_myself();
    }
    return L4_INVALID_ID;
}
示例#6
0
/*
 * prevent all other threads from running
 */
void 
jthread_suspendall(void)
{
 l4_umword_t   old_eflags;
 l4_umword_t   dummy;
 l4_msgdope_t  result;
 l4_threadid_t src;
 l4_threadid_t preempter  = L4_INVALID_ID;
 l4_threadid_t pager      = L4_INVALID_ID;
 jthread_t     current    = live;
 l4thread_t    myself     = l4thread_myself();

 leaflet.gc = l4_myself();

// LOG("suspendall");
 /*
  * ex-regs all threads and save their state
  */
 while (current)
  {
    /**
     * NoHeapRealtimeThreads will not be stopped
     */
    if (current->daemon==0 &&
        #ifdef REALTIME_EXTENSION
        current->threadtype != THREADTYPE_NOHEAPREAL &&
        #endif
        !l4thread_equal(current->l4thread,myself))
    { 
      l4_thread_ex_regs(l4thread_l4_id(current->l4thread),
                        (unsigned long)_l4threads_suspendall,
                        (l4_umword_t)-1,
                        &preempter,
                        &pager,
                        &old_eflags,&current->eip,&current->esp);
    }
    current = current -> next;
  }

 /*
  * Waiting for the notification IPC of the last stopped thread
  */
 {
   l4_ipc_wait(&src, L4_IPC_SHORT_MSG, &dummy, &dummy,
                           L4_IPC_NEVER,&result);
 }while(!l4_tasknum_equal(leaflet.gc, src) ||
         L4_IPC_ERROR(result) == L4_IPC_RECANCELED ||
         L4_IPC_ERROR(result) == L4_IPC_REABORTED);

// LOG("suspendall-complete");
}
示例#7
0
/**
 * preempter thread for each Java thread
 */
static void NONRETURNING jthread_preempter(void * obj)
{
  l4_rt_preemption_t dw;
  l4_threadid_t src;
  l4_msgdope_t result;
  int error;
  l4_threadid_t self = l4_myself();

  l4thread_started(obj);

  while (1)
  {
      /* wait for request */
      error = l4_ipc_wait(&src,
                          L4_IPC_SHORT_MSG,
                          &dw.lh.low,
                          &dw.lh.high,
                          L4_IPC_NEVER,
                          &result);

      if (error == 0 && leaflet.misshandler != NULL) {
        if (l4_tasknum_equal(self, src)) {
          switch(dw.p.type){
            case L4_RT_PREEMPT_TIMESLICE:
//              LOG("TimeSlice "l4util_idfmt"/%d", l4util_idstr(src), dw.p.id);

              jthread_preemption(src, leaflet.wcetover);

              break;
            case L4_RT_PREEMPT_DEADLINE:
//              LOG("DeadLine "l4util_idfmt, l4util_idstr(src));

              jthread_preemption(src, leaflet.deadover);

              break;
            default:
              LOG("unknown preemption");
          }
        }
      }
  }
}
示例#8
0
int sysinit (cfg_opts *options)
{
    struct t_os2process *proc; // sysinit's PTDA/proc
    //l4events_ch_t event_ch = L4EVENTS_EXIT_CHANNEL;
    //l4events_nr_t event_nr = L4EVENTS_NO_NR;
    //l4events_event_t event;
    char   *env;
    APIRET rc;

    // create global environment
    create_env(&env);

    // Create the sysinit process PTDA structure (pid == ppid == 0)
    proc = PrcCreate(0,         // ppid
                     "sysinit", // pPrg
                     NULL,      // pArg
                     env);      // pEnv

    /* set task number */
    sysinit_id = l4_myself();
    proc->task = sysinit_id;

    if (!names_register("os2srv.sysinit"))
        io_log("error registering on the name server\n");

    /* Start servers */
    exec_runserver(proc->pid);

    /* Start run=/call= */
    exec_run_call(proc->pid);

    // Check PROTSHELL statement value
    if (!options->protshell || !*(options->protshell))
    {
        io_log("No PROTSHELL statement in CONFIG.SYS\n");
        rc = ERROR_INVALID_PARAMETER; /*ERROR_INVALID_PARAMETER 87; Not defined for Windows*/
    } else {
        exec_protshell(options);
        rc = 0; /* NO_ERROR */
    }

    io_log("sem wait\n");

    if (!rc) // wait until child process (protshell) terminates (this will unblock us)
        l4semaphore_down(&proc->term_sem);

    io_log("done waiting\n");

    /* if (use_events) // use events server
    {
      // terminate by sending an exit event
      event.len = sizeof(l4_threadid_t);
      *(l4_threadid_t*)event.str = l4_myself();
      // send exit event
      l4events_send(event_ch, &event, &event_nr, L4EVENTS_SEND_ACK);
      // get acknowledge
      l4events_get_ack(&event_nr, L4_IPC_NEVER);
    } */

    io_log("event notification sent\n");

    // unregister at names
    if (!names_unregister_task(sysinit_id))
        io_log("Cannot unregister at name server!\n");

    // destroy proc/PTDA
    PrcDestroy(proc);

    // destroy global environment
    destroy_env(env);

    io_log("OS/2 Server ended\n");
    // terminate OS/2 Server
    exit(rc);

    return rc;
}
示例#9
0
文件: main.c 项目: ErisBlastar/osfree
void main (int argc, char *argv[])
{
  CORBA_Server_Environment env = dice_default_server_environment;
  l4dm_dataspace_t ds;
  l4_threadid_t pager;
  l4_addr_t addr;
  l4_size_t size;
  int  rc, t;
  int  is_int = 0;
  int  value_int = 0;
  char buf[0x1000];
  char *p = buf;
  int optionid;
  int opt = 0;
  const struct option long_options[] =
                {
                { "events",      no_argument, NULL, 'e'},
		{ 0, 0, 0, 0}
                };

  //init_globals();

  if (!names_register("os2exec"))
    {
      LOG("Error registering on the name server!");
      return;
    }

  if (!names_waitfor_name("os2srv", &os2srv, 30000))
    {
      LOG("os2srv not found on name server!");
      return;
    }

  if (!names_waitfor_name("os2fs", &fs, 30000))
    {
      LOG("os2fs not found on name server!");
      return;
    }
  LOG("os2fs tid:%x.%x", fs.id.task, fs.id.lthread);

  if (!names_waitfor_name("LOADER", &loader, 30000))
    {
      LOG("LOADER not found on name server!");
      return;
    }

  execsrv = l4_myself();

  // Parse command line arguments
  for (;;)
  {
    opt = getopt_long(argc, argv, "e", long_options, &optionid);
    if (opt == -1) break;
    switch (opt)
    {
      case 'e':
        LOG("using events server");
	use_events = 1;
	break;
      
      default:
        LOG("Error: Unknown option %c", opt);
        usage();
        return;
    }
  }

  // start events thread
  if (use_events)
  {
    // start events thread
    l4thread_create(event_thread, 0, L4THREAD_CREATE_ASYNC);
    LOG("event thread started");
  }

  /* reserve the area below 64 Mb for application private code
     (not for use by libraries, loaded by execsrv) */
  addr = 0x2f000; size = 0x04000000 - addr;
  if ((rc  = l4rm_direct_area_setup_region(addr,
					   size,
					   L4RM_DEFAULT_REGION_AREA,
					   L4RM_REGION_BLOCKED, 0,
					   L4_INVALID_ID)) < 0)
    {
      LOG_printf("main(): setup region %x-%x failed (%d)!\n",
	  addr, addr + size, rc);
      l4rm_show_region_list();
      enter_kdebug("PANIC");
    }
  memset (&options, 0, sizeof(options));

#if 0
  if (!CfgGetopt("debugmodmgr", &is_int, &value_int, (char **)&p))
    if (is_int)
      options.debugmodmgr = value_int;

  if (!CfgGetopt("debugixfmgr", &is_int, &value_int, (char **)&p))
    if (is_int)
      options.debugixfmgr = value_int;

  if (!CfgGetopt("libpath", &is_int, &value_int, (char **)&p))
    if (!is_int)
    {
      options.libpath = (char *)malloc(strlen(p) + 1);
      strcpy(options.libpath, p);
    }

  LOG("debugmodmgr=%d", options.debugmodmgr);
  LOG("debugixfmgr=%d", options.debugixfmgr);
  LOG("libpath=%s", options.libpath);
#endif
  options.libpath = (char *)malloc(4);
  strcpy(options.libpath, "c:\\");

  /* get our l4env infopage as a dataspace */
  rc = l4loader_app_info_call(&loader, l4_myself().id.task,
                              0, &p, &ds, &env);
  /* attach it */  
  attach_ds(&ds, L4DM_RO, &infopage);

#if 0
  /* load shared libs */
  rc = loadso();
  if (rc)
  {
    LOG("Error loading shared libraries");
    return;
  }
#endif

  init_memmgr(&root_area);

  /* load IXF's */
  rc = load_ixfs();
  if (rc)
  {
    LOG("Error loading IXF driver");
    return;
  }
			      
  /* Initializes the module list. Keeps info about which dlls an process have loaded and
     has linked to it (Only support for LX dlls so far). The head of the linked list is
     declared as a global inside dynlink.c */
  rc = ModInitialize();
  if (rc)
  {
    LOG("Can't initialize module manager");
    return;
  }

  // server loop
  LOG("execsrv started.");
  env.malloc = (dice_malloc_func)malloc;
  env.free = (dice_free_func)free;
  os2exec_server_loop(&env);
}
示例#10
0
void
__pthread_thread_halt (struct __pthread *thread, int need_dealloc)
{
  /* We may deallocate THREAD.  First save any data we need.  */

  addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE];
  memcpy (exception_area, thread->exception_area,
	  sizeof (thread->exception_area));
  memset (thread->exception_area, 0, sizeof (thread->exception_area));

  void *va = thread->exception_area_va;

  addr_t object = thread->object;
  l4_thread_id_t tid = thread->threadid;

  if (need_dealloc)
    __pthread_dealloc (thread);

  /* The THREAD data structure is no longer valid.  */
  thread = NULL;

  /* Deallocate any saved object.  */
  ss_mutex_lock (&saved_object_lock);
  if (! ADDR_IS_VOID (saved_object))
    {
      storage_free (saved_object, false);
      saved_object = ADDR_VOID;
    }
  ss_mutex_unlock (&saved_object_lock);

  /* Free the exception area.  */

  /* Clean up the exception page.  */
  exception_page_cleanup
    (ADDR_TO_PTR (addr_extend (exception_area[EXCEPTION_PAGE],
			       0, PAGESIZE_LOG2)));

  /* Free the storage.  */
  int i;
  for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++)
    {
      assert (! ADDR_IS_VOID (exception_area[i]));
      storage_free (exception_area[i], false);
    }

  /* And the address space.  */
  as_free (addr_chop (PTR_TO_ADDR (va), EXCEPTION_AREA_SIZE_LOG2), false);

  if (tid == l4_myself ())
    /* If we try to storage_free (storage.addr), we will freeze in the
       middle.  That's no good.  We set SAVED_OBJECT to our thread
       object and the next thread in will free us.  */
    {
      ss_mutex_lock (&saved_object_lock);
      saved_object = object;
      ss_mutex_unlock (&saved_object_lock);
    }
  else
    storage_free (object, false);

  if (tid == l4_myself ())
    {
      l4_send_timeout (l4_myself (), L4_NEVER);
      panic ("Failed to stop thread %x.%x!",
	     l4_thread_no (l4_myself ()), l4_version (l4_myself ()));
    }
  else
    thread_stop (object);
}
示例#11
0
文件: main.c 项目: ErisBlastar/osfree
int main(int argc, char **argv)
{
  CORBA_Environment env = dice_default_environment;
  int optionid;
  int opt = 0;
  const struct option long_options[] =
                {
                { "events",      no_argument, NULL, 'e'},
		{ 0, 0, 0, 0}
                };
  //int  rc;

  init_globals();
  //FSR_INIT();

  if (!names_register("os2fs"))
  {
    LOG("Can't register on the name server!");
    return 1;
  }
  LOG("registered at the name server");

  if (!names_waitfor_name("os2srv", &os2srv, 30000))
  {
    LOG("Can't find os2srv on names, exiting...");
    return 1;
  }
  LOG("got os2srv tid from the name server");

  LOG("argc=%d", argc);
  // Parse command line arguments
  for (;;)
  {
    opt = getopt_long(argc, argv, "e", long_options, &optionid);
    LOG("opt=%d", opt);
    if (opt == -1) break;
    switch (opt)
    {
      case 'e':
        LOG("using events server");
	use_events = 1;
	break;
      
      default:
        LOG("Error: Unknown option %c", opt);
        usage();
        break;
    }
  }

  // start events thread
  if (use_events)
  {
    // start events thread
    l4thread_create((void *)event_thread, 0, L4THREAD_CREATE_ASYNC);
    LOG("event thread started");
  }

  // my id
  fs = l4_myself();

  // server loop
  LOG("going to the server loop");
  env.malloc = (dice_malloc_func)malloc;
  env.free = (dice_free_func)free;
  os2fs_server_loop(&env);

  return 0;
}
示例#12
0
文件: main.c 项目: B-Rich/idl4
int main(l4_threadid_t tasksvr, int taskobj)

{
  CORBA_Environment env = idl4_default_environment;
  l4_threadid_t rootsvr, memsvr;
  int rootobj, memobj;
  int x,y,z;
  unsigned int dummyint;
  l4_threadid_t mypagerid, dummyid, t;
  char *buf;

  myid = l4_myself();
  
  printf("Test client started (%X), ",myid.raw);

  dummyid = mypagerid = L4_INVALID_ID;dummyint=0xFFFFFFFF;
  l4_thread_ex_regs(myid, 0xffffffff, 0xffffffff, &dummyid, &mypagerid,
		    &dummyint, &dummyint, &dummyint);

  printf("pager is %X\n\n",mypagerid.raw);

  dummyid = mypagerid = L4_INVALID_ID;
  l4_thread_ex_regs(myid, 0xffffffff, 0xffffffff, &dummyid, &mypagerid,
		    &dummyint, &dummyint, &dummyint);

  printf("========================== chacmOS tester V1.00 ==========================\n");
  printf(" T01 task object is <%Xh,%d>\n",tasksvr.raw,taskobj);
  if (generic_implements(tasksvr,taskobj,sizeof(api_task)/sizeof(int),(sdword*)&api_task,&env)!=ESUCCESS)
    fail("task server does not implement generic or task api");
  
  if (task_get_root(tasksvr,taskobj,&rootsvr,&rootobj,&env)!=ESUCCESS)
    fail("cannot get root from task server");
  printf(" T02 root is <%Xh,%d>\n",rootsvr.raw,rootobj);
  if (generic_implements(rootsvr,rootobj,sizeof(api_directory)/sizeof(int),(sdword*)&api_directory,&env)!=ESUCCESS)
    fail("root does not implement generic or file or directory api");
    
  if (task_get_memory(tasksvr,taskobj,&memsvr,&memobj,&env)!=ESUCCESS)
    fail("cannot get memory object from task server");
  printf(" T03 this task's memory object is <%Xh,%d>\n",memsvr.raw,memobj);
  if (generic_implements(memsvr,memobj,sizeof(api_memory)/sizeof(int),(sdword*)&api_memory,&env)!=ESUCCESS)
    fail("memory server does not implement generic or memory api");
  if (memory_get_pagerid(memsvr,memobj,&x,&env)!=ESUCCESS)
    fail("memory server won't tell me my pager id");
  if (x!=(int)mypagerid.raw)
    fail("my pager id does not match the memory server");

  if (task_get_cmdline(tasksvr,taskobj,&x,&buf,&env)!=ESUCCESS)
    fail("cannot read my command line");
  printf(" T04 my command line is '%s'\n",buf);
  CORBA_free(buf);
  
  if (task_get_threadid(tasksvr,taskobj,&t,&env)!=ESUCCESS)
    fail("task server won't tell me my thread id");
  if (t != myid)
    fail("task server lied about my thread id");

  if (file_open(rootsvr,rootobj,0,&env)!=ESUCCESS)
    fail("cannot open root directory");
  if (file_tell(rootsvr,rootobj,&x,&env)!=ESUCCESS)  
    fail("cannot get file pointer position");
  if (x!=0)
    fail("file pointer is not reset upon open");
  if (file_seek(rootsvr,rootobj,-1,&env)!=ESUCCESS)
    fail("cannot set file pointer to end of file");  
  if (file_tell(rootsvr,rootobj,&x,&env)!=ESUCCESS)  
    fail("cannot get file pointer position (second time)");
  if (file_seek(rootsvr,rootobj,0,&env)!=ESUCCESS)
    fail("cannot set file pointer to beginning of file");  
  printf(" N01 root directory has %d bytes\n",x);
  
  if (x>79) x=79;
  y=file_read(rootsvr,rootobj,x,&z,&buf,&env);
  if (y<=0)
    {
      printf("err code %d\n",y);
      fail("cannot read root directory");
    }  
  if (z!=y)
    fail("return value of open() and data length don't match");
  if (z!=x)
    fail("cannot read all of root directory");
  buf[z]=0;  
  printf(" N02 files contained: (");
  x=0;
  while (z>0) 
    { 
      printf("'%s'",&buf[x]);
      while (buf[x++]) z--;
    }
  printf(")\n");
  if (file_close(rootsvr,rootobj,&env)!=ESUCCESS)
    fail("cannot close root directory\n");
    
  CORBA_free(buf);

  printf("\n");
  
  #ifdef TEST_FILESVR

  handle_t fatfs, dev, hda;

  if (directory_resolve(rootsvr,rootobj,3,"dev",&dev.svr,&dev.obj,&env)!=ESUCCESS)
    fail("cannot find /dev");
  if (generic_implements(dev.svr,dev.obj,sizeof(api_directory)/sizeof(int),(sdword*)&api_directory,&env)!=ESUCCESS)
    fail("/dev does not implement directory or file or generic api");
  if (directory_resolve(dev.svr,dev.obj,3,"hda",&hda.svr,&hda.obj,&env)!=ESUCCESS)
    fail("cannot find /dev/hda");
  if (generic_implements(hda.svr,hda.obj,sizeof(api_block)/sizeof(int),(sdword*)&api_block,&env)!=ESUCCESS)
    fail("/dev/hda does not implement block or generic api");
  printf(" F01 found /dev/hda at <%X,%d>\n",hda.svr.raw,hda.obj);

  if (directory_resolve(dev.svr,dev.obj,5,"fatfs",&fatfs.svr,&fatfs.obj,&env)!=ESUCCESS)
    fail("cannot find /dev/fatfs");
  if (generic_implements(fatfs.svr,fatfs.obj,sizeof(api_filesys)/sizeof(int),(sdword*)&api_filesys,&env)!=ESUCCESS)
    fail("/dev/fatfs does not implement filesystem or generic api");
  printf(" F02 located /dev/fatfs at <%X,%d>\n",hda.svr.raw,hda.obj);

  if (filesystem_mount(fatfs.svr,fatfs.obj,&hda.svr,hda.obj,&env)!=ESUCCESS)
    fail("cannot mount /dev/hda into /dev/fatfs");
  printf(" F03 mounted filesystem\n");

  x=79;
  y=file_read(fatfs.svr,fatfs.obj,x,&z,&buf,&env);
  if (y<=0)
    fail("cannot read root directory of /dev/fatfs");
  if (z>79) z=79;  
  buf[z]=0;  
  printf(" N02 files contained: (");
  x=0;
  while (z>0) 
    { 
      printf("'%s'",&buf[x]);
      while (buf[x++]) z--;
    }
  printf(")\n");
  if (file_close(fatfs.svr,fatfs.obj,&env)!=ESUCCESS)
    fail("cannot close root directory of /dev/fatfs\n");

  CORBA_free(buf);

  printf("\n");
 
  #endif /*TEST_FILESVR*/

  #ifdef TEST_BLOCKDEVICE
  
  int capacity, blksize, size;

  if (directory_resolve(rootsvr,rootobj,3,"dev",&dev.svr,&dev.obj,&env)!=ESUCCESS)
    fail("cannot find /dev");
  if (generic_implements(dev.svr,dev.obj,sizeof(api_directory)/sizeof(int),(sdword*)&api_directory,&env)!=ESUCCESS)
    fail("/dev does not implement directory or file or generic api");
  if (directory_resolve(dev.svr,dev.obj,3,"hda",&hda.svr,&hda.obj,&env)!=ESUCCESS)
    fail("cannot find /dev/hda");
  if (generic_implements(hda.svr,hda.obj,sizeof(api_block)/sizeof(int),(sdword*)&api_block,&env)!=ESUCCESS)
    fail("/dev/hda does not implement block or generic api");
  printf(" B01 found /dev/hda at <%X,%d>\n",hda.svr.raw,hda.obj);
  
  if (block_get_capacity(hda.svr,hda.obj,&capacity,&env)!=ESUCCESS)
    fail("/dev/hda won't tell me its capacity");
  if (block_get_blocksize(hda.svr,hda.obj,&blksize,&env)!=ESUCCESS)
    fail("/dev/hda won't tell me its block size");
  printf(" B02 device reports %d blocks of %d bytes each (%dk)\n",capacity,blksize,(capacity*blksize)/1024);

  if (block_read(hda.svr,hda.obj,1,1,&size,&buf,&env)!=ESUCCESS)
    fail("cannot read block 1 of /dev/hda");
  buf[10]=0;  
  printf(" B03 block 1 reads '%s'\n",buf);
  
  strcpy((char*)&buf[3],"Variatio delectat");
  if (block_write(hda.svr,hda.obj,1,1,21,buf,&env)!=ESUCCESS)
    fail("cannot write block 1 of /dev/hda");
  CORBA_free(buf);
  
  if (block_read(hda.svr,hda.obj,1,1,&size,&buf,&env)!=ESUCCESS)
    fail("cannot reread block 1 of /dev/hda");
  buf[10]=0;  
  printf(" B04 after write, it is '%s'\n",buf);
  CORBA_free(buf);

  #endif /*TEST_BLOCKDEVICE*/

  printf(" X01 test completed successfully\n");

  while (42);  
}