コード例 #1
0
ファイル: robocompiler.c プロジェクト: stevely/New-Robowar
static token_list * push_op( token_list *t ) {
    token_list *tok = t;
    int dest, reg;
    RW_Robo_Op new_op;
    /* Push can take a register, immediate, or label.
       This makes things a bit hairy, as we don't have an instruction for both
       immediates and registers. Therefor, we have two different instructions,
       and pick which one depending on what we got. */
    tok = t->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t == token_reg ) {
        reg = tok->value;
        encode_op_regs(new_op, op_one_reg, reg, 0, op_pushr);
    }
    else if( tok->t == token_num ) {
        dest = tok->value;
        encode_op_imme(new_op, op_push, dest);
    }
    else if( tok->t == token_label ) {
        dest = check_label(tok);
        encode_op_imme(new_op, op_push, dest);
    }
    else {
        error_line = tok->line_number;
        error = err_labelnumreg_expected;
        return NULL;
    }
    create_instruction(new_op);
    return tok->next;
}
コード例 #2
0
ファイル: check.c プロジェクト: Rafael-Ribeiro/pjavac
int check_loop_stmt(is_loop_stmt* node)
{
	int errors = 0;

	if (node->loop_label)
		errors += check_label(node->loop_label);

	switch (node->type)
	{
		case t_loop_stmt_for:
			errors += check_for(node->data.for_stmt, node->loop_label);
		break;

		case t_loop_stmt_while:
			errors += check_while(node->data.while_stmt, node->loop_label);
		break;

		case t_loop_stmt_do_while:
			errors += check_do_while(node->data.do_while_stmt, node->loop_label);
		break;
	}

	if (errors == 0)
	{
		/*
			TODO:
			propagate loop terminates, only if node condition is ALWAYS true
		*/
	}

	return errors;
}
コード例 #3
0
ファイル: read_line.c プロジェクト: GabrielPora/WeThinkCode
int	read_line(t_info *info, char *line, int line_nbr)
{
	int		i;
	int		valid_label;
	t_label	*temp;

	i = 0;
	valid_label = 0;
	while (line[i] != '\0' && line[i] != COMMENT_CHAR)
	{
		if (line[i] == LABEL_CHAR)
		{
			temp = check_label(line, i, &valid_label, line_nbr);
			if (valid_label == -1)
				return (-1);
			if (valid_label == 1)
			{
				info->num_labels++;
				ft_lstappend(&info->labels, ft_lstnew((void *)temp));
			}
		}
		i++;
	}
	return (0);
}
コード例 #4
0
ファイル: arbiter.c プロジェクト: runemaster/ArbiterThread
static void handle_pthread_join_rpc(struct arbiter_thread *abt,
				    struct client_desc *c,
				    struct abt_request *req, 
				    struct rpc_header *hdr)
{
	label_t L1, L2;
	own_t O1, O2;
	struct client_desc *c_join;
	struct abt_reply_header rply;
	struct abreq_pthread_join *pjoinreq = (struct abreq_pthread_join *)hdr;
	AB_INFO("Processing pthread_join \n");
	
	c_join = arbiter_lookup_client_pid(abt, pjoinreq->pid);
	AB_DBG("handle_pthread_join: pid = %d\n", pjoinreq->pid);
	
	//check if the joining child belongs to the control group
	if (c_join == NULL ) {
		AB_MSG("handle_pthread_join_rpc: unknown client\n");
		rply.abt_reply_magic = ABT_RPC_MAGIC;
		rply.msg_len = sizeof(rply);
		rply.return_val = -1; //-1 indicate failure
		abt_sendreply(abt, req, &rply);
		return;
	}

	*(uint64_t *)L1 = c->label;
	*(uint64_t *)O1 = c->ownership;
	*(uint64_t *)L2 = c_join->label;
	*(uint64_t *)O2 = c_join->ownership;

	//label check
	if ( check_label(L1, O1, L2, O2) ) {
		rply.abt_reply_magic = ABT_RPC_MAGIC;
		rply.msg_len = sizeof(rply);
		rply.return_val = -1; //-1 indicate failure

	//report voilation
		AB_MSG("Security Voilation: handle_pthread_join_rpc\n");
		
		abt_sendreply(abt, req, &rply);
		return;
	}

	AB_DBG("thread calling join: &c=%p, pid=%d, label=%lx, ownership=%lx\n", 
		c, c->pid, (long int)c->label, (long int)c->ownership);
	AB_DBG("thread join: &c%p, pid=%d, label=%lx, ownership=%lx\n", 
		c_join, c_join->pid, (long int)c_join->label, (long int)c_join->ownership);
	
	//deallocate c_join
	arbiter_del_client(abt, c_join); //remove from linked list
	free(c_join);

	rply.abt_reply_magic = ABT_RPC_MAGIC;
	rply.msg_len = sizeof(rply);
	rply.return_val = 0; //0 indicate success

	abt_sendreply(abt, req, &rply);

}
コード例 #5
0
ファイル: expressions.c プロジェクト: AlbertVeli/z80asm
int
rd_label (const char **p, int *exists, struct label **previous, int level,
	  int print_errors)
{
  struct label *l = NULL;
  int s;
  if (exists)
    *exists = 0;
  if (previous)
    *previous = NULL;
  if (verbose >= 6)
    fprintf (stderr, "%5d (0x%04x): Starting to read label (string=%s).\n",
	     stack[sp].line, addr, *p);
  for (s = level; s >= 0; --s)
    {
      if (check_label (stack[s].labels, p, &l,
		       (**p == '.' && s == sp) ? previous : NULL, 0))
	break;
    }
  if (s < 0)
    {
      /* not yet found */
      const char *old_p = *p;
      if (!check_label (firstlabel, p, &l, **p != '.' ? previous : NULL, 1))
	{
	  /* label does not exist, or is invalid.  This is an error if there
	   * is no existance check.  */
	  if (!exists && print_errors)
	    printerr (1, "using undefined label %.*s\n", *p - old_p, old_p);
	  /* Return a value to discriminate between non-existing and invalid */
	  if (verbose >= 7)
	    fprintf (stderr, "rd_label returns invalid value\n");
	  return l != NULL;
	}
    }
  if (exists)
    *exists = 1;
  if (verbose >= 7)
    fprintf (stderr, "rd_label returns valid value 0x%x\n", l->value);
  return l->value;
}
コード例 #6
0
ファイル: arbiter.c プロジェクト: runemaster/ArbiterThread
static void handle_realloc_rpc(struct arbiter_thread *abt,
			       struct client_desc *c,
			       struct abt_request *req, 
			       struct rpc_header *hdr)
{
	void *ptr, *rval;
	size_t size;
	pid_t pid;
	ustate unit;
	label_t L1, L2;
	own_t O1;
	struct abt_reply_header rply;
	struct abreq_realloc *reallocreq = (struct abreq_realloc *)hdr;
	AB_INFO("Processing realloc, addr = %lx\n", (unsigned long)reallocreq->addr);

