예제 #1
0
/*---------------------------------Main Routine----------------------------*/
int
main(void)
{
  /* GCC depends on register r1 set to 0 (?) */
  asm volatile ("clr r1");
  
  /* Initialize in a subroutine to maximize stack space */
  initialize();

#if DEBUG
{struct process *p;
 for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) {
  PRINTA("Process=%p Thread=%p  Name=\"%s\" \n",p,p->thread,PROCESS_NAME_STRING(p));
 }
}
#endif

  while(1) {
    process_run();

    watchdog_periodic();

  }
  return 0;
}
예제 #2
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(processes(struct httpd_state *s, char *ptr))
{
    PSOCK_BEGIN(&s->sout);
    for(s->u.ptr = PROCESS_LIST(); s->u.ptr != NULL; s->u.ptr = ((struct process *)s->u.ptr)->next) {
        PSOCK_GENERATOR_SEND(&s->sout, make_processes, s->u.ptr);
    }
    PSOCK_END(&s->sout);
}
예제 #3
0
파일: shell-ps.c 프로젝트: AWRyder/contiki
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_ps_process, ev, data)
{
  struct process *p;
  PROCESS_BEGIN();

  shell_output_str(&ps_command, "Processes:", "");
  for(p = PROCESS_LIST(); p != NULL; p = p->next) {
    char namebuf[30];
    strncpy(namebuf, PROCESS_NAME_STRING(p), sizeof(namebuf));
    shell_output_str(&ps_command, namebuf, "");
  }

  PROCESS_END();
}
/*---------------------------------Main Routine----------------------------*/
int
main(void)
{
  /* GCC depends on register r1 set to 0 (?) */
  asm volatile ("clr r1");
  
  /* Initialize in a subroutine to maximize stack space */
  initialize();
#if DEBUG
{struct process *p;
 for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) {
  printf_P(PSTR("Process=%p Thread=%p  Name=\"%s\" \n"),p,p->thread,p->name);
 }
}
#endif
  while(1) {
    process_run();

    watchdog_periodic();

/* Print rssi of all received packets, useful for range testing */
#ifdef RF230_MIN_RX_POWER
    uint8_t lastprint;
    if (rf230_last_rssi != lastprint) {        //can be set in halbb.c interrupt routine
        printf_P(PSTR("%u "),rf230_last_rssi);
        lastprint=rf230_last_rssi;
    }
#endif

#if TESTRTIMER
    if (rtimerflag) {  //8 seconds is maximum interval, my jackdaw 4% slow
      rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
      rtimerflag=0;
#if STAMPS
      if ((rtime%STAMPS)==0) {
        printf("%us ",rtime);
      }
#endif
      rtime+=1;
#if PINGS
      if ((rtime%PINGS)==0) {
        PRINTF("**Ping\n");
        pingsomebody();
      }
#endif
    }
#endif /* TESTRTIMER */

/* Use with rf230bb.c DEBUGFLOW to show the sequence of driver calls from the uip stack */
#if RF230BB&&0
extern uint8_t debugflowsize,debugflow[];
  if (debugflowsize) {
    debugflow[debugflowsize]=0;
    printf("%s",debugflow);
    debugflowsize=0;
   }
#endif

/* Use for low level interrupt debugging */
#if RF230BB&&0
extern uint8_t rf230interruptflag;   //in halbb.c
extern uint8_t rf230processflag;     //in rf230bb.c
  if (rf230processflag) {
    printf("**RF230 process flag %u\n\r",rf230processflag);
    rf230processflag=0;
  }
  if (rf230interruptflag) {
//  if (rf230interruptflag!=11) {
      printf("**RF230 Interrupt %u\n\r",rf230interruptflag);
 // }
    rf230interruptflag=0;
  }
#endif
  }

  return 0;
}
예제 #5
0
/*---------------------------------Main Routine----------------------------*/
int
main(void)
{
  /* GCC depends on register r1 set to 0 (?) */
  asm volatile ("clr r1");
  
  /* Initialize in a subroutine to maximize stack space */
  initialize();

#if DEBUG
{struct process *p;
 for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) {
  PRINTA("Process=%p Thread=%p  Name=\"%s\" \n",p,p->thread,PROCESS_NAME_STRING(p));
 }
}
#endif

  while(1) {
    process_run();

    watchdog_periodic();

/* Print rssi of all received packets, useful for range testing */
#ifdef RF230_MIN_RX_POWER
    uint8_t lastprint;
    if (rf230_last_rssi != lastprint) {        //can be set in halbb.c interrupt routine
        PRINTA("%u ",rf230_last_rssi);
        lastprint=rf230_last_rssi;
    }
#endif

#if 0
/* Clock.c can trigger a periodic PLL calibration in the RF230BB driver.
 * This can show when that happens.
 */
    extern uint8_t rf230_calibrated;
    if (rf230_calibrated) {
      PRINTA("\nRF230 calibrated!\n");
      rf230_calibrated=0;
    }
#endif

#if TESTRTIMER
/* Timeout can be increased up to 8 seconds maximum.
 * A one second cycle is convenient for triggering the various debug printouts.
 * The triggers are staggered to avoid printing everything at once.
 * My Jackdaw is 4% slow.
 */
    if (rtimerflag) {
      rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
      rtimerflag=0;

#if STAMPS
if ((rtime%STAMPS)==0) {
  PRINTA("%us ",rtime);
  if (rtime%STAMPS*10) PRINTA("\n");
}
#endif
      rtime+=1;

#if PINGS && UIP_CONF_IPV6_RPL
extern void raven_ping6(void);
if ((rtime%PINGS)==1) {
  PRINTA("**Ping\n");
  raven_ping6();
}
#endif

#if ROUTES && UIP_CONF_IPV6_RPL
if ((rtime%ROUTES)==2) {

extern uip_ds6_netif_t uip_ds6_if;

  uint8_t i,j;
  uip_ds6_nbr_t *nbr;

  PRINTA("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB);
  for (i=0;i<UIP_DS6_ADDR_NB;i++) {
    if (uip_ds6_if.addr_list[i].isused) {
      uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr);
      PRINTA("\n");
    }
  }
  PRINTA("\nNeighbors [%u max]\n",NBR_TABLE_MAX_NEIGHBORS);

  for(nbr = nbr_table_head(ds6_neighbors);
      nbr != NULL;
      nbr = nbr_table_next(ds6_neighbors, nbr)) {
    uip_debug_ipaddr_print(&nbr->ipaddr);
    PRINTA("\n");
    j=0;
  }
  if (j) PRINTA("  <none>");
  PRINTA("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB);
  uip_ds6_route_t *r;
  for(r = uip_ds6_route_head();
      r != NULL;
      r = uip_ds6_route_next(r)) {
    if(r->isused) {
      uip_debug_ipaddr_print(&r->ipaddr);
      PRINTA("/%u (via ", r->length);
      uip_debug_ipaddr_print(uip_ds6_route_nexthop(r));
 //     if(r->state.lifetime < 600) {
        PRINTA(") %lus\n", r->state.lifetime);
 //     } else {
 //       PRINTA(")\n");
 //     }
      j=0;
    }
  }
  if (j) PRINTA("  <none>");
  PRINTA("\n---------\n");
}
#endif

#if STACKMONITOR && CONFIG_STACK_MONITOR
if ((rtime%STACKMONITOR)==3) {
  extern uint16_t __bss_end;
  uint16_t p=(uint16_t)&__bss_end;
  do {
    if (*(uint16_t *)p != 0x4242) {
      PRINTA("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end);
      break;
    }
    p+=100;
  } while (p<RAMEND-10);
}
#endif

    }
#endif /* TESTRTIMER */

//Use with RF230BB DEBUGFLOW to show path through driver
#if RF230BB&&0
extern uint8_t debugflowsize,debugflow[];  //in rf230bb.c
  if (debugflowsize) {
    debugflow[debugflowsize]=0;
    PRINTA("%s",debugflow);
    debugflowsize=0;
   }
#endif

  }
  return 0;
}
예제 #6
0
/* Return 0 means success */
int
ast_syntax_parse(ast_node_t root, int tail)
{
	/* parse only unparsed list */
	if (root->header.type != AST_GENERAL)
		return 0;

	if (root->general.head == NULL) // ()
	{
		root->header.type = AST_SYMBOL;
		root->symbol.type = SYMBOL_NULL;
		
		return 0;
	}

	ast_node_t h = root->general.head;

	int succ = 1;
	/* The head symbol */
	xstring_t s = NULL;
	if (h->header.type == AST_SYMBOL && h->symbol.type == SYMBOL_GENERAL)
		s = h->symbol.str;

#define PROCESS_LIST(HEAD, TAIL, TAILFLAG)								\
	do																	\
	{																	\
		ast_node_t __cur = (HEAD);										\
		int __tail = 0;													\
		while (!__tail)													\
		{																\
			__tail = __cur->header.next == (TAIL);						\
			if (ast_syntax_parse(__cur,									\
								 (TAILFLAG) && __tail) != 0) succ = 0;	\
			__cur = __cur->header.next;									\
		}																\
	} while (0)

	/* Process LAMBDA */
	if (s != NULL && xstring_equal_cstr(s, TOKEN_LAMBDA, -1))
	{
		ast_node_t args_list = h->header.next;
		ast_node_t body_head = args_list->header.next;
		int args_count;
		
		if (args_list == h || body_head == h)
		{
			ERROR("BAD SYNTAX FOR LAMBDA\n");
			succ = 0;
		}
		else if (args_list->header.type != AST_GENERAL)
		{
			ERROR("BAD ARGS POSITION\n");
			succ = 0;
		}
		else
		{
			ast_node_t a_now = args_list->general.head;
			args_count = 0;
			
			while (a_now != NULL)
			{
				++ args_count;
				
				if (a_now->header.type != AST_SYMBOL ||
					a_now->symbol.type != SYMBOL_GENERAL)
				{
					ERROR("ARG MUST BE SYMBOL\n");
					succ = 0;
					break;
				}
				
				a_now = a_now->header.next;
				if (a_now == args_list->general.head) break;
			}

			if (succ && args_count > 0)
			{
				a_now = args_list->general.head->header.prev;
				if (xstring_equal_cstr(a_now->symbol.str, "...", -1))
				{
					args_count = -args_count + 1;
					if (args_count == 0)
					{
						ERROR("INVALID ARG LIST FORMAT\n");
						succ = 0;
					}
				}
			}
		}

		if (succ)
			PROCESS_LIST(body_head, h, 1);

		ast_node_t proc;
		xstring_t *args;
		
		if (succ)
			succ = !!(proc = (ast_node_t)SEE_MALLOC(sizeof(struct ast_node_s)));

		if (succ)
		{
			if (!(succ = !!(args = (xstring_t *)SEE_MALLOC(
								sizeof(xstring_t) *
								(args_count > 0 ? args_count : -args_count)))))
				SEE_FREE(proc);
		}

		if (succ)
		{
			root->header.type = AST_LAMBDA;

			if (args_count > 0)
			{
				root->lambda.tail_list = 0;
				root->lambda.argc = args_count;
			}
			else
			{
				root->lambda.tail_list = 1;
				root->lambda.argc = -args_count;
			}
			
			root->lambda.args = args;

			ast_node_t a_now = args_list->general.head;
			int i;
			for (i = 0; i != root->lambda.argc; ++ i)
			{
				root->lambda.args[i] = a_now->symbol.str;
				ast_node_t last = a_now;
				a_now = a_now->header.next;
				SEE_FREE(last);
			}
			if (a_now != args_list->general.head)
			{
				// Free the "..."
				xstring_free(a_now->symbol.str);
				SEE_FREE(a_now);
			}

			root->lambda.proc = proc;
			proc->header.type = AST_PROC;
			proc->header.prev = proc->header.next = proc;
			proc->header.priv = NULL;
			proc->proc.toplevel = 0;
			proc->proc.head = body_head;
			
			body_head->header.prev = h->header.prev;
			body_head->header.prev->header.next = body_head;

			SEE_FREE(args_list);
			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else if (s != NULL && xstring_equal_cstr(s, TOKEN_WITH, -1))
	{
		ast_node_t vars_list = h->header.next;
		ast_node_t body_head = vars_list->header.next;
		int vars_count;
		
		if (vars_list == h || body_head == h)
		{
			ERROR("BAD SYNTAX FOR WITH\n");
			succ = 0;
		}
		else if (vars_list->header.type != AST_GENERAL)
		{
			ERROR("BAD VARS POSITION\n");
			succ = 0;
		}
		else
		{
			ast_node_t v_now  = vars_list->general.head;
			
			if (v_now == NULL)
			{
				ERROR("BAD VARS LIST\n");
				succ = 0;
			}
			else
			{
				vars_count = 0;
				
				while (v_now != NULL)
				{
					++ vars_count;
					
					if (v_now->header.type != AST_SYMBOL ||
						v_now->symbol.type != SYMBOL_GENERAL)
					{
						ERROR("VAR MUST BE SYMBOL\n");
						succ = 0;
						break;
					}
					
					v_now = v_now->header.next;
					if (v_now == vars_list->general.head) v_now = NULL;
				}
			}
		}

		if (succ)
			PROCESS_LIST(body_head, h, tail);

		xstring_t *vars;
		ast_node_t proc;

		if (succ)
			succ = !!(proc = (ast_node_t)SEE_MALLOC(sizeof(struct ast_node_s)));

		if (succ)
		{
			if (!(succ = !!(vars = (xstring_t *)SEE_MALLOC(
								sizeof(xstring_t) *
								vars_count))))
				SEE_FREE(proc);
		}

		if (succ)
		{
			root->header.type = AST_WITH;

			root->with.varc = vars_count;
			root->with.vars = vars;

			ast_node_t v_now  = vars_list->general.head;
			int i;
			for (i = 0; i != root->with.varc; ++ i)
			{
				root->with.vars[i] = v_now->symbol.str;
				ast_node_t last = v_now;
				v_now = v_now->header.next;
				SEE_FREE(last);
			}
			
			root->with.proc = proc;
			proc->header.type = AST_PROC;
			proc->header.prev = proc->header.next = proc;
			proc->header.priv = NULL;
			proc->proc.toplevel = 0;
			proc->proc.head = body_head;

			body_head->header.prev = h->header.prev;
			body_head->header.prev->header.next = body_head;

			SEE_FREE(vars_list);
			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else if (s != NULL && xstring_equal_cstr(s, TOKEN_COND, -1))
	{
		ast_node_t c = h->header.next;
		ast_node_t t = c->header.next;
		ast_node_t e = t->header.next;

		if (c == h || t == h || (e != h && e->header.next != h))
		{
			ERROR("Invalid format for IF\n");
			succ = 0;
		}

		if (succ)
			succ = !ast_syntax_parse(c, 0);

		if (succ)
			succ = !ast_syntax_parse(t, tail);

		if (succ && e != h)
			succ = !ast_syntax_parse(e, tail);

		if (succ)
		{
			root->header.type = AST_COND;
			
			c->header.prev = c->header.next = c;
			t->header.prev = t->header.next = t;

			root->cond.c = c;
			root->cond.t = t;

			if (e == h)
				root->cond.e = NULL;
			else
			{
				e->header.prev = e->header.next = e;
				root->cond.e = e;
			}
			
			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else if (s != NULL && xstring_equal_cstr(s, TOKEN_SET, -1))
	{
		ast_node_t n = h->header.next;
		ast_node_t v = n->header.next;

		if (n == h || v == h || v->header.next != h)
		{
			
			succ = 0;
			/* TODO ERROR */
		}
		else if (n->header.type != AST_SYMBOL ||
				 n->symbol.type != SYMBOL_GENERAL)
		{
			succ = 0;
			/* TODO ERROR */
		}

		if (succ)
			succ = !ast_syntax_parse(v, 0);
		
		if (succ)
		{
			root->header.type = AST_SET;
			
			root->set.name = n->symbol.str;
			v->header.next = v->header.prev = v;
			root->set.value = v;

			SEE_FREE(n);
			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else if (s != NULL && (xstring_equal_cstr(s, TOKEN_BEGIN, -1) ||
						   xstring_equal_cstr(s, TOKEN_TOPLEVEL, -1)))
	{
		ast_node_t s_now = h->header.next;

		if (s_now == h)
		{
			ERROR("not empty for begin\n");
			succ = 0;
		}

		if (succ)
			PROCESS_LIST(s_now, h, tail);
		
		if (succ)
		{
			root->header.type = AST_PROC;
			root->proc.toplevel = xstring_equal_cstr(s, TOKEN_TOPLEVEL, -1);
			root->proc.head = s_now;
			
			s_now->header.prev = h->header.prev;
			s_now->header.prev->header.next = s_now;
			
			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else if (s != NULL && xstring_equal_cstr(s, TOKEN_AND, -1))
	{
		ast_node_t s_now = h->header.next;

		if (s_now == h)
		{
			ERROR("not empty for and\n");
			succ = 0;
		}

		if (succ)
			PROCESS_LIST(s_now, h, tail);

		if (succ)
		{
			root->header.type = AST_AND;
			root->s_and.head = s_now;

			s_now->header.prev = h->header.prev;
			s_now->header.prev->header.next = s_now;
			
			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else if (s != NULL && xstring_equal_cstr(s, TOKEN_OR, -1))
	{
		ast_node_t s_now = h->header.next;

		if (s_now == h)
		{
			ERROR("not empty for and\n");
			succ = 0;
		}

		if (succ)
			PROCESS_LIST(s_now, h, tail);
		
		if (succ)
		{
			root->header.type = AST_AND;
			root->s_and.head = s_now;

			s_now->header.prev = h->header.prev;
			s_now->header.prev->header.next = s_now;
			
			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else if (s != NULL && xstring_equal_cstr(s, TOKEN_CALLCC, -1))
	{
		ast_node_t n = h->header.next;
		if (n == h || n->header.next != h)
		{
			ERROR("ERROR FORMAT FOR CALL/CC\n");
			succ = 0;
		}

		if (succ)
			succ = !ast_syntax_parse(n, 0);
		
		if (succ)
		{
			root->header.type = AST_CALLCC;
			n->header.next = n->header.prev = n;
			root->callcc.node = n;
			root->callcc.tail = tail;

			SEE_FREE(h);
			xstring_free(s);
		}
	}
	else
	{
		/* PROCESS APPLY */
		int a_count = 0;
		ast_node_t a_now = h->header.next;
		
		succ = !ast_syntax_parse(h, 0);
		
		if (succ)
		{
			while (a_now != h)
			{
				++ a_count;
				if (ast_syntax_parse(a_now, 0)) succ = 0;
				a_now = a_now->header.next;
			}
		}
		
		ast_node_t *args = NULL;
		if (succ && a_count > 0)
			succ = !!(args = (ast_node_t *)SEE_MALLOC(sizeof(ast_node_t) * a_count));
		
		if (succ)
		{
			root->header.type = AST_APPLY;
		
			root->apply.argc = a_count;
			root->apply.tail = tail;
			root->apply.func = h;
			
			root->apply.args = args;
			
			a_now = h->header.next;
			int i;
			for (i = 0; i != a_count; ++ i)
			{
				root->apply.args[i] = a_now;
				a_now = a_now->header.next;
			}
		}
	}

	return !succ;
}
static void
process_one_file (const char *filename,
                  GError    **err)
{
  char *new_filename;
  char *dirname;
  char *basename;
  GKeyFile *kf = NULL;
  GError *rebuild_error;
  GSList *tmp;
  
  kf = g_key_file_new ();
  if (!g_key_file_load_from_file (kf, filename,
			          G_KEY_FILE_KEEP_COMMENTS|
				  G_KEY_FILE_KEEP_TRANSLATIONS,
				  err)) {
    g_key_file_free (kf);
    return;
  }

  if (!desktop_file_fixup (kf, filename)) {
    g_key_file_free (kf);
    g_set_error (err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE,
                 _("Failed to fix the content of the desktop file"));
    return;
  }

  if (copy_name_to_generic_name)
    dfu_key_file_copy_key (kf, GROUP_DESKTOP_ENTRY, "Name",
                               GROUP_DESKTOP_ENTRY, "GenericName");

  if (copy_generic_name_to_name)
    dfu_key_file_copy_key (kf, GROUP_DESKTOP_ENTRY, "GenericName",
                               GROUP_DESKTOP_ENTRY, "Name");
  
  /* Mark file as having been processed by us, so automated
   * tools can check that desktop files went through our
   * munging
   */
  g_key_file_set_string (kf, GROUP_DESKTOP_ENTRY,
                         "X-Desktop-File-Install-Version", VERSION);

#define PROCESS_LIST(key, added, removed)                       \
  /* Add to the list */                                         \
  tmp = added;                                                  \
  while (tmp != NULL)                                           \
    {                                                           \
      dfu_key_file_merge_list (kf, GROUP_DESKTOP_ENTRY,         \
                               key, tmp->data);                 \
      tmp = tmp->next;                                          \
    }                                                           \
                                                                \
  /* Remove from the list */                                    \
  tmp = removed;                                                \
  while (tmp != NULL)                                           \
    {                                                           \
      dfu_key_file_remove_list (kf, GROUP_DESKTOP_ENTRY,        \
                                key, tmp->data);                \
      tmp = tmp->next;                                          \
    }

  /* Add/remove categories */
  PROCESS_LIST ("Categories", added_categories, removed_categories);

  /* Add/remove onlyshowin */
  PROCESS_LIST ("OnlyShowIn", added_only_show_in, removed_only_show_in);

  /* Remove keys */
  tmp = removed_keys;
  while (tmp != NULL)
    {
      g_key_file_remove_key (kf, GROUP_DESKTOP_ENTRY, tmp->data, NULL);

      tmp = tmp->next;
    }

  /* Add/remove mime-types */
  PROCESS_LIST ("MimeType", added_mime_types, removed_mime_types);


  dirname = g_path_get_dirname (filename);
  basename = g_path_get_basename (filename);
  
  if (vendor_name && !g_str_has_prefix (basename, vendor_name))
    {
      char *new_base;
      new_base = g_strconcat (vendor_name, "-", basename, NULL);
      new_filename = g_build_filename (target_dir, new_base, NULL);
      g_free (new_base);
    }
  else
    {
      new_filename = g_build_filename (target_dir, basename, NULL);
    }

  g_free (dirname);
  g_free (basename);
  
  if (!dfu_key_file_to_file (kf, new_filename, err)) {
    g_key_file_free (kf);
    g_free (new_filename);
    return;
  }
  
  g_key_file_free (kf);

  /* Load and validate the file we just wrote */
  if (!desktop_file_validate (new_filename, FALSE, TRUE))
    {
      g_set_error (err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE,
                   _("Failed to validate the created desktop file"));
      g_unlink (new_filename);
      g_free (new_filename);
      return;
    }

  if (g_chmod (new_filename, permissions) < 0)
    {
      g_set_error (err, G_FILE_ERROR,
                   g_file_error_from_errno (errno),
                   _("Failed to set permissions %o on \"%s\": %s"),
                   permissions, new_filename, g_strerror (errno));

      g_unlink (new_filename);
      g_free (new_filename);
      return;
    }

  if (delete_original &&
      !files_are_the_same (filename, new_filename))
    {
      if (g_unlink (filename) < 0)
        g_printerr (_("Error removing original file \"%s\": %s\n"),
                    filename, g_strerror (errno));
    }

  if (rebuild_mime_info_cache)
    {
      rebuild_error = NULL;
      rebuild_cache (target_dir, &rebuild_error);

      if (rebuild_error != NULL)
        g_propagate_error (err, rebuild_error);
    }
  
  g_free (new_filename);
}