	pid = (pid_t)(c->pid);
	*(uint64_t *)L1 = c->label;
	*(uint64_t *)O1 = c->ownership;

	ptr = (void *)(reallocreq->addr);
	size = reallocreq->size;
	if (ptr != NULL) {
		unit = lookup_ustate_by_mem(ptr);
		assert(unit != NULL);
		memcpy(L2, unit->unit_av->label, sizeof(label_t));
	}
	else {
		*(uint64_t *)L2 = c->label; //in order to pass label check
	}
	
	//label check	
	if ( check_label(L1, O1, L2, NULL) ) {
		rply.abt_reply_magic = ABT_RPC_MAGIC;
		rply.msg_len = sizeof(rply);

		//report voilatioin
		AB_MSG("VOILATION: realloc voilation!\n");
	
		abt_sendreply(abt, req, &rply);
		return;
	}
	
	rval = (void *)ablib_realloc(pid, ptr, size, L2);
	
	rply.abt_reply_magic = ABT_RPC_MAGIC;
	rply.msg_len = sizeof(rply);
	rply.return_val = (uint32_t)rval;

	abt_sendreply(abt, req, &rply);


}
コード例 #7
0
ファイル: label.c プロジェクト: ErisBlastar/osfree
void get_label()
{
    char temp[MAX_LABEL_LENGTH+1];

    do
        {
        myprintf("Volume label (11 characters, ENTER for none)? ",0);
        mygets(temp,MAX_LABEL_LENGTH+1);
        } /* end do. */
    while (check_label(temp));
    strcpy(Label, temp);

} /* end get_label. */
コード例 #8
0
void params_read_gsl_vector(FILE* f, char* name, gsl_vector** x)
{
    int size, i;
    double val;

    check_label(f, name);
    assert(fscanf(f, "%d", &size) > 0);
    *x = gsl_vector_calloc(size);
    for (i = 0; i < size; i++)
    {
        assert(fscanf(f, "%lf", &val) > 0);
        gsl_vector_set(*x, i, val);
    }
}
コード例 #9
0
ファイル: label.c プロジェクト: ErisBlastar/osfree
int valid_label(char *s)
{
    if (s[2] != '\0')
        {
        if (check_label(&s[2]))
            return(1);

        save_label(&s[2]);
        return(0);
        } /* end if. */

    return 0; /* empty string is not a valid label, or is it??? */

} /* end valid_label. */
コード例 #10
0
ファイル: label.c プロジェクト: ErisBlastar/osfree
void do_cmdline(int ac, char *av[])
{
    int i;

    for (i=1;i<ac;i++)
        {
        if (valid_drive((av[i])=strupr(av[i])))
            {
            if (*Drive == '?')
                {
                *Drive = *av[i];        /* Save the drive letter. */
                } /* end if. */
            else
                {
                myprintf("There were multiple drives mentioned.\r\n",0);
                myprintf("Please select one drive to label at a time.\r\n",0);
                exit(26);
                } /* end if. */

            /* See if the drive letter is the first parameter. */
            if (i != 1)
                DriveNotFirst = 1;

            /* See if the label is tacked right onto the drive letter. */
            /* Verify label if it is. */
            if (valid_label(av[i]))
                return;

            } /* end if. */
        else
            {
            if (check_label(av[i]))
                return;
            else
                save_label(av[i]);

            } /* end else. */

        } /* end for. */

    if (check_quotes())
        {
        strcpy(Label,"");
        myprintf("Invalid label\r\n",0);
        return;
        } /* end if. */

} /* end process_cmdline. */
コード例 #11
0
ファイル: arbiter.c プロジェクト: runemaster/ArbiterThread
static void handle_calloc_rpc(struct arbiter_thread *abt,
			      struct client_desc *c,
			      struct abt_request *req, 
			      struct rpc_header *hdr)
{
	void *ptr;
	size_t size, nmemb;
	label_t L1, L2;
	pid_t pid;
	own_t O1;
	struct abt_reply_header rply;
	struct abreq_calloc *callocreq = (struct abreq_calloc *)hdr;
	AB_INFO("Processing calloc \n");

	nmemb = callocreq->nmemb;
	size = callocreq->size;
	*(uint64_t *)L2 = callocreq->label;

	pid = (pid_t)(c->pid);
	*(uint64_t *)L1 = c->label;
	*(uint64_t *)O1 = c->ownership;

	//label check	
	if ( check_label(L1, O1, L2, NULL) ) {
		ptr = NULL;
		rply.abt_reply_magic = ABT_RPC_MAGIC;
		rply.msg_len = sizeof(rply);
		rply.return_val = (uint32_t)ptr;

		//report voilatioin
		AB_MSG("VOILATION: calloc voilation!\n");
	
		abt_sendreply(abt, req, &rply);
		return;
	}
	
	ptr = (void *)ablib_calloc(pid, nmemb, size, L2);

	rply.abt_reply_magic = ABT_RPC_MAGIC;
	rply.msg_len = sizeof(rply);
	rply.return_val = (uint32_t)ptr;

	abt_sendreply(abt, req, &rply);

}
コード例 #12
0
ファイル: check.c プロジェクト: Rafael-Ribeiro/pjavac
int check_switch(is_switch* node)
{
	int errors = 0;
	int mylabel = ++label_counter; /* setting label for use with break */
	char *type;

	if (node->label)
		errors += check_label(node->label);

	errors += check_expr(node->expr);

	if (errors == 0)
	{
		if (node->expr->s_type->type == t_type_decl_array_decl)
		{
			errors++;

			type = string_type_decl(node->expr->s_type);
			pretty_error(node->line, "switch statement expression must be of object type (got %s)", type);
			free(type);
		}
	}

	if (errors == 0)
	{
		if (node->label)
			node->scope = scope_new(symbol_new_switch(node->label->name, node->line, mylabel, node->expr->s_type->data.type_object, symtab->framepos++), false);
		else
			node->scope = scope_new(symbol_new_switch(NULL, node->line, mylabel, node->expr->s_type->data.type_object, symtab->framepos++), false);

		scope_push(node->scope);
			check_switch_stmt_list(node->list, node);

			if (errors == 0)
				node->terminates = (node->list ? node->list->terminates : true);
		scope_pop();
 	}

	return errors;
}
コード例 #13
0
ファイル: sunlabel.c プロジェクト: edgar-pek/PerspicuOS
static int
parse_label(struct sun_disklabel *sl, const char *file)
{
	char offset[32];
	char size[32];
	char flag[32];
	char tag[32];
	char buf[128];
	char text[128];
	char volname[SUN_VOLNAME_LEN + 1];
	struct sun_disklabel sl1;
	char *bp;
	const char *what;
	uint8_t part;
	FILE *fp;
	int line;
	int rv;
	int wantvtoc;
	unsigned alt, cyl, hd, nr, sec;

	line = wantvtoc = 0;
	if ((fp = fopen(file, "r")) == NULL)
		err(1, "fopen");
	sl1 = *sl;
	bzero(&sl1.sl_part, sizeof(sl1.sl_part));
	while (fgets(buf, sizeof(buf), fp) != NULL) {
		/*
		 * In order to recognize a partition entry, we search
		 * for lines starting with a single letter followed by
		 * a colon as their first non-white characters.  We
		 * silently ignore any other lines, so any comment etc.
		 * lines in the label template will be ignored.
		 *
		 * XXX We should probably also recognize the geometry
		 * fields on top, and allow changing the geometry
		 * emulated by this disk.
		 */
		for (bp = buf; isspace(*bp); bp++)
			;
		if (strncmp(bp, "text:", strlen("text:")) == 0) {
			bp += strlen("text:");
			rv = sscanf(bp,
			    " %s cyl %u alt %u hd %u sec %u",
			    text, &cyl, &alt, &hd, &sec);
			if (rv != 5) {
				warnx("%s, line %d: text label does not "
				    "contain required fields",
				    file, line + 1);
				fclose(fp);
				return (1);
			}
			if (alt != 2) {
				warnx("%s, line %d: # alt must be equal 2",
				    file, line + 1);
				fclose(fp);
				return (1);
			}
			if (cyl == 0 || cyl > USHRT_MAX) {
				what = "cyl";
				nr = cyl;
			unreasonable:
				warnx("%s, line %d: # %s %d unreasonable",
				    file, line + 1, what, nr);
				fclose(fp);
				return (1);
			}
			if (hd == 0 || hd > USHRT_MAX) {
				what = "hd";
				nr = hd;
				goto unreasonable;
			}
			if (sec == 0 || sec > USHRT_MAX) {
				what = "sec";
				nr = sec;
				goto unreasonable;
			}
			if (mediasize == 0)
				warnx("unit size unknown, no sector count "
				    "check could be done");
			else if ((uintmax_t)(cyl + alt) * sec * hd >
				 (uintmax_t)mediasize / sectorsize) {
				warnx("%s, line %d: sector count %ju exceeds "
				    "unit size %ju",
				    file, line + 1,
				    (uintmax_t)(cyl + alt) * sec * hd,
				    (uintmax_t)mediasize / sectorsize);
				fclose(fp);
				return (1);
			}
			sl1.sl_pcylinders = cyl + alt;
			sl1.sl_ncylinders = cyl;
			sl1.sl_acylinders = alt;
			sl1.sl_nsectors = sec;
			sl1.sl_ntracks = hd;
			memset(sl1.sl_text, 0, sizeof(sl1.sl_text));
			snprintf(sl1.sl_text, sizeof(sl1.sl_text),
			    "%s cyl %u alt %u hd %u sec %u",
			    text, cyl, alt, hd, sec);
			continue;
		}
		if (strncmp(bp, "volume name:", strlen("volume name:")) == 0) {
			wantvtoc = 1; /* Volume name requires VTOC. */
			bp += strlen("volume name:");
#if SUN_VOLNAME_LEN != 8
# error "scanf field width does not match SUN_VOLNAME_LEN"
#endif
			/*
			 * We set the field length to one more than
			 * SUN_VOLNAME_LEN to allow detecting an
			 * overflow.
			 */
			memset(volname, 0, sizeof volname);
			rv = sscanf(bp, " %9[^\n]", volname);
			if (rv != 1) {
				/* Clear the volume name. */
				memset(sl1.sl_vtoc_volname, 0,
				    SUN_VOLNAME_LEN);
			} else {
				memcpy(sl1.sl_vtoc_volname, volname,
				    SUN_VOLNAME_LEN);
				if (volname[SUN_VOLNAME_LEN] != '\0')
					warnx(
"%s, line %d: volume name longer than %d characters, truncating",
					    file, line + 1, SUN_VOLNAME_LEN);
			}
			continue;
		}
		if (strlen(bp) < 2 || bp[1] != ':') {
			line++;
			continue;
		}
		rv = sscanf(bp, "%c: %30s %30s %30s %30s",
		    &part, size, offset, tag, flag);
		if (rv < 3) {
		syntaxerr:
			warnx("%s: syntax error on line %d",
			    file, line + 1);
			fclose(fp);
			return (1);
		}
		if (parse_size(&sl1, part - 'a', size) ||
		    parse_offset(&sl1, part - 'a', offset))
			goto syntaxerr;
		if (rv > 3) {
			wantvtoc = 1;
			if (rv == 5 && parse_flag(&sl1, part - 'a', flag))
				goto syntaxerr;
			if (parse_tag(&sl1, part - 'a', tag))
				goto syntaxerr;
		}
		line++;
	}
	fclose(fp);
	if (wantvtoc) {
		sl1.sl_vtoc_sane = SUN_VTOC_SANE;
		sl1.sl_vtoc_vers = SUN_VTOC_VERSION;
		sl1.sl_vtoc_nparts = SUN_NPART;
	} else {
		sl1.sl_vtoc_sane = 0;
		sl1.sl_vtoc_vers = 0;
		sl1.sl_vtoc_nparts = 0;
		bzero(&sl1.sl_vtoc_map, sizeof(sl1.sl_vtoc_map));
	}
	*sl = sl1;
	return (check_label(sl));
}
コード例 #14
0
void params_read_double(FILE* f, char* name, double* x)
{
    check_label(f, name);
    assert(fscanf(f, "%lf", x) > 0);
    outlog("%-10s READ NAME=%-10s DBL=%1.14e", "[PARAMS]", name, *x);
}
コード例 #15
0
ファイル: rdwr_efi.c プロジェクト: ryao/openzfs
static int
efi_read(int fd, struct dk_gpt *vtoc)
{
	int			i, j;
	int			label_len;
	int			rval = 0;
	int			md_flag = 0;
	int			vdc_flag = 0;
	struct dk_minfo		disk_info;
	dk_efi_t		dk_ioc;
	efi_gpt_t		*efi;
	efi_gpe_t		*efi_parts;
	struct dk_cinfo		dki_info;
	uint32_t		user_length;
	boolean_t		legacy_label = B_FALSE;

	/*
	 * get the partition number for this file descriptor.
	 */
	if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
		if (efi_debug) {
			(void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno);
		}
		switch (errno) {
		case EIO:
			return (VT_EIO);
		case EINVAL:
			return (VT_EINVAL);
		default:
			return (VT_ERROR);
		}
	}
	if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) &&
	    (strncmp(dki_info.dki_dname, "md", 3) == 0)) {
		md_flag++;
	} else if ((strncmp(dki_info.dki_cname, "vdc", 4) == 0) &&
	    (strncmp(dki_info.dki_dname, "vdc", 4) == 0)) {
		/*
		 * The controller and drive name "vdc" (virtual disk client)
		 * indicates a LDoms virtual disk.
		 */
		vdc_flag++;
	}

	/* get the LBA size */
	if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
		if (efi_debug) {
			(void) fprintf(stderr,
			    "assuming LBA 512 bytes %d\n",
			    errno);
		}
		disk_info.dki_lbsize = DEV_BSIZE;
	}
	if (disk_info.dki_lbsize == 0) {
		if (efi_debug) {
			(void) fprintf(stderr,
			    "efi_read: assuming LBA 512 bytes\n");
		}
		disk_info.dki_lbsize = DEV_BSIZE;
	}
	/*
	 * Read the EFI GPT to figure out how many partitions we need
	 * to deal with.
	 */
	dk_ioc.dki_lba = 1;
	if (NBLOCKS(vtoc->efi_nparts, disk_info.dki_lbsize) < 34) {
		label_len = EFI_MIN_ARRAY_SIZE + disk_info.dki_lbsize;
	} else {
		label_len = vtoc->efi_nparts * (int) sizeof (efi_gpe_t) +
		    disk_info.dki_lbsize;
		if (label_len % disk_info.dki_lbsize) {
			/* pad to physical sector size */
			label_len += disk_info.dki_lbsize;
			label_len &= ~(disk_info.dki_lbsize - 1);
		}
	}

	if ((dk_ioc.dki_data = calloc(label_len, 1)) == NULL)
		return (VT_ERROR);

	dk_ioc.dki_length = disk_info.dki_lbsize;
	user_length = vtoc->efi_nparts;
	efi = dk_ioc.dki_data;
	if (md_flag) {
		dk_ioc.dki_length = label_len;
		if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) {
			switch (errno) {
			case EIO:
				return (VT_EIO);
			default:
				return (VT_ERROR);
			}
		}
	} else if ((rval = check_label(fd, &dk_ioc)) == VT_EINVAL) {
		/*
		 * No valid label here; try the alternate. Note that here
		 * we just read GPT header and save it into dk_ioc.data,
		 * Later, we will read GUID partition entry array if we
		 * can get valid GPT header.
		 */

		/*
		 * This is a workaround for legacy systems. In the past, the
		 * last sector of SCSI disk was invisible on x86 platform. At
		 * that time, backup label was saved on the next to the last
		 * sector. It is possible for users to move a disk from previous
		 * solaris system to present system. Here, we attempt to search
		 * legacy backup EFI label first.
		 */
		dk_ioc.dki_lba = disk_info.dki_capacity - 2;
		dk_ioc.dki_length = disk_info.dki_lbsize;
		rval = check_label(fd, &dk_ioc);
		if (rval == VT_EINVAL) {
			/*
			 * we didn't find legacy backup EFI label, try to
			 * search backup EFI label in the last block.
			 */
			dk_ioc.dki_lba = disk_info.dki_capacity - 1;
			dk_ioc.dki_length = disk_info.dki_lbsize;
			rval = check_label(fd, &dk_ioc);
			if (rval == 0) {
				legacy_label = B_TRUE;
				if (efi_debug)
					(void) fprintf(stderr,
					    "efi_read: primary label corrupt; "
					    "using EFI backup label located on"
					    " the last block\n");
			}
		} else {
			if ((efi_debug) && (rval == 0))
				(void) fprintf(stderr, "efi_read: primary label"
				    " corrupt; using legacy EFI backup label "
				    " located on the next to last block\n");
		}

		if (rval == 0) {
			dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA);
			vtoc->efi_flags |= EFI_GPT_PRIMARY_CORRUPT;
			vtoc->efi_nparts =
			    LE_32(efi->efi_gpt_NumberOfPartitionEntries);
			/*
			 * Partition tables are between backup GPT header
			 * table and ParitionEntryLBA (the starting LBA of
			 * the GUID partition entries array). Now that we
			 * already got valid GPT header and saved it in
			 * dk_ioc.dki_data, we try to get GUID partition
			 * entry array here.
			 */
			/* LINTED */
			dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data
			    + disk_info.dki_lbsize);
			if (legacy_label)
				dk_ioc.dki_length = disk_info.dki_capacity - 1 -
				    dk_ioc.dki_lba;
			else
				dk_ioc.dki_length = disk_info.dki_capacity - 2 -
				    dk_ioc.dki_lba;
			dk_ioc.dki_length *= disk_info.dki_lbsize;
			if (dk_ioc.dki_length >
			    ((len_t)label_len - sizeof (*dk_ioc.dki_data))) {
				rval = VT_EINVAL;
			} else {
				/*
				 * read GUID partition entry array
				 */
				rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc);
			}
		}

	} else if (rval == 0) {

		dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA);
		/* LINTED */
		dk_ioc.dki_data = (efi_gpt_t *)((char *)dk_ioc.dki_data
		    + disk_info.dki_lbsize);
		dk_ioc.dki_length = label_len - disk_info.dki_lbsize;
		rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc);

	} else if (vdc_flag && rval == VT_ERROR && errno == EINVAL) {
		/*
		 * When the device is a LDoms virtual disk, the DKIOCGETEFI
		 * ioctl can fail with EINVAL if the virtual disk backend
		 * is a ZFS volume serviced by a domain running an old version
		 * of Solaris. This is because the DKIOCGETEFI ioctl was
		 * initially incorrectly implemented for a ZFS volume and it
		 * expected the GPT and GPE to be retrieved with a single ioctl.
		 * So we try to read the GPT and the GPE using that old style
		 * ioctl.
		 */
		dk_ioc.dki_lba = 1;
		dk_ioc.dki_length = label_len;
		rval = check_label(fd, &dk_ioc);
	}

	if (rval < 0) {
		free(efi);
		return (rval);
	}

	/* LINTED -- always longlong aligned */
	efi_parts = (efi_gpe_t *)(((char *)efi) + disk_info.dki_lbsize);

	/*
	 * Assemble this into a "dk_gpt" struct for easier
	 * digestibility by applications.
	 */
	vtoc->efi_version = LE_32(efi->efi_gpt_Revision);
	vtoc->efi_nparts = LE_32(efi->efi_gpt_NumberOfPartitionEntries);
	vtoc->efi_part_size = LE_32(efi->efi_gpt_SizeOfPartitionEntry);
	vtoc->efi_lbasize = disk_info.dki_lbsize;
	vtoc->efi_last_lba = disk_info.dki_capacity - 1;
	vtoc->efi_first_u_lba = LE_64(efi->efi_gpt_FirstUsableLBA);
	vtoc->efi_last_u_lba = LE_64(efi->efi_gpt_LastUsableLBA);
	vtoc->efi_altern_lba = LE_64(efi->efi_gpt_AlternateLBA);
	UUID_LE_CONVERT(vtoc->efi_disk_uguid, efi->efi_gpt_DiskGUID);

	/*
	 * If the array the user passed in is too small, set the length
	 * to what it needs to be and return
	 */
	if (user_length < vtoc->efi_nparts) {
		return (VT_EINVAL);
	}

	for (i = 0; i < vtoc->efi_nparts; i++) {

		UUID_LE_CONVERT(vtoc->efi_parts[i].p_guid,
		    efi_parts[i].efi_gpe_PartitionTypeGUID);

		for (j = 0;
		    j < sizeof (conversion_array)
		    / sizeof (struct uuid_to_ptag); j++) {

			if (bcmp(&vtoc->efi_parts[i].p_guid,
			    &conversion_array[j].uuid,
			    sizeof (struct uuid)) == 0) {
				vtoc->efi_parts[i].p_tag = j;
				break;
			}
		}
		if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED)
			continue;
		vtoc->efi_parts[i].p_flag =
		    LE_16(efi_parts[i].efi_gpe_Attributes.PartitionAttrs);
		vtoc->efi_parts[i].p_start =
		    LE_64(efi_parts[i].efi_gpe_StartingLBA);
		vtoc->efi_parts[i].p_size =
		    LE_64(efi_parts[i].efi_gpe_EndingLBA) -
		    vtoc->efi_parts[i].p_start + 1;
		for (j = 0; j < EFI_PART_NAME_LEN; j++) {
			vtoc->efi_parts[i].p_name[j] =
			    (uchar_t)LE_16(
			    efi_parts[i].efi_gpe_PartitionName[j]);
		}

		UUID_LE_CONVERT(vtoc->efi_parts[i].p_uguid,
		    efi_parts[i].efi_gpe_UniquePartitionGUID);
	}
	free(efi);

	return (dki_info.dki_partition);
}
コード例 #16
0
ファイル: arbiter.c プロジェクト: runemaster/ArbiterThread
static void handle_fork_rpc(struct arbiter_thread *abt,
			    struct client_desc *c,
			    struct abt_request *req, 
			    struct rpc_header *hdr)
{
	label_t L1, L2;
	own_t O1, O2;
	struct client_desc *c_new;
	struct abt_reply_header rply;
	struct abreq_fork *forkreq = (struct abreq_fork *)hdr;
	AB_INFO("Arbiter: Processing fork \n");
	
	*(uint64_t *)L1 = c->label;
	*(uint64_t *)O1 = c->ownership;
	*(uint64_t *)L2 = forkreq->label;
	*(uint64_t *)O2 = forkreq->ownership;

	//label check
	if ( check_label(L1, O1, L2, O2) ) {
		rply.abt_reply_magic = ABT_RPC_MAGIC;
		rply.msg_len = sizeof(rply);
		rply.return_val = -1; //-1 indicate failure

	//report voilation
		AB_MSG("Arbiter: Security Voilation: handle_fork_rpc\n");
		
		abt_sendreply(abt, req, &rply);
		return;
	}

	//allocate a new struct client_desc for new thread
	c_new = (struct client_desc *)malloc(sizeof(struct client_desc));
	memset(c_new, 0, sizeof(c_new));

	//fill out client_desc for the new thread...
	memcpy(	&(c_new->client_addr.unix_addr), 
		&(req->client_addr), 
		sizeof(req->client_addr));
	c_new->client_addr.addr_len = req->client_addr_len;
	
	//FIXME: to get the pid of new thread in secure way
	c_new->pid  = forkreq->pid;
	c_new->label = *(uint64_t *)L2;
	c_new->ownership = *(uint64_t *)O2;
	
	GET_FAMILY(c_new->client_addr.unix_addr) = AF_UNIX;
	snprintf(GET_PATH(c_new->client_addr.unix_addr), 108, "/tmp/abt_client_%d", c_new->pid);
	c_new->client_addr.addr_len = sizeof(GET_FAMILY(c_new->client_addr.unix_addr)) + strlen(GET_PATH(c_new->client_addr.unix_addr)) + 1;
	
	//add new thread to linked list	
	list_insert_tail(&(arbiter.client_list), (void *)c_new);
	
	AB_DBG("Arbiter: new thread forked: pid=%d, label=%lx, ownership=%lx\n", 
		c_new->pid, (long int)c_new->label, (long int)c_new->ownership);
	
	//set up or update page tables for existing allocated memory
	malloc_update(c_new);
	
	rply.abt_reply_magic = ABT_RPC_MAGIC;
	rply.msg_len = sizeof(rply);
	rply.return_val = 0; //0 indicate success

	abt_sendreply(abt, req, &rply);

}
コード例 #17
0
ファイル: rdwr_efi.c プロジェクト: andreiw/polaris
static int
efi_read(int fd, struct dk_gpt *vtoc)
{
	int			i, j;
	int			label_len;
	int			rval = 0;
	int			md_flag = 0;
	struct dk_minfo		disk_info;
	dk_efi_t		dk_ioc;
	efi_gpt_t		*efi;
	efi_gpe_t		*efi_parts;
	struct dk_cinfo		dki_info;
	uint32_t		user_length;

	/*
	 * get the partition number for this file descriptor.
	 */
	if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) {
		if (efi_debug)
		    (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno);
		switch (errno) {
		case EIO:
			return (VT_EIO);
		case EINVAL:
			return (VT_EINVAL);
		default:
			return (VT_ERROR);
		}
	}
	if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) &&
	    (strncmp(dki_info.dki_dname, "md", 3) == 0)) {
		md_flag++;
	}
	/* get the LBA size */
	if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
		if (efi_debug) {
			(void) fprintf(stderr,
			    "assuming LBA 512 bytes %d\n",
			    errno);
		}
		disk_info.dki_lbsize = DEV_BSIZE;
	}
	if (disk_info.dki_lbsize == 0) {
		if (efi_debug) {
			(void) fprintf(stderr,
			    "efi_read: assuming LBA 512 bytes\n");
		}
		disk_info.dki_lbsize = DEV_BSIZE;
	}
	/*
	 * Read the EFI GPT to figure out how many partitions we need
	 * to deal with.
	 */
	dk_ioc.dki_lba = 1;
	if (NBLOCKS(vtoc->efi_nparts, disk_info.dki_lbsize) < 34) {
		label_len = EFI_MIN_ARRAY_SIZE + disk_info.dki_lbsize;
	} else {
		label_len = vtoc->efi_nparts * (int) sizeof (efi_gpe_t) +
				    disk_info.dki_lbsize;
		if (label_len % disk_info.dki_lbsize) {
			/* pad to physical sector size */
			label_len += disk_info.dki_lbsize;
			label_len &= ~(disk_info.dki_lbsize - 1);
		}
	}

	if ((dk_ioc.dki_data = calloc(label_len, 1)) == NULL)
		return (VT_ERROR);

	dk_ioc.dki_length = label_len;
	user_length = vtoc->efi_nparts;
	efi = dk_ioc.dki_data;
	if (md_flag) {
		if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) {
			switch (errno) {
			case EIO:
				return (VT_EIO);
			default:
				return (VT_ERROR);
			}
		}
	} else if ((rval = check_label(fd, &dk_ioc)) == VT_EINVAL) {
		/* no valid label here; try the alternate */
		dk_ioc.dki_lba = disk_info.dki_capacity - 1;
		dk_ioc.dki_length = disk_info.dki_lbsize;
		rval = check_label(fd, &dk_ioc);
		if (rval != 0) {
			/*
			 * This is a workaround for legacy systems.
			 *
			 * In the past, the last sector of SCSI disk was
			 * invisible on x86 platform. At that time, backup
			 * label was saved on the next to the last sector.
			 * It is possible for users to move a disk from
			 * previous solaris system to present system.
			 */
			dk_ioc.dki_lba = disk_info.dki_capacity - 2;
			dk_ioc.dki_length = disk_info.dki_lbsize;
			rval = check_label(fd, &dk_ioc);
			if (efi_debug && (rval == 0)) {
				(void) fprintf(stderr,
				    "efi_read: primary label corrupt; "
				    "using legacy EFI backup label\n");
			}
		}

		if (rval == 0) {
			if (efi_debug) {
				(void) fprintf(stderr,
				    "efi_read: primary label corrupt; "
				    "using backup\n");
			}
			dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA);
			vtoc->efi_flags |= EFI_GPT_PRIMARY_CORRUPT;
			vtoc->efi_nparts =
			    LE_32(efi->efi_gpt_NumberOfPartitionEntries);
			/*
			 * partitions are between last usable LBA and
			 * backup partition header
			 */
			dk_ioc.dki_data++;
			dk_ioc.dki_length = disk_info.dki_capacity -
						    dk_ioc.dki_lba - 1;
			dk_ioc.dki_length *= disk_info.dki_lbsize;
			if (dk_ioc.dki_length > (len_t)label_len) {
				rval = VT_EINVAL;
			} else {
				rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc);
			}
		}
	}
	if (rval < 0) {
		free(efi);
		return (rval);
	}

	/* partitions start in the next block */
	/* LINTED -- always longlong aligned */
	efi_parts = (efi_gpe_t *)(((char *)efi) + disk_info.dki_lbsize);

	/*
	 * Assemble this into a "dk_gpt" struct for easier
	 * digestibility by applications.
	 */
	vtoc->efi_version = LE_32(efi->efi_gpt_Revision);
	vtoc->efi_nparts = LE_32(efi->efi_gpt_NumberOfPartitionEntries);
	vtoc->efi_part_size = LE_32(efi->efi_gpt_SizeOfPartitionEntry);
	vtoc->efi_lbasize = disk_info.dki_lbsize;
	vtoc->efi_last_lba = disk_info.dki_capacity - 1;
	vtoc->efi_first_u_lba = LE_64(efi->efi_gpt_FirstUsableLBA);
	vtoc->efi_last_u_lba = LE_64(efi->efi_gpt_LastUsableLBA);
	UUID_LE_CONVERT(vtoc->efi_disk_uguid, efi->efi_gpt_DiskGUID);

	/*
	 * If the array the user passed in is too small, set the length
	 * to what it needs to be and return
	 */
	if (user_length < vtoc->efi_nparts) {
		return (VT_EINVAL);
	}

	for (i = 0; i < vtoc->efi_nparts; i++) {

	    UUID_LE_CONVERT(vtoc->efi_parts[i].p_guid,
		efi_parts[i].efi_gpe_PartitionTypeGUID);

	    for (j = 0;
		j < sizeof (conversion_array) / sizeof (struct uuid_to_ptag);
		j++) {

		    if (bcmp(&vtoc->efi_parts[i].p_guid,
			&conversion_array[j].uuid,
			sizeof (struct uuid)) == 0) {
			    vtoc->efi_parts[i].p_tag = j;
			    break;
		    }
	    }
	    if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED)
		    continue;
	    vtoc->efi_parts[i].p_flag =
		LE_16(efi_parts[i].efi_gpe_Attributes.PartitionAttrs);
	    vtoc->efi_parts[i].p_start =
		LE_64(efi_parts[i].efi_gpe_StartingLBA);
	    vtoc->efi_parts[i].p_size =
		LE_64(efi_parts[i].efi_gpe_EndingLBA) -
		    vtoc->efi_parts[i].p_start + 1;
	    for (j = 0; j < EFI_PART_NAME_LEN; j++) {
		vtoc->efi_parts[i].p_name[j] =
		    (uchar_t)LE_16(efi_parts[i].efi_gpe_PartitionName[j]);
	    }

	    UUID_LE_CONVERT(vtoc->efi_parts[i].p_uguid,
		efi_parts[i].efi_gpe_UniquePartitionGUID);
	}
	free(efi);

	return (dki_info.dki_partition);
}
コード例 #18
0
ファイル: robocompiler.c プロジェクト: stevely/New-Robowar
static token_list * branch_op( token_list *t ) {
    int reg, dest;
    RW_Robo_Op new_op;
    token_list *tok = t;
    int type = tok->t;
    /* Check if we need a test instruction */
    if( tok->t != token_call && tok->t != token_jump ) {
        /* Get reg1 */
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_reg ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_reg1_expected;
            return NULL;
        }
        reg = tok->value;
        /* Create test instruction */
        encode_op_regs(new_op, op_one_reg, reg, 0, op_test);
        create_instruction(new_op);
        /* Eat comma */
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_comma ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_comma_expected;
            return NULL;
        }
    }
    /* Every branch instruction has at least 1 dest */
    tok = tok->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t != token_label && tok->t != token_num ) {
        /* Syntax error */
        error_line = tok->line_number;
        error = err_labelnum_expected;
        return NULL;
    }
    if( tok->t == token_label ) {
        dest = check_label(tok);
    }
    else { /* tok->t == token_num */
        dest = tok->value;
    }
    /* Create first (and possibly last) branch instruction */
    if( type == token_jump || type == token_ifg || type == token_ifeg ) {
        encode_op_imme(new_op, op_jump, dest);
        create_instruction(new_op);
    }
    else {
        encode_op_imme(new_op, op_call, dest);
        create_instruction(new_op);
    }
    /* Do we have a second branch instruction we need to make? */
    if( type == token_ife || type == token_ifeg ) {
        /* Eat comma */
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_comma ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_comma_expected;
            return NULL;
        }
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_label && tok->t != token_num ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_labelnum_expected;
            return NULL;
        }
        if( tok->t == token_label ) {
            dest = check_label(tok);
        }
        else { /* tok->t == token_num */
            dest = tok->value;
        }
        /* Create second branch instruction */
        if( type == token_ifeg ) {
            encode_op_imme(new_op, op_jump, dest);
            create_instruction(new_op);
        }
        else {
            encode_op_imme(new_op, op_call, dest);
            create_instruction(new_op);
        }
    }
    return tok->next;
}
コード例 #19
0
void params_read_int(FILE* f, char* name, int* x)
{
    check_label(f, name);
    assert(fscanf(f, "%d", x) > 0);
    outlog("%-10s READ NAME=%-10s INT=%d", "[PARAMS]", name, *x);
}
コード例 #20
0
ファイル: sunlabel.c プロジェクト: edgar-pek/PerspicuOS
static void
write_label(struct sun_disklabel *sl, const char *disk, const char *bootpath)
{
	char path[MAXPATHLEN];
	char boot[SUN_BOOTSIZE];
	char buf[SUN_SIZE];
	const char *errstr;
	off_t off;
	int bfd;
	int fd;
	int i;
	struct gctl_req *grq;

	sl->sl_magic = SUN_DKMAGIC;

	if (check_label(sl) != 0)
		errx(1, "invalid label");

	bzero(buf, sizeof(buf));
	sunlabel_enc(buf, sl);

	if (nflag) {
		print_label(sl, disk, stdout);
		return;
	}
	if (Bflag) {
		if ((bfd = open(bootpath, O_RDONLY)) < 0)
			err(1, "open %s", bootpath);
		i = read(bfd, boot, sizeof(boot));
		if (i < 0)
			err(1, "read");
		else if (i != sizeof (boot))
			errx(1, "read wrong size boot code (%d)", i);
		close(bfd);
	}
	snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk);
	fd = open(path, O_RDWR);
	if (fd < 0) {
		grq = gctl_get_handle();
		gctl_ro_param(grq, "verb", -1, "write label");
		gctl_ro_param(grq, "class", -1, "SUN");
		gctl_ro_param(grq, "geom", -1, disk);
		gctl_ro_param(grq, "label", sizeof buf, buf);
		errstr = gctl_issue(grq);
		if (errstr != NULL)
			errx(1, "%s", errstr);
		gctl_free(grq);
		if (Bflag) {
			grq = gctl_get_handle();
			gctl_ro_param(grq, "verb", -1, "write bootcode");
			gctl_ro_param(grq, "class", -1, "SUN");
			gctl_ro_param(grq, "geom", -1, disk);
			gctl_ro_param(grq, "bootcode", sizeof boot, boot);
			errstr = gctl_issue(grq);
			if (errstr != NULL)
				errx(1, "%s", errstr);
			gctl_free(grq);
		}
	} else {
		if (lseek(fd, 0, SEEK_SET) < 0)
			err(1, "lseek");
		if (write(fd, buf, sizeof(buf)) != sizeof(buf))
			err (1, "write");
		if (Bflag) {
			for (i = 0; i < SUN_NPART; i++) {
				if (sl->sl_part[i].sdkp_nsectors == 0)
					continue;
				off = sl->sl_part[i].sdkp_cyloffset *
				    sl->sl_ntracks * sl->sl_nsectors * 512;
				/*
				 * Ignore first SUN_SIZE bytes of boot code to
				 * avoid overwriting the label.
				 */
				if (lseek(fd, off + SUN_SIZE, SEEK_SET) < 0)
					err(1, "lseek");
				if (write(fd, boot + SUN_SIZE,
				    sizeof(boot) - SUN_SIZE) !=
				    sizeof(boot) - SUN_SIZE)
					err(1, "write");
			}
		}
		close(fd);
	}
	exit(0);
}
コード例 #21
0
ファイル: biosdisk.c プロジェクト: Hooman3/minix
static int
read_label(struct biosdisk *d)
{
	struct disklabel dflt_lbl;
	struct mbr_partition mbr[MBR_PART_COUNT];
	struct partition *p;
	uint32_t sector;
	int i;
	int error;
	int typ;
	uint32_t ext_base, this_ext, next_ext;
#ifdef COMPAT_386BSD_MBRPART
	int sector_386bsd = -1;
#endif

	memset(&dflt_lbl, 0, sizeof(dflt_lbl));
	dflt_lbl.d_npartitions = 8;

	d->boff = 0;

	if (d->ll.type != BIOSDISK_TYPE_HD)
		/* No label on floppy and CD */
		return -1;

	/*
	 * find NetBSD Partition in DOS partition table
	 * XXX check magic???
	 */
	ext_base = 0;
	next_ext = 0;
	for (;;) {
		this_ext = ext_base + next_ext;
		next_ext = 0;
		if (readsects(&d->ll, this_ext, 1, d->buf, 0)) {
#ifdef DISK_DEBUG
			printf("error reading MBR sector %u\n", this_ext);
#endif
			return EIO;
		}
		memcpy(&mbr, MBR_PARTS(d->buf), sizeof(mbr));
		/* Look for NetBSD partition ID */
		for (i = 0; i < MBR_PART_COUNT; i++) {
			typ = mbr[i].mbrp_type;
			if (typ == 0)
				continue;
			sector = this_ext + mbr[i].mbrp_start;
#ifdef DISK_DEBUG
			printf("ptn type %d in sector %u\n", typ, sector);
#endif
                        if (typ == MBR_PTYPE_MINIX_14B) {
				if (!read_minix_subp(d, &dflt_lbl,
						   this_ext, sector)) {
					/* Don't add "container" partition */
					continue;
				}
			}
			if (typ == MBR_PTYPE_NETBSD) {
				error = check_label(d, sector);
				if (error >= 0)
					return error;
			}
			if (MBR_IS_EXTENDED(typ)) {
				next_ext = mbr[i].mbrp_start;
				continue;
			}
#ifdef COMPAT_386BSD_MBRPART
			if (this_ext == 0 && typ == MBR_PTYPE_386BSD)
				sector_386bsd = sector;
#endif
			if (this_ext != 0) {
				if (dflt_lbl.d_npartitions >= MAXPARTITIONS)
					continue;
				p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++];
			} else
				p = &dflt_lbl.d_partitions[i];
			p->p_offset = sector;
			p->p_size = mbr[i].mbrp_size;
			p->p_fstype = xlat_mbr_fstype(typ);
		}
		if (next_ext == 0)
			break;
		if (ext_base == 0) {
			ext_base = next_ext;
			next_ext = 0;
		}
	}

	sector = 0;
#ifdef COMPAT_386BSD_MBRPART
	if (sector_386bsd != -1) {
		printf("old BSD partition ID!\n");
		sector = sector_386bsd;
	}
#endif

	/*
	 * One of two things:
	 * 	1. no MBR
	 *	2. no NetBSD partition in MBR
	 *
	 * We simply default to "start of disk" in this case and
	 * press on.
	 */
	error = check_label(d, sector);
	if (error >= 0)
		return error;

	/*
	 * Nothing at start of disk, return info from mbr partitions.
	 */
	/* XXX fill it to make checksum match kernel one */
	dflt_lbl.d_checksum = dkcksum(&dflt_lbl);
	ingest_label(d, &dflt_lbl);
	return 0;
}
コード例 #22
0
void params_read_string(FILE* f, char* name, char* x)
{
    check_label(f, name);
    fscanf(f, "%s", x);
    outlog("%-10s READ NAME=%-10s STRING=%s", "[PARAMS]", name, x);
}