// shouldbuild reports whether we should build this file.
// It applies the same rules that are used with context tags
// in package go/build, except that the GOOS and GOARCH
// can appear anywhere in the file name, not just after _.
// In particular, they can be the entire file name (like windows.c).
// We also allow the special tag cmd_go_bootstrap.
// See ../go/bootstrap.go and package go/build.
static bool
shouldbuild(char *file, char *dir)
{
	char *name, *p;
	int i, j, ret;
	Buf b;
	Vec lines, fields;

	// On Plan 9, most of the libraries are already present.
	// The main exception is libmach which has been modified
	// in various places to support Go object files.
	if(streq(gohostos, "plan9")) {
		if(streq(dir, "lib9")) {
			name = lastelem(file);
			if(streq(name, "goos.c") || streq(name, "flag.c"))
				return 1;
			if(!contains(name, "plan9"))
				return 0;
		}
		if(streq(dir, "libbio"))
			return 0;
	}
	
	// Check file name for GOOS or GOARCH.
	name = lastelem(file);
	for(i=0; i<nelem(okgoos); i++)
		if(contains(name, okgoos[i]) && !streq(okgoos[i], goos))
			return 0;
	for(i=0; i<nelem(okgoarch); i++)
		if(contains(name, okgoarch[i]) && !streq(okgoarch[i], goarch))
			return 0;

	// Omit test files.
	if(contains(name, "_test"))
		return 0;

	// cmd/go/doc.go has a giant /* */ comment before
	// it gets to the important detail that it is not part of
	// package main.  We don't parse those comments,
	// so special case that file.
	if(hassuffix(file, "cmd/go/doc.go") || hassuffix(file, "cmd\\go\\doc.go"))
		return 0;
	if(hassuffix(file, "cmd/cgo/doc.go") || hassuffix(file, "cmd\\cgo\\doc.go"))
		return 0;

	// Check file contents for // +build lines.
	binit(&b);
	vinit(&lines);
	vinit(&fields);

	ret = 1;
	readfile(&b, file);
	splitlines(&lines, bstr(&b));
	for(i=0; i<lines.len; i++) {
		p = lines.p[i];
		while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
			p++;
		if(*p == '\0')
			continue;
		if(contains(p, "package documentation")) {
			ret = 0;
			goto out;
		}
		if(contains(p, "package main") && !streq(dir, "cmd/go") && !streq(dir, "cmd/cgo")) {
			ret = 0;
			goto out;
		}
		if(!hasprefix(p, "//"))
			break;
		if(!contains(p, "+build"))
			continue;
		splitfields(&fields, lines.p[i]);
		if(fields.len < 2 || !streq(fields.p[1], "+build"))
			continue;
		for(j=2; j<fields.len; j++) {
			p = fields.p[j];
			if((*p == '!' && !matchfield(p+1)) || matchfield(p))
				goto fieldmatch;
		}
		ret = 0;
		goto out;
	fieldmatch:;
	}

out:
	bfree(&b);
	vfree(&lines);
	vfree(&fields);

	return ret;
}
Example #2
0
int do_restore_client_burp1(struct asfd *asfd,
                            struct conf *conf, enum action act, int vss_restore)
{
    int ars=0;
    int ret=-1;
    char msg[512]="";
    struct sbuf *sb=NULL;
// Windows needs to have the VSS data written first, and the actual data
// written immediately afterwards. The server is transferring them in two
// chunks. So, leave bfd open after a Windows metadata transfer.
    BFILE bfd;
#ifdef HAVE_WIN32
    binit(&bfd, 0, conf);
#endif

    logp("doing %s\n", act_str(act));

    snprintf(msg, sizeof(msg), "%s %s:%s", act_str(act),
             conf->backup?conf->backup:"", conf->regex?conf->regex:"");
    if(asfd->write_str(asfd, CMD_GEN, msg)
            || asfd->read_expect(asfd, CMD_GEN, "ok"))
        return -1;
    logp("doing %s confirmed\n", act_str(act));

    if(conf->send_client_cntr)
    {
// FIX THIS
//		if(cntr_recv(conf)) goto end;
    }

#if defined(HAVE_WIN32)
    if(act==ACTION_RESTORE) win32_enable_backup_privileges();
#endif

    if(!(sb=sbuf_alloc(conf))) goto end;
    while(1)
    {
        char *fullpath=NULL;

        sbuf_free_content(sb);
        if((ars=sbufl_fill(sb, asfd, NULL, NULL, conf->cntr)))
        {
            if(ars<0) goto end;
            else
            {
                // ars==1 means it ended ok.
                //logp("got %s end\n", act_str(act));
                if(asfd->write_str(asfd,
                                   CMD_GEN, "restoreend ok")) goto end;
            }
            break;
        }

        switch(sb->path.cmd)
        {
        case CMD_DIRECTORY:
        case CMD_FILE:
        case CMD_ENC_FILE:
        case CMD_SOFT_LINK:
        case CMD_HARD_LINK:
        case CMD_SPECIAL:
        case CMD_METADATA:
        case CMD_ENC_METADATA:
        case CMD_VSS:
        case CMD_ENC_VSS:
        case CMD_VSS_T:
        case CMD_ENC_VSS_T:
        case CMD_EFS_FILE:
            if(conf->strip)
            {
                int s;
                s=strip_path_components(asfd, sb,
                                        &(sb->path.buf), conf);
                if(s<0) goto end; // error
                else if(s==0)
                {
                    // Too many components stripped
                    // - carry on.
                    continue;
                }
                // It is OK, sb->path is now stripped.
            }
            if(!(fullpath=prepend_s(conf->restoreprefix,
                                    sb->path.buf)))
            {
                log_and_send_oom(asfd, __func__);
                goto end;
            }
            if(act==ACTION_RESTORE)
            {
                strip_invalid_characters(&fullpath);
                if(!overwrite_ok(sb, conf, &bfd, fullpath))
                {
                    char msg[512]="";
                    // Something exists at that path.
                    snprintf(msg, sizeof(msg),
                             "Path exists: %s", fullpath);
                    if(restore_interrupt(asfd, sb, msg, conf))
                        goto end;
                    else
                    {
                        if(fullpath) free(fullpath);
                        continue;
                    }
                }
            }
            break;
        default:
            break;
        }

        switch(sb->path.cmd)
        {
        case CMD_WARNING:
            cntr_add(conf->cntr, sb->path.cmd, 1);
            printf("\n");
            logp("%s", sb->path);
            break;
        case CMD_DIRECTORY:
            if(restore_dir(asfd, sb, fullpath, act, conf))
                goto end;
            break;
        case CMD_FILE:
        case CMD_VSS_T:
            // Have it a separate statement to the
            // encrypted version so that encrypted and not
            // encrypted files can be restored at the
            // same time.
            if(restore_file_or_get_meta(asfd, &bfd, sb,
                                        fullpath, act,
                                        NULL, NULL, NULL,
                                        vss_restore, conf))
            {
                logp("restore_file error\n");
                goto end;
            }
            break;
        case CMD_ENC_FILE:
        case CMD_ENC_VSS_T:
            if(restore_file_or_get_meta(asfd, &bfd, sb,
                                        fullpath, act,
                                        conf->encryption_password,
                                        NULL, NULL, vss_restore, conf))
            {
                logp("restore_file error\n");
                goto end;
            }
            break;
        case CMD_SOFT_LINK:
        case CMD_HARD_LINK:
            if(restore_link(asfd, sb, fullpath,
                            conf->restoreprefix, act, conf))
                goto end;
            break;
        case CMD_SPECIAL:
            if(restore_special(asfd, sb, fullpath, act, conf))
                goto end;
            break;
        case CMD_METADATA:
        case CMD_VSS:
            if(restore_metadata(asfd, &bfd, sb, fullpath,
                                act, NULL, vss_restore, conf))
                goto end;
            break;
        case CMD_ENC_METADATA:
        case CMD_ENC_VSS:
            if(restore_metadata(asfd, &bfd, sb, fullpath,
                                act, conf->encryption_password,
                                vss_restore, conf))
                goto end;
            break;
        case CMD_EFS_FILE:
            if(restore_file_or_get_meta(asfd, &bfd, sb,
                                        fullpath, act,
                                        NULL, NULL, NULL, vss_restore, conf))
            {
                logp("restore_file error\n");
                goto end;
            }
            break;
        default:
            logp("unknown cmd: %c\n", sb->path.cmd);
            goto end;
            break;
        }

        if(fullpath) free(fullpath);
    }

    ret=0;
end:
    sbuf_free(sb);

#ifdef HAVE_WIN32
    // It is possible for a bfd to still be open.
    bclose(&bfd, asfd);
#endif

    cntr_print_end(conf->cntr);
    cntr_print(conf->cntr, act);

    if(!ret) logp("%s finished\n", act_str(act));
    else logp("ret: %d\n", ret);

    return ret;
}
Example #3
0
void
print(struct termios *tp, struct winsize *wp, int ldisc, enum FMT fmt)
{
	struct cchar *p;
	long tmp;
	u_char *cc;
	int cnt, ispeed, ospeed;
	char buf1[100], buf2[100];

	cnt = 0;

	/* Line discipline. */
	if (ldisc != TTYDISC) {
		switch(ldisc) {
		case SLIPDISC:
			cnt += printf("slip disc; ");
			break;
		case PPPDISC:
			cnt += printf("ppp disc; ");
			break;
		default:
			cnt += printf("#%d disc; ", ldisc);
			break;
		}
	}

	/* Line speed. */
	ispeed = cfgetispeed(tp);
	ospeed = cfgetospeed(tp);
	if (ispeed != ospeed)
		cnt +=
		    printf("ispeed %d baud; ospeed %d baud;", ispeed, ospeed);
	else
		cnt += printf("speed %d baud;", ispeed);
	if (fmt >= BSD)
		cnt += printf(" %d rows; %d columns;", wp->ws_row, wp->ws_col);
	if (cnt)
		printf("\n");

#define	on(f)	((tmp & (f)) != 0)
#define put(n, f, d) \
	if (fmt >= BSD || on(f) != (d)) \
		bput((n) + on(f));

	/* "local" flags */
	tmp = tp->c_lflag;
	binit("lflags");
	put("-icanon", ICANON, 1);
	put("-isig", ISIG, 1);
	put("-iexten", IEXTEN, 1);
	put("-echo", ECHO, 1);
	put("-echoe", ECHOE, 0);
	put("-echok", ECHOK, 0);
	put("-echoke", ECHOKE, 0);
	put("-echonl", ECHONL, 0);
	put("-echoctl", ECHOCTL, 0);
	put("-echoprt", ECHOPRT, 0);
	put("-altwerase", ALTWERASE, 0);
	put("-noflsh", NOFLSH, 0);
	put("-tostop", TOSTOP, 0);
	put("-flusho", FLUSHO, 0);
	put("-pendin", PENDIN, 0);
	put("-nokerninfo", NOKERNINFO, 0);
	put("-extproc", EXTPROC, 0);

	/* input flags */
	tmp = tp->c_iflag;
	binit("iflags");
	put("-istrip", ISTRIP, 0);
	put("-icrnl", ICRNL, 1);
	put("-inlcr", INLCR, 0);
	put("-igncr", IGNCR, 0);
	put("-ixon", IXON, 1);
	put("-ixoff", IXOFF, 0);
	put("-ixany", IXANY, 1);
	put("-imaxbel", IMAXBEL, 1);
	put("-ignbrk", IGNBRK, 0);
	put("-brkint", BRKINT, 1);
	put("-inpck", INPCK, 0);
	put("-ignpar", IGNPAR, 0);
	put("-parmrk", PARMRK, 0);

	/* output flags */
	tmp = tp->c_oflag;
	binit("oflags");
	put("-opost", OPOST, 1);
	put("-onlcr", ONLCR, 1);
	put("-ocrnl", OCRNL, 0);
	put("-oxtabs", OXTABS, 1);
	put("-onocr", OXTABS, 0);
	put("-onlret", OXTABS, 0);

	/* control flags (hardware state) */
	tmp = tp->c_cflag;
	binit("cflags");
	put("-cread", CREAD, 1);
	switch(tmp&CSIZE) {
	case CS5:
		bput("cs5");
		break;
	case CS6:
		bput("cs6");
		break;
	case CS7:
		bput("cs7");
		break;
	case CS8:
		bput("cs8");
		break;
	}
	bput("-parenb" + on(PARENB));
	put("-parodd", PARODD, 0);
	put("-hupcl", HUPCL, 1);
	put("-clocal", CLOCAL, 0);
	put("-cstopb", CSTOPB, 0);
	switch(tmp & (CCTS_OFLOW | CRTS_IFLOW)) {
	case CCTS_OFLOW:
		bput("ctsflow");
		break;
	case CRTS_IFLOW:
		bput("rtsflow");
		break;
	default:
		put("-crtscts", CCTS_OFLOW | CRTS_IFLOW, 0);
		break;
	}
	put("-dsrflow", CDSR_OFLOW, 0);
	put("-dtrflow", CDTR_IFLOW, 0);
	put("-mdmbuf", MDMBUF, 0);	/* XXX mdmbuf ==  dtrflow */

	/* special control characters */
	cc = tp->c_cc;
	if (fmt == POSIX) {
		binit("cchars");
		for (p = cchars1; p->name; ++p) {
			snprintf(buf1, sizeof(buf1), "%s = %s;",
			    p->name, ccval(p, cc[p->sub]));
			bput(buf1);
		}
		binit(NULL);
	} else {
		binit(NULL);
		for (p = cchars1, cnt = 0; p->name; ++p) {
			if (fmt != BSD && cc[p->sub] == p->def)
				continue;
#define	WD	"%-8s"
			snprintf(buf1 + cnt * 8, sizeof(buf1) - cnt * 8,
			    WD, p->name);
			snprintf(buf2 + cnt * 8, sizeof(buf2) - cnt * 8,
			    WD, ccval(p, cc[p->sub]));
			if (++cnt == LINELENGTH / 8) {
				cnt = 0;
				printf("%s\n", buf1);
				printf("%s\n", buf2);
			}
		}
		if (cnt) {
			printf("%s\n", buf1);
			printf("%s\n", buf2);
		}
	}
}
Example #4
0
// init handles initialization of the various global state, like goroot and goarch.
void
init(void)
{
	char *p;
	int i;
	Buf b;

	binit(&b);

	xgetenv(&b, "GOROOT");
	if(b.len > 0) {
		// if not "/", then strip trailing path separator
		if(b.len >= 2 && b.p[b.len - 1] == slash[0])
			b.len--;
		goroot = btake(&b);
	}

	xgetenv(&b, "GOBIN");
	if(b.len == 0)
		bprintf(&b, "%s%sbin", goroot, slash);
	gobin = btake(&b);

	xgetenv(&b, "GOOS");
	if(b.len == 0)
		bwritestr(&b, gohostos);
	goos = btake(&b);
	if(find(goos, okgoos, nelem(okgoos)) < 0)
		fatal("unknown $GOOS %s", goos);

	p = bpathf(&b, "%s/include/u.h", goroot);
	if(!isfile(p)) {
		fatal("$GOROOT is not set correctly or not exported\n"
			"\tGOROOT=%s\n"
			"\t%s does not exist", goroot, p);
	}

	xgetenv(&b, "GOHOSTARCH");
	if(b.len > 0)
		gohostarch = btake(&b);

	i = find(gohostarch, okgoarch, nelem(okgoarch));
	if(i < 0)
		fatal("unknown $GOHOSTARCH %s", gohostarch);
	bprintf(&b, "%c", gochars[i]);
	gohostchar = btake(&b);

	xgetenv(&b, "GOARCH");
	if(b.len == 0)
		bwritestr(&b, gohostarch);
	goarch = btake(&b);
	i = find(goarch, okgoarch, nelem(okgoarch));
	if(i < 0)
		fatal("unknown $GOARCH %s", goarch);
	bprintf(&b, "%c", gochars[i]);
	gochar = btake(&b);

	xsetenv("GOROOT", goroot);
	xsetenv("GOARCH", goarch);
	xsetenv("GOOS", goos);

	// Make the environment more predictable.
	xsetenv("LANG", "C");
	xsetenv("LANGUAGE", "en_US.UTF8");

	goversion = findgoversion();

	workdir = xworkdir();
	xatexit(rmworkdir);

	bpathf(&b, "%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch);
	tooldir = btake(&b);

	bfree(&b);
}
Example #5
0
/*
 * Initialization code.
 * Called from cold start routine as
 * soon as a stack and segmentation
 * have been established.
 * Functions:
 *  clear and free user core
 *  turn on clock
 *  hand craft 0th process
 *  call all initialization routines
 *  fork - process 0 to schedule
 *       - process 1 execute bootstrap
 */
int
main()
{
    register struct proc *p;
    register int i;
    register struct fs *fs = NULL;
    char inbuf[4];
    char inch;
    int s __attribute__((unused));

    startup();
    printf ("\n%s", version);
    cpuidentify();
    cnidentify();

    /*
     * Set up system process 0 (swapper).
     */
    p = &proc[0];
    p->p_addr = (size_t) &u;
    p->p_stat = SRUN;
    p->p_flag |= SLOAD | SSYS;
    p->p_nice = NZERO;

    u.u_procp = p;          /* init user structure */
    u.u_cmask = CMASK;
    u.u_lastfile = -1;
    for (i = 1; i < NGROUPS; i++)
        u.u_groups[i] = NOGROUP;
    for (i = 0; i < sizeof(u.u_rlimit)/sizeof(u.u_rlimit[0]); i++)
        u.u_rlimit[i].rlim_cur = u.u_rlimit[i].rlim_max =
            RLIM_INFINITY;

    /* Initialize signal state for process 0 */
    siginit (p);

    /*
     * Initialize tables, protocols, and set up well-known inodes.
     */
#ifdef LOG_ENABLED
    loginit();
#endif
    coutinit();
    cinit();
    pqinit();
    ihinit();
    bhinit();
    binit();
    nchinit();
    clkstart();
    s = spl0();
    rdisk_init();

    pipedev = rootdev = get_boot_device();
    swapdev = get_swap_device();

    /* Mount a root filesystem. */
    for (;;) {
        if(rootdev!=-1)
        {
            fs = mountfs (rootdev, (boothowto & RB_RDONLY) ? MNT_RDONLY : 0,
                (struct inode*) 0);
        }
        if (fs)
            break;
        printf ("No root filesystem available!\n");
//      rdisk_list_partitions(RDISK_FS);
retry:
        printf ("Please enter device to boot from (press ? to list): ");
        inch=0;
        inbuf[0] = inbuf[1] = inbuf[2] = inbuf[3] = 0;
        while((inch=cngetc()) != '\r')
        {
            switch(inch)
            {
                case '?':
                    printf("?\n");
                    rdisk_list_partitions(RDISK_FS);
                    printf ("Please enter device to boot from (press ? to list): ");
                    break;
                default:
                    printf("%c",inch);
                    inbuf[0] = inbuf[1];
                    inbuf[1] = inbuf[2];
                    inbuf[2] = inbuf[3];
                    inbuf[3] = inch;
                    break;
            }
        }

        inch = 0;
        if(inbuf[0]=='r' && inbuf[1]=='d')
        {
            if(inbuf[2]>='0' && inbuf[2] < '0'+rdisk_num_disks())
            {
                if(inbuf[3]>='a' && inbuf[3]<='d')
                {
                    rootdev=makedev(inbuf[2]-'0',inbuf[3]-'a'+1);
                    inch = 1;
                }
            }
        } else if(inbuf[1]=='r' && inbuf[2]=='d') {
            if(inbuf[3]>='0' && inbuf[3] < '0'+rdisk_num_disks())
            {
                rootdev=makedev(inbuf[3]-'0',0);
                inch = 1;
            }
        } else if(inbuf[3] == 0) {
            inch = 1;
        }
        if(inch==0)
        {
            printf("\nUnknown device.\n\n");
            goto retry;
        }
        printf ("\n\n");
    }
    printf ("phys mem  = %u kbytes\n", physmem / 1024);
    printf ("user mem  = %u kbytes\n", MAXMEM / 1024);
    if(minor(rootdev)==0)
    {
        printf ("root dev  = rd%d (%d,%d)\n",
            major(rootdev),
            major(rootdev), minor(rootdev)
        );
    } else {
        printf ("root dev  = rd%d%c (%d,%d)\n",
            major(rootdev), 'a'+minor(rootdev)-1,
            major(rootdev), minor(rootdev)
        );
    }

    printf ("root size = %u kbytes\n", fs->fs_fsize * DEV_BSIZE / 1024);
    mount[0].m_inodp = (struct inode*) 1;   /* XXX */
    mount_updname (fs, "/", "root", 1, 4);
    time.tv_sec = fs->fs_time;
    boottime = time;

    /* Find a swap file. */
    swapstart = 1;
    while(swapdev == -1)
    {
        printf("Please enter swap device (press ? to list): ");
        inbuf[0] = inbuf[1] = inbuf[2] = inbuf[3] = 0;
        while((inch = cngetc())!='\r')
        {
            switch(inch)
            {
                case '?':
                    printf("?\n");
                    rdisk_list_partitions(RDISK_SWAP);
                    printf("Please enter swap device (press ? to list): ");
                    break;
                default:
                    printf("%c",inch);
                    inbuf[0] = inbuf[1];
                    inbuf[1] = inbuf[2];
                    inbuf[2] = inbuf[3];
                    inbuf[3] = inch;
                    break;
            }
        }
        inch = 0;
        if(inbuf[0]=='r' && inbuf[1]=='d')
        {
            if(inbuf[2]>='0' && inbuf[2] < '0'+rdisk_num_disks())
            {
                if(inbuf[3]>='a' && inbuf[3]<='d')
                {
                    swapdev=makedev(inbuf[2]-'0',inbuf[3]-'a'+1);
                    inch = 1;
                }
            }
        } else if(inbuf[1]=='r' && inbuf[2]=='d') {
            if(inbuf[3]>='0' && inbuf[3] < '0'+rdisk_num_disks())
            {
                swapdev=makedev(inbuf[3]-'0',0);
                inch = 1;
            }
        }

        if(minor(swapdev)!=0)
        {
            if(partition_type(swapdev)!=RDISK_SWAP)
            {
                printf("\nNot a swap partition!\n\n");
                swapdev=-1;
            }
        }
    }
    nswap = rdsize(swapdev);

    if(minor(swapdev)==0)
    {
        printf ("swap dev  = rd%d (%d,%d)\n",
            major(swapdev),
            major(swapdev), minor(swapdev)
        );
    } else {
        printf ("swap dev  = rd%d%c (%d,%d)\n",
            major(swapdev), 'a'+minor(swapdev)-1,
            major(swapdev), minor(swapdev)
        );
    }
    (*bdevsw[major(swapdev)].d_open)(swapdev, FREAD|FWRITE, S_IFBLK);
    printf ("swap size = %u kbytes\n", nswap * DEV_BSIZE / 1024);
    if (nswap <= 0)
        panic ("zero swap size");   /* don't want to panic, but what ? */
    mfree (swapmap, nswap, swapstart);

    /* Kick off timeout driven events by calling first time. */
    schedcpu (0);

    /* Set up the root file system. */
    rootdir = iget (rootdev, &mount[0].m_filsys, (ino_t) ROOTINO);
    iunlock (rootdir);
    u.u_cdir = iget (rootdev, &mount[0].m_filsys, (ino_t) ROOTINO);
    iunlock (u.u_cdir);
    u.u_rdir = NULL;

    /*
     * Make init process.
     */
    if (newproc (0) == 0) {
        /* Parent process with pid 0: swapper.
         * No return from sched. */
        sched();
    }
    /* Child process with pid 1: init. */
    s = splhigh();
    p = u.u_procp;
    p->p_dsize = icodeend - icode;
    p->p_daddr = USER_DATA_START;
    p->p_ssize = 1024;              /* one kbyte of stack */
    p->p_saddr = USER_DATA_END - 1024;
    bcopy ((caddr_t) icode, (caddr_t) USER_DATA_START, icodeend - icode);
    /*
     * return goes to location 0 of user init code
     * just copied out.
     */
    return 0;
}
// setup sets up the tree for the initial build.
static void
setup(void)
{
	int i;
	Buf b;
	char *p;

	binit(&b);

	// Create bin directory.
	p = bpathf(&b, "%s/bin", goroot);
	if(!isdir(p))
		xmkdir(p);

	// Create package directory.
	p = bpathf(&b, "%s/pkg", goroot);
	if(!isdir(p))
		xmkdir(p);
	p = bpathf(&b, "%s/pkg/%s_%s", goroot, gohostos, gohostarch);
	if(rebuildall)
		xremoveall(p);
	xmkdirall(p);
	if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
		p = bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch);
		if(rebuildall)
			xremoveall(p);
		xmkdirall(p);
	}

	// Create object directory.
	// We keep it in pkg/ so that all the generated binaries
	// are in one tree.  If pkg/obj/libgc.a exists, it is a dreg from
	// before we used subdirectories of obj.  Delete all of obj
	// to clean up.
	bpathf(&b, "%s/pkg/obj/libgc.a", goroot);
	if(isfile(bstr(&b)))
		xremoveall(bpathf(&b, "%s/pkg/obj", goroot));
	p = bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch);
	if(rebuildall)
		xremoveall(p);
	xmkdirall(p);

	// Create tool directory.
	// We keep it in pkg/, just like the object directory above.
	if(rebuildall)
		xremoveall(tooldir);
	xmkdirall(tooldir);

	// Remove tool binaries from before the tool/gohostos_gohostarch
	xremoveall(bpathf(&b, "%s/bin/tool", goroot));

	// Remove old pre-tool binaries.
	for(i=0; i<nelem(oldtool); i++)
		xremove(bpathf(&b, "%s/bin/%s", goroot, oldtool[i]));

	// If $GOBIN is set and has a Go compiler, it must be cleaned.
	for(i=0; gochars[i]; i++) {
		if(isfile(bprintf(&b, "%s%s%c%s", gobin, slash, gochars[i], "g"))) {
			for(i=0; i<nelem(oldtool); i++)
				xremove(bprintf(&b, "%s%s%s", gobin, slash, oldtool[i]));
			break;
		}
	}

	// For release, make sure excluded things are excluded.
	if(hasprefix(goversion, "release.") || hasprefix(goversion, "go")) {
		for(i=0; i<nelem(unreleased); i++)
			if(isdir(bpathf(&b, "%s/%s", goroot, unreleased[i])))
				fatal("%s should not exist in release build", bstr(&b));
	}

	bfree(&b);
}
Example #7
0
File: buildgc.c Project: 8l/go
// mkanames reads [5689].out.h and writes anames[5689].c
// The format is much the same as the Go opcodes above.
// It also writes out cnames array for C_* constants and the dnames
// array for D_* constants.
void
mkanames(char *dir, char *file)
{
	int i, j, ch, n, unknown;
	Buf in, b, out, out2;
	Vec lines;
	char *p, *p2;
	Vec dnames[128];

	binit(&b);
	binit(&in);
	binit(&out);
	binit(&out2);
	vinit(&lines);
	for(i=0; i<nelem(dnames); i++)
		vinit(&dnames[i]);

	ch = file[xstrlen(file)-3];
	bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
	readfile(&in, bstr(&b));
	splitlines(&lines, bstr(&in));
	
	// Include link.h so that the extern declaration there is
	// checked against the non-extern declaration we are generating.
	bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
	bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
	bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
	bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
	bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
	bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
	bwritestr(&out, bprintf(&b, "\n"));

	bwritestr(&out, bprintf(&b, "char*	anames%c[] = {\n", ch));
	for(i=0; i<lines.len; i++) {
		if(hasprefix(lines.p[i], "\tA")) {
			p = xstrstr(lines.p[i], ",");
			if(p)
				*p = '\0';
			p = xstrstr(lines.p[i], "\n");
			if(p)
				*p = '\0';
			p = lines.p[i] + 2;
			bwritestr(&out, bprintf(&b, "\t\"%s\",\n", p));
		}
	}
	bwritestr(&out, "};\n");

	j=0;
	bprintf(&out2, "char*	cnames%c[] = {\n", ch);
	for(i=0; i<lines.len; i++) {
		if(hasprefix(lines.p[i], "\tC_")) {
			p = xstrstr(lines.p[i], ",");
			if(p)
				*p = '\0';
			p = xstrstr(lines.p[i], "\n");
			if(p)
				*p = '\0';
			p = lines.p[i] + 3;
			bwritestr(&out2, bprintf(&b, "\t\"%s\",\n", p));
			j++;
		}
	}
	bwritestr(&out2, "};\n");
	if(j>0)
		bwriteb(&out, &out2);

	j=unknown=0;
	n=-1;
	for(i=0; i<lines.len; i++) {
		if(hasprefix(lines.p[i], "\tD_")) {
			p = xstrstr(lines.p[i], ",");
			if(p)
				*p = '\0';
			p = xstrstr(lines.p[i], "\n");
			if(p)
				*p = '\0';

			// Parse explicit value, if any
			p = xstrstr(lines.p[i], "=");
			if(p) {
				// Skip space after '='
				p2 = p + 1;
				while(*p2 == ' ' || *p2 == '\t')
					p2++;
				n = xatoi(p2, &p2);
				// We can't do anything about
				// non-numeric values or anything that
				// follows
				while(*p2 == ' ' || *p2 == '\t')
					p2++;
				if(*p2 != 0) {
					unknown = 1;
					continue;
				}
				// Truncate space before '='
				while(*(p-1) == ' ' || *(p-1) == '\t')
					p--;
				*p = '\0';
				unknown = 0;
			} else {
				n++;
			}

			if(unknown || n >= nelem(dnames))
				continue;

			p = lines.p[i] + 3;
			if(xstrcmp(p, "LAST") == 0)
				continue;
			vadd(&dnames[n], p);
			j++;
		}
	}
	if(j>0){
		bwritestr(&out, bprintf(&b, "char*	dnames%c[D_LAST] = {\n", ch));
		for(i=0; i<nelem(dnames); i++) {
			if(dnames[i].len == 0)
				continue;
			bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
			for(j=0; j<dnames[i].len; j++) {
				if(j != 0)
					bwritestr(&out, "/");
				bwritestr(&out, dnames[i].p[j]);
			}
			bwritestr(&out, "\",\n");
		}
		bwritestr(&out, "};\n");
	}

	writefile(&out, file, 0);

	bfree(&b);
	bfree(&in);
	bfree(&out);
	bfree(&out2);
	vfree(&lines);
	for(i=0; i<nelem(dnames); i++)
		vfree(&dnames[i]);
}
Example #8
0
// Bootstrap processor starts running C code here.
// Allocate a real stack and switch to it, first
// doing some setup required for memory allocator to work.
int
main(void)
{
	monitor_clear();
	xylos_logo();

	kinit1(end, P2V(4 * 1024 * 1024)); // phys page allocator, 16MB for kernel
	kvmalloc();      // kernel page table
	mpinit();        // collect info about this machine
	lapicinit();
	seginit();       // set up segments

	cprintf("Initializing interrupts...             ");
	init_generic_irq_table();
	picinit();       // interrupt controller
	ioapicinit();    // another interrupt controller
	cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");

	cprintf("Initializing console and serial...     ");
	consoleinit();   // I/O devices & their interrupts
	uartinit();      // serial port
	cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");

	cprintf("Setting up swap space disk...          ");
	swapinit();
	cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");

	cprintf("Initializing tasking...                ");
	pinit();         // process table
	tvinit();        // trap vectors
	binit();         // buffer cache
	cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");

	cprintf("Initializing pipe IPC...               ");
	init_pipe_ipc_system();
	if(pipe_ipc_sanitycheck() == 0) {
		cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");
	}

	cprintf("Initializing direct IPC...             ");
	init_direct_ipc_table();
	if(direct_ipc_sanitycheck() == 0) {
		cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");
	}

	cprintf("Mounting root filesystem...            ");
	fileinit();      // file table
	ideinit();       // disk
	cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");

	if(!ismp) {
		cprintf("Starting up uniprocessor CPU...        ");
		timerinit();   // uniprocessor timer
		cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");
	}

	if(ismp) {
		if(ncpu > 1) {
			cprintf("Starting up %d CPU cores...             ", ncpu);
		} else {
			cprintf("Starting up %d CPU core...              ", ncpu);
		}
	}

	startothers();   // start other processors
	kinit2(P2V(4 * 1024 * 1024), P2V(PHYSTOP)); // 16MB to PHYSTOP [234MB]

	if(ismp) {
		cprintf_color(COLOR_BLACK, COLOR_LIGHT_GREEN, false, "done\n");
	}

	// detects and starts km drivers
	auto_enable_nic();

	// first user process
	userinit();

	// Finish setting up this processor in mpmain.
	mpmain();


}
Example #9
0
File: build.c Project: Isor/golang
// shouldbuild reports whether we should build this file.
// It applies the same rules that are used with context tags
// in package go/build, except that the GOOS and GOARCH
// can appear anywhere in the file name, not just after _.
// In particular, they can be the entire file name (like windows.c).
// We also allow the special tag cmd_go_bootstrap.
// See ../go/bootstrap.go and package go/build.
static bool
shouldbuild(char *file, char *dir)
{
	char *name, *p;
	int i, j, ret;
	Buf b;
	Vec lines, fields;
	
	// Check file name for GOOS or GOARCH.
	name = lastelem(file);
	for(i=0; i<nelem(okgoos); i++) {
		if(streq(okgoos[i], goos))
			continue;
		p = xstrstr(name, okgoos[i]);
		if(p == nil)
			continue;
		p += xstrlen(okgoos[i]);
		if(*p == '.' || *p == '_' || *p == '\0')
			return 0;
	}
	for(i=0; i<nelem(okgoarch); i++) {
		if(streq(okgoarch[i], goarch))
			continue;
		p = xstrstr(name, okgoarch[i]);
		if(p == nil)
			continue;
		p += xstrlen(okgoarch[i]);
		if(*p == '.' || *p == '_' || *p == '\0')
			return 0;
	}

	// Omit test files.
	if(contains(name, "_test"))
		return 0;

	// cmd/go/doc.go has a giant /* */ comment before
	// it gets to the important detail that it is not part of
	// package main.  We don't parse those comments,
	// so special case that file.
	if(hassuffix(file, "cmd/go/doc.go") || hassuffix(file, "cmd\\go\\doc.go"))
		return 0;
	if(hassuffix(file, "cmd/cgo/doc.go") || hassuffix(file, "cmd\\cgo\\doc.go"))
		return 0;

	// Check file contents for // +build lines.
	binit(&b);
	vinit(&lines);
	vinit(&fields);

	ret = 1;
	readfile(&b, file);
	splitlines(&lines, bstr(&b));
	for(i=0; i<lines.len; i++) {
		p = lines.p[i];
		while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
			p++;
		if(*p == '\0')
			continue;
		if(contains(p, "package documentation")) {
			ret = 0;
			goto out;
		}
		if(contains(p, "package main") && !streq(dir, "cmd/go") && !streq(dir, "cmd/cgo")) {
			ret = 0;
			goto out;
		}
		if(!hasprefix(p, "//"))
			break;
		if(!contains(p, "+build"))
			continue;
		splitfields(&fields, lines.p[i]);
		if(fields.len < 2 || !streq(fields.p[1], "+build"))
			continue;
		for(j=2; j<fields.len; j++) {
			p = fields.p[j];
			if((*p == '!' && !matchfield(p+1)) || matchfield(p))
				goto fieldmatch;
		}
		ret = 0;
		goto out;
	fieldmatch:;
	}

out:
	bfree(&b);
	vfree(&lines);
	vfree(&fields);

	return ret;
}
Example #10
0
// mkzasm writes zasm_$GOOS_$GOARCH.h,
// which contains struct offsets for use by
// assembly files.  It also writes a copy to the work space
// under the name zasm_GOOS_GOARCH.h (no expansion).
// 
void
mkzasm(char *dir, char *file)
{
	int i, n;
	char *aggr, *p;
	Buf in, b, out;
	Vec argv, lines, fields;

	binit(&in);
	binit(&b);
	binit(&out);
	vinit(&argv);
	vinit(&lines);
	vinit(&fields);
	
	bwritestr(&out, "// auto generated by go tool dist\n\n");
	for(i=0; i<nelem(zasmhdr); i++) {
		if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
			bwritestr(&out, zasmhdr[i].hdr);
			goto ok;
		}
	}
	fatal("unknown $GOOS/$GOARCH in mkzasm");
ok:

	// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c
	// to get acid [sic] output.
	vreset(&argv);
	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
	vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
	vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
	vadd(&argv, bprintf(&b, "-I%s", workdir));
	vadd(&argv, "-a");
	vadd(&argv, "proc.c");
	runv(&in, dir, CheckExit, &argv);
	
	// Convert input like
	//	aggr G
	//	{
	//		Gobuf 24 sched;
	//		'Y' 48 stack0;
	//	}
	// into output like
	//	#define g_sched 24
	//	#define g_stack0 48
	//
	aggr = nil;
	splitlines(&lines, bstr(&in));
	for(i=0; i<lines.len; i++) {
		splitfields(&fields, lines.p[i]);
		if(fields.len == 2 && streq(fields.p[0], "aggr")) {
			if(streq(fields.p[1], "G"))
				aggr = "g";
			else if(streq(fields.p[1], "M"))
				aggr = "m";
			else if(streq(fields.p[1], "Gobuf"))
				aggr = "gobuf";
			else if(streq(fields.p[1], "WinCall"))
				aggr = "wincall";
		}
		if(hasprefix(lines.p[i], "}"))
			aggr = nil;
		if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) {
			n = fields.len;
			p = fields.p[n-1];
			if(p[xstrlen(p)-1] == ';')
				p[xstrlen(p)-1] = '\0';
			bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2]));
		}
	}
	
	// Write both to file and to workdir/zasm_GOOS_GOARCH.h.
	writefile(&out, file, 0);
	writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0);

	bfree(&in);
	bfree(&b);
	bfree(&out);
	vfree(&argv);
	vfree(&lines);
	vfree(&fields);
}
Example #11
0
// mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
// which contains Go struct definitions equivalent to the C ones.
// Mostly we just write the output of 6c -q to the file.
// However, we run it on multiple files, so we have to delete
// the duplicated definitions, and we don't care about the funcs
// and consts, so we delete those too.
// 
void
mkzruntimedefs(char *dir, char *file)
{
	int i, skip;
	char *p;
	Buf in, b, out;
	Vec argv, lines, fields, seen;
	
	binit(&in);
	binit(&b);
	binit(&out);
	vinit(&argv);
	vinit(&lines);
	vinit(&fields);
	vinit(&seen);
	
	bwritestr(&out, "// auto generated by go tool dist\n"
		"\n"
		"package runtime\n"
		"import \"unsafe\"\n"
		"var _ unsafe.Pointer\n"
		"\n"
	);

	
	// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q
	// on each of the runtimedefs C files.
	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
	vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
	vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
	vadd(&argv, bprintf(&b, "-I%s", workdir));
	vadd(&argv, "-q");
	vadd(&argv, "");
	p = argv.p[argv.len-1];
	for(i=0; i<nelem(runtimedefs); i++) {
		argv.p[argv.len-1] = runtimedefs[i];
		runv(&b, dir, CheckExit, &argv);
		bwriteb(&in, &b);
	}
	argv.p[argv.len-1] = p;
		
	// Process the aggregate output.
	skip = 0;
	splitlines(&lines, bstr(&in));
	for(i=0; i<lines.len; i++) {
		p = lines.p[i];
		// Drop comment, func, and const lines.
		if(hasprefix(p, "//") || hasprefix(p, "const") || hasprefix(p, "func"))
			continue;
		
		// Note beginning of type or var decl, which can be multiline.
		// Remove duplicates.  The linear check of seen here makes the
		// whole processing quadratic in aggregate, but there are only
		// about 100 declarations, so this is okay (and simple).
		if(hasprefix(p, "type ") || hasprefix(p, "var ")) {
			splitfields(&fields, p);
			if(fields.len < 2)
				continue;
			if(find(fields.p[1], seen.p, seen.len) >= 0) {
				if(streq(fields.p[fields.len-1], "{"))
					skip = 1;  // skip until }
				continue;
			}
			vadd(&seen, fields.p[1]);
		}
		if(skip) {
			if(hasprefix(p, "}"))
				skip = 0;
			continue;
		}
		
		bwritestr(&out, p);
	}
	
	writefile(&out, file, 0);

	bfree(&in);
	bfree(&b);
	bfree(&out);
	vfree(&argv);
	vfree(&lines);
	vfree(&fields);
	vfree(&seen);
}
Example #12
0
// mkzasm writes zasm_$GOOS_$GOARCH.h,
// which contains struct offsets for use by
// assembly files.  It also writes a copy to the work space
// under the name zasm_GOOS_GOARCH.h (no expansion).
// 
void
mkzasm(char *dir, char *file)
{
	int i, n;
	char *aggr, *p;
	Buf in, b, out, exp;
	Vec argv, lines, fields;

	binit(&in);
	binit(&b);
	binit(&out);
	binit(&exp);
	vinit(&argv);
	vinit(&lines);
	vinit(&fields);
	
	bwritestr(&out, "// auto generated by go tool dist\n\n");
	for(i=0; i<nelem(zasmhdr); i++) {
		if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
			bwritestr(&out, zasmhdr[i].hdr);
			goto ok;
		}
	}
	fatal("unknown $GOOS/$GOARCH in mkzasm");
ok:

	// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
	// to get acid [sic] output.
	vreset(&argv);
	vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
	vadd(&argv, "-D");
	vadd(&argv, bprintf(&b, "GOOS_%s", goos));
	vadd(&argv, "-D");
	vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
	vadd(&argv, "-I");
	vadd(&argv, bprintf(&b, "%s", workdir));
	vadd(&argv, "-a");
	vadd(&argv, "-n");
	vadd(&argv, "-o");
	vadd(&argv, bpathf(&b, "%s/proc.acid", workdir));
	vadd(&argv, "proc.c");
	runv(nil, dir, CheckExit, &argv);
	readfile(&in, bpathf(&b, "%s/proc.acid", workdir));
	
	// Convert input like
	//	aggr G
	//	{
	//		Gobuf 24 sched;
	//		'Y' 48 stack0;
	//	}
	//	StackMin = 128;
	// into output like
	//	#define g_sched 24
	//	#define g_stack0 48
	//	#define const_StackMin 128
	aggr = nil;
	splitlines(&lines, bstr(&in));
	for(i=0; i<lines.len; i++) {
		splitfields(&fields, lines.p[i]);
		if(fields.len == 2 && streq(fields.p[0], "aggr")) {
			if(streq(fields.p[1], "G"))
				aggr = "g";
			else if(streq(fields.p[1], "M"))
				aggr = "m";
			else if(streq(fields.p[1], "P"))
				aggr = "p";
			else if(streq(fields.p[1], "Gobuf"))
				aggr = "gobuf";
			else if(streq(fields.p[1], "LibCall"))
				aggr = "libcall";
			else if(streq(fields.p[1], "WinCallbackContext"))
				aggr = "cbctxt";
			else if(streq(fields.p[1], "SEH"))
				aggr = "seh";
		}
		if(hasprefix(lines.p[i], "}"))
			aggr = nil;
		if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) {
			n = fields.len;
			p = fields.p[n-1];
			if(p[xstrlen(p)-1] == ';')
				p[xstrlen(p)-1] = '\0';
			bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2]));
		}
		if(fields.len == 3 && streq(fields.p[1], "=")) { // generated from enumerated constants
			p = fields.p[2];
			if(p[xstrlen(p)-1] == ';')
				p[xstrlen(p)-1] = '\0';
			bwritestr(&out, bprintf(&b, "#define const_%s %s\n", fields.p[0], p));
		}
	}

	// Some #defines that are used for .c files.
	if(streq(goos, "windows")) {
		bwritestr(&out, bprintf(&b, "#define cb_max %d\n", MAXWINCB));
	}
	
	xgetenv(&exp, "GOEXPERIMENT");
	bwritestr(&out, bprintf(&b, "#define GOEXPERIMENT \"%s\"\n", bstr(&exp)));
	
	// Write both to file and to workdir/zasm_GOOS_GOARCH.h.
	writefile(&out, file, 0);
	writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0);

	bfree(&in);
	bfree(&b);
	bfree(&out);
	bfree(&exp);
	vfree(&argv);
	vfree(&lines);
	vfree(&fields);
}
Example #13
0
File: plan9.c Project: hfeeki/go
// genrun is the generic run implementation.
static void
genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
{
	int i, p[2], pid;
	Buf b1, cmd;
	char *q;

	while(nbg >= maxnbg)
		bgwait1();

	binit(&b1);
	binit(&cmd);

	if(!isabs(argv->p[0])) {
		bpathf(&b1, "/bin/%s", argv->p[0]);
		free(argv->p[0]);
		argv->p[0] = xstrdup(bstr(&b1));
	}

	// Generate a copy of the command to show in a log.
	// Substitute $WORK for the work directory.
	for(i=0; i<argv->len; i++) {
		if(i > 0)
			bwritestr(&cmd, " ");
		q = argv->p[i];
		if(workdir != nil && hasprefix(q, workdir)) {
			bwritestr(&cmd, "$WORK");
			q += strlen(workdir);
		}
		bwritestr(&cmd, q);
	}
	if(vflag > 1)
		errprintf("%s\n", bstr(&cmd));

	if(b != nil) {
		breset(b);
		if(pipe(p) < 0)
			fatal("pipe");
	}

	switch(pid = fork()) {
	case -1:
		fatal("fork");
	case 0:
		if(b != nil) {
			close(0);
			close(p[0]);
			dup(p[1], 1);
			dup(p[1], 2);
			if(p[1] > 2)
				close(p[1]);
		}
		if(dir != nil) {
			if(chdir(dir) < 0) {
				fprint(2, "chdir: %r\n");
				_exits("chdir");
			}
		}
		vadd(argv, nil);
		exec(argv->p[0], argv->p);
		fprint(2, "%s\n", bstr(&cmd));
		fprint(2, "exec: %r\n");
		_exits("exec");
	}
	if(b != nil) {
		close(p[1]);
		breadfrom(b, p[0]);
		close(p[0]);
	}

	if(nbg < 0)
		fatal("bad bookkeeping");
	bg[nbg].pid = pid;
	bg[nbg].mode = mode;
	bg[nbg].cmd = btake(&cmd);
	bg[nbg].b = b;
	nbg++;
	
	if(wait)
		bgwait();

	bfree(&cmd);
	bfree(&b1);
}
Example #14
0
int main (int argc, char *argv[])
{
   int ch;
   FILE *fd;
   char line[1000];
   bool got_inc = false;

   setlocale(LC_ALL, "");
   bindtextdomain("bareos", LOCALEDIR);
   textdomain("bareos");
   init_stack_dump();
   lmgr_init_thread();

   working_directory = "/tmp";
   my_name_is(argc, argv, "bextract");
   init_msg(NULL, NULL);              /* setup message handler */

   OSDependentInit();

   ff = init_find_files();
   binit(&bfd);

   while ((ch = getopt(argc, argv, "b:c:D:d:e:i:pvV:?")) != -1) {
      switch (ch) {
      case 'b':                    /* bootstrap file */
         bsr = parse_bsr(NULL, optarg);
//       dump_bsr(bsr, true);
         break;

      case 'c':                    /* specify config file */
         if (configfile != NULL) {
            free(configfile);
         }
         configfile = bstrdup(optarg);
         break;

      case 'D':                    /* specify director name */
         if (DirectorName != NULL) {
            free(DirectorName);
         }
         DirectorName = bstrdup(optarg);
         break;

      case 'd':                    /* debug level */
         if (*optarg == 't') {
            dbg_timestamp = true;
         } else {
            debug_level = atoi(optarg);
            if (debug_level <= 0) {
               debug_level = 1;
            }
         }
         break;

      case 'e':                    /* exclude list */
         if ((fd = fopen(optarg, "rb")) == NULL) {
            berrno be;
            Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"),
               optarg, be.bstrerror());
            exit(1);
         }
         while (fgets(line, sizeof(line), fd) != NULL) {
            strip_trailing_junk(line);
            Dmsg1(900, "add_exclude %s\n", line);
            add_fname_to_exclude_list(ff, line);
         }
         fclose(fd);
         break;

      case 'i':                    /* include list */
         if ((fd = fopen(optarg, "rb")) == NULL) {
            berrno be;
            Pmsg2(0, _("Could not open include file: %s, ERR=%s\n"),
               optarg, be.bstrerror());
            exit(1);
         }
         while (fgets(line, sizeof(line), fd) != NULL) {
            strip_trailing_junk(line);
            Dmsg1(900, "add_include %s\n", line);
            add_fname_to_include_list(ff, 0, line);
         }
         fclose(fd);
         got_inc = true;
         break;

      case 'p':
         forge_on = true;
         break;

      case 'v':
         verbose++;
         break;

      case 'V':                    /* Volume name */
         VolumeName = optarg;
         break;

      case '?':
      default:
         usage();

      } /* end switch */
   } /* end while */
   argc -= optind;
   argv += optind;

   if (argc != 2) {
      Pmsg0(0, _("Wrong number of arguments. Make sure the last two parameters are <bareos-archive-device-name> <directory-to-store-files>\n"));
      usage();
   }

   if (configfile == NULL) {
      configfile = bstrdup(CONFIG_FILE);
   }

   my_config = new_config_parser();
   parse_sd_config(my_config, configfile, M_ERROR_TERM);

   if (DirectorName) {
      foreach_res(director, R_DIRECTOR) {
         if (bstrcmp(director->hdr.name, DirectorName)) {
            break;
         }
      }
      if (!director) {
         Emsg2(M_ERROR_TERM, 0, _("No Director resource named %s defined in %s. Cannot continue.\n"),
               DirectorName, configfile);
      }
   }

   load_sd_plugins(me->plugin_directory, me->plugin_names);

   read_crypto_cache(me->working_directory, "bareos-sd",
                     get_first_port_host_order(me->SDaddrs));

   if (!got_inc) {                            /* If no include file, */
      add_fname_to_include_list(ff, 0, "/");  /*   include everything */
   }

   where = argv[1];
   do_extract(argv[0]);

   if (bsr) {
      free_bsr(bsr);
   }
   if (prog_name_msg) {
      Pmsg1(000, _("%d Program Name and/or Program Data Stream records ignored.\n"),
         prog_name_msg);
   }
   if (win32_data_msg) {
      Pmsg1(000, _("%d Win32 data or Win32 gzip data stream records. Ignored.\n"),
         win32_data_msg);
   }
   term_include_exclude_files(ff);
   term_find_files(ff);
   return 0;
}
Example #15
0
// The bootstrap command runs a build from scratch,
// stopping at having installed the go_bootstrap command.
void
cmdbootstrap(int argc, char **argv)
{
	int i;
	Buf b;
	char *oldgoos, *oldgoarch, *oldgochar;

	binit(&b);

	ARGBEGIN{
	case 'a':
		rebuildall = 1;
		break;
	case 's':
		sflag++;
		break;
	case 'v':
		vflag++;
		break;
	default:
		usage();
	}ARGEND

	if(argc > 0)
		usage();

	if(rebuildall)
		clean();
	goversion = findgoversion();
	setup();

	xsetenv("GOROOT", goroot);
	xsetenv("GOROOT_FINAL", goroot_final);

	// For the main bootstrap, building for host os/arch.
	oldgoos = goos;
	oldgoarch = goarch;
	oldgochar = gochar;
	goos = gohostos;
	goarch = gohostarch;
	gochar = gohostchar;
	xsetenv("GOARCH", goarch);
	xsetenv("GOOS", goos);

	for(i=0; i<nelem(buildorder); i++) {
		install(bprintf(&b, buildorder[i], gohostchar));
		if(!streq(oldgochar, gohostchar) && xstrstr(buildorder[i], "%s"))
			install(bprintf(&b, buildorder[i], oldgochar));
	}

	goos = oldgoos;
	goarch = oldgoarch;
	gochar = oldgochar;
	xsetenv("GOARCH", goarch);
	xsetenv("GOOS", goos);

	// Build pkg/runtime for actual goos/goarch too.
	if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
		install("pkg/runtime");

	bfree(&b);
}
Example #16
0
File: build.c Project: Isor/golang
// The bootstrap command runs a build from scratch,
// stopping at having installed the go_bootstrap command.
void
cmdbootstrap(int argc, char **argv)
{
	int i;
	Buf b;
	char *oldgoos, *oldgoarch, *oldgochar;

	binit(&b);

	ARGBEGIN{
	case 'a':
		rebuildall = 1;
		break;
	case 's':
		sflag++;
		break;
	case 'v':
		vflag++;
		break;
	default:
		usage();
	}ARGEND

	if(argc > 0)
		usage();

	if(isdir(bpathf(&b, "%s/src/pkg", goroot))) {
		fatal("\n\n"
			"The Go package sources have moved to $GOROOT/src.\n"
			"*** %s still exists. ***\n"
			"It probably contains stale files that may confuse the build.\n"
			"Please (check what's there and) remove it and try again.\n"
			"See http://golang.org/s/go14nopkg\n", bpathf(&b, "%s/src/pkg", goroot));
	}
	
	if(rebuildall)
		clean();
	goversion = findgoversion();
	setup();

	xsetenv("GOROOT", goroot);
	xsetenv("GOROOT_FINAL", goroot_final);

	// For the main bootstrap, building for host os/arch.
	oldgoos = goos;
	oldgoarch = goarch;
	oldgochar = gochar;
	goos = gohostos;
	goarch = gohostarch;
	gochar = gohostchar;
	xsetenv("GOARCH", goarch);
	xsetenv("GOOS", goos);

	for(i=0; i<nelem(buildorder); i++) {
		install(bprintf(&b, buildorder[i], gohostchar));
		if(!streq(oldgochar, gohostchar) && xstrstr(buildorder[i], "%s"))
			install(bprintf(&b, buildorder[i], oldgochar));
	}

	goos = oldgoos;
	goarch = oldgoarch;
	gochar = oldgochar;
	xsetenv("GOARCH", goarch);
	xsetenv("GOOS", goos);

	// Build runtime for actual goos/goarch too.
	if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
		install("runtime");

	bfree(&b);
}
Example #17
0
// findgoversion determines the Go version to use in the version string.
static char*
findgoversion(void)
{
	char *tag, *rev, *p;
	int i, nrev;
	Buf b, path, bmore, branch;
	Vec tags;

	binit(&b);
	binit(&path);
	binit(&bmore);
	binit(&branch);
	vinit(&tags);

	// The $GOROOT/VERSION file takes priority, for distributions
	// without the Mercurial repo.
	bpathf(&path, "%s/VERSION", goroot);
	if(isfile(bstr(&path))) {
		readfile(&b, bstr(&path));
		chomp(&b);
		// Commands such as "dist version > VERSION" will cause
		// the shell to create an empty VERSION file and set dist's
		// stdout to its fd. dist in turn looks at VERSION and uses
		// its content if available, which is empty at this point.
		if(b.len > 0)
			goto done;
	}

	// The $GOROOT/VERSION.cache file is a cache to avoid invoking
	// hg every time we run this command.  Unlike VERSION, it gets
	// deleted by the clean command.
	bpathf(&path, "%s/VERSION.cache", goroot);
	if(isfile(bstr(&path))) {
		readfile(&b, bstr(&path));
		chomp(&b);
		goto done;
	}

	// Otherwise, use Mercurial.
	// What is the current branch?
	run(&branch, goroot, CheckExit, "hg", "identify", "-b", nil);
	chomp(&branch);

	// What are the tags along the current branch?
	tag = "devel";
	rev = ".";
	run(&b, goroot, CheckExit, "hg", "log", "-b", bstr(&branch), "-r", ".:0", "--template", "{tags} + ", nil);
	splitfields(&tags, bstr(&b));
	nrev = 0;
	for(i=0; i<tags.len; i++) {
		p = tags.p[i];
		if(streq(p, "+"))
			nrev++;
		// NOTE: Can reenable the /* */ code when we want to
		// start reporting versions named 'weekly' again.
		if(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) {
			tag = xstrdup(p);
			// If this tag matches the current checkout
			// exactly (no "+" yet), don't show extra
			// revision information.
			if(nrev == 0)
				rev = "";
			break;
		}
	}

	if(tag[0] == '\0') {
		// Did not find a tag; use branch name.
		bprintf(&b, "branch.%s", bstr(&branch));
		tag = btake(&b);
	}

	if(rev[0]) {
		// Tag is before the revision we're building.
		// Add extra information.
		run(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short} {date|date}", "-r", rev, nil);
		chomp(&bmore);
	}

	bprintf(&b, "%s", tag);
	if(bmore.len > 0)
		bwriteb(&b, &bmore);

	// Cache version.
	writefile(&b, bstr(&path), 0);

done:
	p = btake(&b);


	bfree(&b);
	bfree(&path);
	bfree(&bmore);
	bfree(&branch);
	vfree(&tags);

	return p;
}
Example #18
0
File: build.c Project: Isor/golang
// init handles initialization of the various global state, like goroot and goarch.
void
init(void)
{
	char *p;
	int i;
	Buf b;

	binit(&b);

	xgetenv(&b, "GOROOT");
	if(b.len > 0) {
		// if not "/", then strip trailing path separator
		if(b.len >= 2 && b.p[b.len - 1] == slash[0])
			b.len--;
		goroot = btake(&b);
	}

	xgetenv(&b, "GOBIN");
	if(b.len == 0)
		bprintf(&b, "%s%sbin", goroot, slash);
	gobin = btake(&b);

	xgetenv(&b, "GOOS");
	if(b.len == 0)
		bwritestr(&b, gohostos);
	goos = btake(&b);
	if(find(goos, okgoos, nelem(okgoos)) < 0)
		fatal("unknown $GOOS %s", goos);

	xgetenv(&b, "GOARM");
	if(b.len == 0)
		bwritestr(&b, xgetgoarm());
	goarm = btake(&b);

	xgetenv(&b, "GO386");
	if(b.len == 0) {
		if(cansse2())
			bwritestr(&b, "sse2");
		else
			bwritestr(&b, "387");
	}
	go386 = btake(&b);

	p = bpathf(&b, "%s/include/u.h", goroot);
	if(!isfile(p)) {
		fatal("$GOROOT is not set correctly or not exported\n"
			"\tGOROOT=%s\n"
			"\t%s does not exist", goroot, p);
	}

	xgetenv(&b, "GOHOSTARCH");
	if(b.len > 0)
		gohostarch = btake(&b);

	i = find(gohostarch, okgoarch, nelem(okgoarch));
	if(i < 0)
		fatal("unknown $GOHOSTARCH %s", gohostarch);
	bprintf(&b, "%c", gochars[i]);
	gohostchar = btake(&b);

	xgetenv(&b, "GOARCH");
	if(b.len == 0)
		bwritestr(&b, gohostarch);
	goarch = btake(&b);
	i = find(goarch, okgoarch, nelem(okgoarch));
	if(i < 0)
		fatal("unknown $GOARCH %s", goarch);
	bprintf(&b, "%c", gochars[i]);
	gochar = btake(&b);

	xgetenv(&b, "GO_EXTLINK_ENABLED");
	if(b.len > 0) {
		goextlinkenabled = btake(&b);
		if(!streq(goextlinkenabled, "0") && !streq(goextlinkenabled, "1"))
			fatal("unknown $GO_EXTLINK_ENABLED %s", goextlinkenabled);
	}
	
	xgetenv(&b, "CC");
	if(b.len == 0) {
		// Use clang on OS X, because gcc is deprecated there.
		// Xcode for OS X 10.9 Mavericks will ship a fake "gcc" binary that
		// actually runs clang. We prepare different command
		// lines for the two binaries, so it matters what we call it.
		// See golang.org/issue/5822.
		if(defaultclang)
			bprintf(&b, "clang");
		else
			bprintf(&b, "gcc");
	}
	defaultcc = btake(&b);

	xgetenv(&b, "CFLAGS");
	defaultcflags = btake(&b);

	xgetenv(&b, "LDFLAGS");
	defaultldflags = btake(&b);

	xgetenv(&b, "CC_FOR_TARGET");
	if(b.len == 0) {
		bprintf(&b, defaultcc);
	}
	defaultcctarget = btake(&b);

	xgetenv(&b, "CXX_FOR_TARGET");
	if(b.len == 0) {
		xgetenv(&b, "CXX");
		if(b.len == 0) {
			if(defaultclang)
				bprintf(&b, "clang++");
			else
				bprintf(&b, "g++");
		}
	}
	defaultcxxtarget = btake(&b);

	xsetenv("GOROOT", goroot);
	xsetenv("GOARCH", goarch);
	xsetenv("GOOS", goos);
	xsetenv("GOARM", goarm);
	xsetenv("GO386", go386);

	// Make the environment more predictable.
	xsetenv("LANG", "C");
	xsetenv("LANGUAGE", "en_US.UTF8");

	goversion = findgoversion();

	workdir = xworkdir();
	xatexit(rmworkdir);

	bpathf(&b, "%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch);
	tooldir = btake(&b);

	bfree(&b);
}
Example #19
0
// install installs the library, package, or binary associated with dir,
// which is relative to $GOROOT/src.
static void
install(char *dir)
{
	char *name, *p, *elem, *prefix, *exe;
	bool islib, ispkg, isgo, stale;
	Buf b, b1, path;
	Vec compile, files, link, go, missing, clean, lib, extra;
	Time ttarg, t;
	int i, j, k, n, doclean, targ, usecpp;

	if(vflag) {
		if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
			errprintf("%s (%s/%s)\n", dir, goos, goarch);
		else
			errprintf("%s\n", dir);
	}

	binit(&b);
	binit(&b1);
	binit(&path);
	vinit(&compile);
	vinit(&files);
	vinit(&link);
	vinit(&go);
	vinit(&missing);
	vinit(&clean);
	vinit(&lib);
	vinit(&extra);


	// path = full path to dir.
	bpathf(&path, "%s/src/%s", goroot, dir);
	name = lastelem(dir);

	// For misc/prof, copy into the tool directory and we're done.
	if(hasprefix(dir, "misc/")) {
		copy(bpathf(&b, "%s/%s", tooldir, name),
			bpathf(&b1, "%s/misc/%s", goroot, name), 1);
		goto out;
	}

	// For release, cmd/prof is not included.
	if((streq(dir, "cmd/prof")) && !isdir(bstr(&path))) {
		if(vflag > 1)
			errprintf("skipping %s - does not exist\n", dir);
		goto out;
	}

	// set up gcc command line on first run.
	if(gccargs.len == 0) {
		bprintf(&b, "%s", defaultcc);
		splitfields(&gccargs, bstr(&b));
		for(i=0; i<nelem(proto_gccargs); i++)
			vadd(&gccargs, proto_gccargs[i]);
		if(contains(gccargs.p[0], "clang")) {
			// disable ASCII art in clang errors, if possible
			vadd(&gccargs, "-fno-caret-diagnostics");
			// clang is too smart about unused command-line arguments
			vadd(&gccargs, "-Qunused-arguments");
		}
		if(streq(gohostos, "darwin")) {
			// golang.org/issue/5261
			vadd(&gccargs, "-mmacosx-version-min=10.6");
		}
	}

	islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
	ispkg = hasprefix(dir, "pkg");
	isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");

	exe = "";
	if(streq(gohostos, "windows"))
		exe = ".exe";

	// Start final link command line.
	// Note: code below knows that link.p[targ] is the target.
	if(islib) {
		// C library.
		vadd(&link, "ar");
		if(streq(gohostos, "plan9"))
			vadd(&link, "rc");
		else
			vadd(&link, "rsc");
		prefix = "";
		if(!hasprefix(name, "lib"))
			prefix = "lib";
		targ = link.len;
		vadd(&link, bpathf(&b, "%s/pkg/obj/%s_%s/%s%s.a", goroot, gohostos, gohostarch, prefix, name));
	} else if(ispkg) {
		// Go library (package).
		vadd(&link, bpathf(&b, "%s/pack", tooldir));
		vadd(&link, "grc");
		p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir+4);
		*xstrrchr(p, '/') = '\0';
		xmkdirall(p);
		targ = link.len;
		vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir+4));
	} else if(streq(dir, "cmd/go") || streq(dir, "cmd/cgo")) {
		// Go command.
		vadd(&link, bpathf(&b, "%s/%sl", tooldir, gochar));
		vadd(&link, "-o");
		elem = name;
		if(streq(elem, "go"))
			elem = "go_bootstrap";
		targ = link.len;
		vadd(&link, bpathf(&b, "%s/%s%s", tooldir, elem, exe));
	} else {
		// C command. Use gccargs.
		if(streq(gohostos, "plan9")) {
			vadd(&link, bprintf(&b, "%sl", gohostchar));
			vadd(&link, "-o");
			targ = link.len;
			vadd(&link, bpathf(&b, "%s/%s", tooldir, name));
		} else {
			vcopy(&link, gccargs.p, gccargs.len);
			if(sflag)
				vadd(&link, "-static");
			vadd(&link, "-o");
			targ = link.len;
			vadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe));
			if(streq(gohostarch, "amd64"))
				vadd(&link, "-m64");
			else if(streq(gohostarch, "386"))
				vadd(&link, "-m32");
		}
	}
	ttarg = mtime(link.p[targ]);

	// Gather files that are sources for this target.
	// Everything in that directory, and any target-specific
	// additions.
	xreaddir(&files, bstr(&path));

	// Remove files beginning with . or _,
	// which are likely to be editor temporary files.
	// This is the same heuristic build.ScanDir uses.
	// There do exist real C files beginning with _,
	// so limit that check to just Go files.
	n = 0;
	for(i=0; i<files.len; i++) {
		p = files.p[i];
		if(hasprefix(p, ".") || (hasprefix(p, "_") && hassuffix(p, ".go")))
			xfree(p);
		else
			files.p[n++] = p;
	}
	files.len = n;

	for(i=0; i<nelem(deptab); i++) {
		if(hasprefix(dir, deptab[i].prefix)) {
			for(j=0; (p=deptab[i].dep[j])!=nil; j++) {
				breset(&b1);
				bwritestr(&b1, p);
				bsubst(&b1, "$GOROOT", goroot);
				bsubst(&b1, "$GOOS", goos);
				bsubst(&b1, "$GOARCH", goarch);
				p = bstr(&b1);
				if(hassuffix(p, ".a")) {
					if(streq(gohostos, "plan9") && hassuffix(p, "libbio.a"))
						continue;
					vadd(&lib, bpathf(&b, "%s", p));
					continue;
				}
				if(hassuffix(p, "/*")) {
					bpathf(&b, "%s/%s", bstr(&path), p);
					b.len -= 2;
					xreaddir(&extra, bstr(&b));
					bprintf(&b, "%s", p);
					b.len -= 2;
					for(k=0; k<extra.len; k++)
						vadd(&files, bpathf(&b1, "%s/%s", bstr(&b), extra.p[k]));
					continue;
				}
				if(hasprefix(p, "-")) {
					p++;
					n = 0;
					for(k=0; k<files.len; k++) {
						if(hasprefix(files.p[k], p))
							xfree(files.p[k]);
						else
							files.p[n++] = files.p[k];
					}
					files.len = n;
					continue;
				}
				vadd(&files, p);
			}
		}
	}
	vuniq(&files);

	// Convert to absolute paths.
	for(i=0; i<files.len; i++) {
		if(!isabs(files.p[i])) {
			bpathf(&b, "%s/%s", bstr(&path), files.p[i]);
			xfree(files.p[i]);
			files.p[i] = btake(&b);
		}
	}

	// Is the target up-to-date?
	stale = rebuildall;
	n = 0;
	for(i=0; i<files.len; i++) {
		p = files.p[i];
		for(j=0; j<nelem(depsuffix); j++)
			if(hassuffix(p, depsuffix[j]))
				goto ok;
		xfree(files.p[i]);
		continue;
	ok:
		t = mtime(p);
		if(t != 0 && !hassuffix(p, ".a") && !shouldbuild(p, dir)) {
			xfree(files.p[i]);
			continue;
		}
		if(hassuffix(p, ".go"))
			vadd(&go, p);
		if(t > ttarg)
			stale = 1;
		if(t == 0) {
			vadd(&missing, p);
			files.p[n++] = files.p[i];
			continue;
		}
		files.p[n++] = files.p[i];
	}
	files.len = n;

	// If there are no files to compile, we're done.
	if(files.len == 0)
		goto out;
	
	for(i=0; i<lib.len && !stale; i++)
		if(mtime(lib.p[i]) > ttarg)
			stale = 1;

	if(!stale)
		goto out;

	// For package runtime, copy some files into the work space.
	if(streq(dir, "pkg/runtime")) {
		copy(bpathf(&b, "%s/arch_GOARCH.h", workdir),
			bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
		copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
			bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
		p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
		if(isfile(p))
			copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
		copy(bpathf(&b, "%s/os_GOOS.h", workdir),
			bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
		copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
			bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
	}

	// Generate any missing files; regenerate existing ones.
	for(i=0; i<files.len; i++) {
		p = files.p[i];
		elem = lastelem(p);
		for(j=0; j<nelem(gentab); j++) {
			if(hasprefix(elem, gentab[j].nameprefix)) {
				if(vflag > 1)
					errprintf("generate %s\n", p);
				gentab[j].gen(bstr(&path), p);
				// Do not add generated file to clean list.
				// In pkg/runtime, we want to be able to
				// build the package with the go tool,
				// and it assumes these generated files already
				// exist (it does not know how to build them).
				// The 'clean' command can remove
				// the generated files.
				goto built;
			}
		}
		// Did not rebuild p.
		if(find(p, missing.p, missing.len) >= 0)
			fatal("missing file %s", p);
	built:;
	}

	// One more copy for package runtime.
	// The last batch was required for the generators.
	// This one is generated.
	if(streq(dir, "pkg/runtime")) {
		copy(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
			bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
	}

	// Generate .c files from .goc files.
	if(streq(dir, "pkg/runtime")) {
		for(i=0; i<files.len; i++) {
			p = files.p[i];
			if(!hassuffix(p, ".goc"))
				continue;
			// b = path/zp but with _goos_goarch.c instead of .goc
			bprintf(&b, "%s%sz%s", bstr(&path), slash, lastelem(p));
			b.len -= 4;
			bwritef(&b, "_%s_%s.c", goos, goarch);
			goc2c(p, bstr(&b));
			vadd(&files, bstr(&b));
		}
		vuniq(&files);
	}

	if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
		// We've generated the right files; the go command can do the build.
		if(vflag > 1)
			errprintf("skip build for cross-compile %s\n", dir);
		goto nobuild;
	}

	// The files generated by GNU Bison use macros that aren't
	// supported by the Plan 9 compilers so we have to use the
	// external preprocessor when compiling.
	usecpp = 0;
	if(streq(gohostos, "plan9")) {
		for(i=0; i<files.len; i++) {
			p = files.p[i];
			if(hassuffix(p, "y.tab.c") || hassuffix(p, "y.tab.h")){
				usecpp = 1;
				break;
			}
		}
	}

	// Compile the files.
	for(i=0; i<files.len; i++) {
		if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s"))
			continue;
		name = lastelem(files.p[i]);

		vreset(&compile);
		if(!isgo) {
			// C library or tool.
			if(streq(gohostos, "plan9")) {
				vadd(&compile, bprintf(&b, "%sc", gohostchar));
				vadd(&compile, "-FTVw");
				if(usecpp)
					vadd(&compile, "-Bp+");
				vadd(&compile, bpathf(&b, "-I%s/include/plan9", goroot));
				vadd(&compile, bpathf(&b, "-I%s/include/plan9/%s", goroot, gohostarch));
				// Work around Plan 9 C compiler's handling of #include with .. path.
				vadd(&compile, bpathf(&b, "-I%s/src/cmd/ld", goroot));
			} else {
				vcopy(&compile, gccargs.p, gccargs.len);
				vadd(&compile, "-c");
				if(streq(gohostarch, "amd64"))
					vadd(&compile, "-m64");
				else if(streq(gohostarch, "386"))
					vadd(&compile, "-m32");
				if(streq(dir, "lib9"))
					vadd(&compile, "-DPLAN9PORT");
	
				vadd(&compile, "-I");
				vadd(&compile, bpathf(&b, "%s/include", goroot));
			}

			vadd(&compile, "-I");
			vadd(&compile, bstr(&path));

			// lib9/goos.c gets the default constants hard-coded.
			if(streq(name, "goos.c")) {
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOOS=\"%s\"", goos));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOARCH=\"%s\"", goarch));
				bprintf(&b1, "%s", goroot_final);
				bsubst(&b1, "\\", "\\\\");  // turn into C string
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOROOT=\"%s\"", bstr(&b1)));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOVERSION=\"%s\"", goversion));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386));
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b, "GO_EXTLINK_ENABLED=\"%s\"", goextlinkenabled));
			}

			// gc/lex.c records the GOEXPERIMENT setting used during the build.
			if(streq(name, "lex.c")) {
				xgetenv(&b, "GOEXPERIMENT");
				vadd(&compile, "-D");
				vadd(&compile, bprintf(&b1, "GOEXPERIMENT=\"%s\"", bstr(&b)));
			}
		} else {
			// Supporting files for a Go package.
			if(hassuffix(files.p[i], ".s"))
				vadd(&compile, bpathf(&b, "%s/%sa", tooldir, gochar));
			else {
				vadd(&compile, bpathf(&b, "%s/%sc", tooldir, gochar));
				vadd(&compile, "-F");
				vadd(&compile, "-V");
				vadd(&compile, "-w");
			}
			vadd(&compile, "-I");
			vadd(&compile, workdir);
			vadd(&compile, "-I");
			vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
			vadd(&compile, "-D");
			vadd(&compile, bprintf(&b, "GOOS_%s", goos));
			vadd(&compile, "-D");
			vadd(&compile, bprintf(&b, "GOARCH_%s", goarch));
			vadd(&compile, "-D");
			vadd(&compile, bprintf(&b, "GOOS_GOARCH_%s_%s", goos, goarch));
		}

		bpathf(&b, "%s/%s", workdir, lastelem(files.p[i]));
		doclean = 1;
		if(!isgo && streq(gohostos, "darwin")) {
			// To debug C programs on OS X, it is not enough to say -ggdb
			// on the command line.  You have to leave the object files
			// lying around too.  Leave them in pkg/obj/, which does not
			// get removed when this tool exits.
			bpathf(&b1, "%s/pkg/obj/%s", goroot, dir);
			xmkdirall(bstr(&b1));
			bpathf(&b, "%s/%s", bstr(&b1), lastelem(files.p[i]));
			doclean = 0;
		}

		// Change the last character of the output file (which was c or s).
		if(streq(gohostos, "plan9"))
			b.p[b.len-1] = gohostchar[0];
		else
			b.p[b.len-1] = 'o';
		vadd(&compile, "-o");
		vadd(&compile, bstr(&b));
		vadd(&compile, files.p[i]);
		bgrunv(bstr(&path), CheckExit, &compile);

		vadd(&link, bstr(&b));
		if(doclean)
			vadd(&clean, bstr(&b));
	}
	bgwait();

	if(isgo) {
		// The last loop was compiling individual files.
		// Hand the Go files to the compiler en masse.
		vreset(&compile);
		vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));

		bpathf(&b, "%s/_go_.%s", workdir, gochar);
		vadd(&compile, "-o");
		vadd(&compile, bstr(&b));
		vadd(&clean, bstr(&b));
		vadd(&link, bstr(&b));

		vadd(&compile, "-p");
		if(hasprefix(dir, "pkg/"))
			vadd(&compile, dir+4);
		else
			vadd(&compile, "main");

		if(streq(dir, "pkg/runtime"))
			vadd(&compile, "-+");

		vcopy(&compile, go.p, go.len);

		runv(nil, bstr(&path), CheckExit, &compile);
	}

	if(!islib && !isgo) {
		// C binaries need the libraries explicitly, and -lm.
		vcopy(&link, lib.p, lib.len);
		if(!streq(gohostos, "plan9"))
			vadd(&link, "-lm");
	}

	// Remove target before writing it.
	xremove(link.p[targ]);

	runv(nil, nil, CheckExit, &link);

nobuild:
	// In package runtime, we install runtime.h and cgocall.h too,
	// for use by cgo compilation.
	if(streq(dir, "pkg/runtime")) {
		copy(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
			bpathf(&b1, "%s/src/pkg/runtime/cgocall.h", goroot), 0);
		copy(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
			bpathf(&b1, "%s/src/pkg/runtime/runtime.h", goroot), 0);
	}


out:
	for(i=0; i<clean.len; i++)
		xremove(clean.p[i]);

	bfree(&b);
	bfree(&b1);
	bfree(&path);
	vfree(&compile);
	vfree(&files);
	vfree(&link);
	vfree(&go);
	vfree(&missing);
	vfree(&clean);
	vfree(&lib);
	vfree(&extra);
}
Example #20
0
/*
 * Called here by find() for each file included.
 *   This is a callback. The original is find_files() above.
 *
 *  Send the file and its data to the Storage daemon.
 *
 *  Returns: 1 if OK
 *           0 if error
 *          -1 to ignore file/directory (not used here)
 */
int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
{
   bool do_read = false;
   int stat, data_stream; 
   int rtnstat = 0;
   DIGEST *digest = NULL;
   DIGEST *signing_digest = NULL;
   int digest_stream = STREAM_NONE;
   SIGNATURE *sig = NULL;
   bool has_file_data = false;
   // TODO landonf: Allow the user to specify the digest algorithm
#ifdef HAVE_SHA2
   crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA256;
#else
   crypto_digest_t signing_algorithm = CRYPTO_DIGEST_SHA1;
#endif
   BSOCK *sd = jcr->store_bsock;

   if (job_canceled(jcr)) {
      return 0;
   }

   jcr->num_files_examined++;         /* bump total file count */

   switch (ff_pkt->type) {
   case FT_LNKSAVED:                  /* Hard linked, file already saved */
      Dmsg2(130, "FT_LNKSAVED hard link: %s => %s\n", ff_pkt->fname, ff_pkt->link);
      break;
   case FT_REGE:
      Dmsg1(130, "FT_REGE saving: %s\n", ff_pkt->fname);
      has_file_data = true;
      break;
   case FT_REG:
      Dmsg1(130, "FT_REG saving: %s\n", ff_pkt->fname);
      has_file_data = true;
      break;
   case FT_LNK:
      Dmsg2(130, "FT_LNK saving: %s -> %s\n", ff_pkt->fname, ff_pkt->link);
      break;
   case FT_DIRBEGIN:
      jcr->num_files_examined--;      /* correct file count */
      return 1;                       /* not used */
   case FT_NORECURSE:
      Jmsg(jcr, M_INFO, 1, _("     Recursion turned off. Will not descend from %s into %s\n"),
           ff_pkt->top_fname, ff_pkt->fname);
      ff_pkt->type = FT_DIREND;       /* Backup only the directory entry */
      break;
   case FT_NOFSCHG:
      /* Suppress message for /dev filesystems */
      if (!is_in_fileset(ff_pkt)) {
         Jmsg(jcr, M_INFO, 1, _("     %s is a different filesystem. Will not descend from %s into %s\n"),
              ff_pkt->fname, ff_pkt->top_fname, ff_pkt->fname);
      }
      ff_pkt->type = FT_DIREND;       /* Backup only the directory entry */
      break;
   case FT_INVALIDFS:
      Jmsg(jcr, M_INFO, 1, _("     Disallowed filesystem. Will not descend from %s into %s\n"),
           ff_pkt->top_fname, ff_pkt->fname);
      ff_pkt->type = FT_DIREND;       /* Backup only the directory entry */
      break;
   case FT_INVALIDDT:
      Jmsg(jcr, M_INFO, 1, _("     Disallowed drive type. Will not descend into %s\n"),
           ff_pkt->fname);
      break;
   case FT_REPARSE:
   case FT_DIREND:
      Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link);
      break;
   case FT_SPEC:
      Dmsg1(130, "FT_SPEC saving: %s\n", ff_pkt->fname);
      if (S_ISSOCK(ff_pkt->statp.st_mode)) {
        Jmsg(jcr, M_SKIPPED, 1, _("     Socket file skipped: %s\n"), ff_pkt->fname);
        return 1;
      }
      break;
   case FT_RAW:
      Dmsg1(130, "FT_RAW saving: %s\n", ff_pkt->fname);
      has_file_data = true;
      break;
   case FT_FIFO:
      Dmsg1(130, "FT_FIFO saving: %s\n", ff_pkt->fname);
      break;
   case FT_NOACCESS: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not access \"%s\": ERR=%s\n"), ff_pkt->fname,
         be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   case FT_NOFOLLOW: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not follow link \"%s\": ERR=%s\n"), 
           ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   case FT_NOSTAT: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not stat \"%s\": ERR=%s\n"), ff_pkt->fname,
         be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   case FT_DIRNOCHG:
   case FT_NOCHG:
      Jmsg(jcr, M_SKIPPED, 1, _("     Unchanged file skipped: %s\n"), ff_pkt->fname);
      return 1;
   case FT_ISARCH:
      Jmsg(jcr, M_NOTSAVED, 0, _("     Archive file not saved: %s\n"), ff_pkt->fname);
      return 1;
   case FT_NOOPEN: {
      berrno be;
      Jmsg(jcr, M_NOTSAVED, 0, _("     Could not open directory \"%s\": ERR=%s\n"), 
           ff_pkt->fname, be.bstrerror(ff_pkt->ff_errno));
      jcr->JobErrors++;
      return 1;
   }
   default:
      Jmsg(jcr, M_NOTSAVED, 0,  _("     Unknown file type %d; not saved: %s\n"), 
           ff_pkt->type, ff_pkt->fname);
      jcr->JobErrors++;
      return 1;
   }

   Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname);

   /* Digests and encryption are only useful if there's file data */
   if (has_file_data) {
      /*
       * Setup for digest handling. If this fails, the digest will be set to NULL
       * and not used. Note, the digest (file hash) can be any one of the four
       * algorithms below.
       *
       * The signing digest is a single algorithm depending on
       * whether or not we have SHA2.              
       *   ****FIXME****  the signing algoritm should really be
       *   determined a different way!!!!!!  What happens if
       *   sha2 was available during backup but not restore?
       */
      if (ff_pkt->flags & FO_MD5) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_MD5);
         digest_stream = STREAM_MD5_DIGEST;

      } else if (ff_pkt->flags & FO_SHA1) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA1);
         digest_stream = STREAM_SHA1_DIGEST;

      } else if (ff_pkt->flags & FO_SHA256) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA256);
         digest_stream = STREAM_SHA256_DIGEST;

      } else if (ff_pkt->flags & FO_SHA512) {
         digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA512);
         digest_stream = STREAM_SHA512_DIGEST;
      }

      /* Did digest initialization fail? */
      if (digest_stream != STREAM_NONE && digest == NULL) {
         Jmsg(jcr, M_WARNING, 0, _("%s digest initialization failed\n"),
            stream_to_ascii(digest_stream));
      }

      /*
       * Set up signature digest handling. If this fails, the signature digest will be set to
       * NULL and not used.
       */
      // TODO landonf: We should really only calculate the digest once, for both verification and signing.
      if (jcr->crypto.pki_sign) {
         signing_digest = crypto_digest_new(jcr, signing_algorithm);

         /* Full-stop if a failure occurred initializing the signature digest */
         if (signing_digest == NULL) {
            Jmsg(jcr, M_NOTSAVED, 0, _("%s signature digest initialization failed\n"),
               stream_to_ascii(signing_algorithm));
            jcr->JobErrors++;
            goto good_rtn;
         }
      }

      /* Enable encryption */
      if (jcr->crypto.pki_encrypt) {
         ff_pkt->flags |= FO_ENCRYPT;
      }
   }

   /* Initialize the file descriptor we use for data and other streams. */
   binit(&ff_pkt->bfd);
   if (ff_pkt->flags & FO_PORTABLE) {
      set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
   }
   if (ff_pkt->cmd_plugin) {
      if (!set_cmd_plugin(&ff_pkt->bfd, jcr)) {
         goto bail_out;
      }
      send_plugin_name(jcr, sd, true);      /* signal start of plugin data */
   }

   /* Send attributes -- must be done after binit() */
   if (!encode_and_send_attributes(jcr, ff_pkt, data_stream)) {
      goto bail_out;
   }

   /* Set up the encryption context and send the session data to the SD */
   if (has_file_data && jcr->crypto.pki_encrypt) {
      if (!crypto_session_send(jcr, sd)) {
         goto bail_out;
      }
   }

   /*
    * Open any file with data that we intend to save, then save it.
    *
    * Note, if is_win32_backup, we must open the Directory so that
    * the BackupRead will save its permissions and ownership streams.
    */
   if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode)) {
#ifdef HAVE_WIN32
      do_read = !is_portable_backup(&ff_pkt->bfd) || ff_pkt->statp.st_size > 0;
#else
      do_read = ff_pkt->statp.st_size > 0;  
#endif
   } else if (ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO ||
              ff_pkt->type == FT_REPARSE ||
         (!is_portable_backup(&ff_pkt->bfd) && ff_pkt->type == FT_DIREND)) {
      do_read = true;
   }
   if (ff_pkt->cmd_plugin) {
      do_read = true;
   }

   Dmsg1(400, "do_read=%d\n", do_read);
   if (do_read) {
      btimer_t *tid;

      if (ff_pkt->type == FT_FIFO) {
         tid = start_thread_timer(jcr, pthread_self(), 60);
      } else {
         tid = NULL;
      }
      int noatime = ff_pkt->flags & FO_NOATIME ? O_NOATIME : 0;
      ff_pkt->bfd.reparse_point = ff_pkt->type == FT_REPARSE;
      if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY | noatime, 0) < 0) {
         ff_pkt->ff_errno = errno;
         berrno be;
         Jmsg(jcr, M_NOTSAVED, 0, _("     Cannot open \"%s\": ERR=%s.\n"), ff_pkt->fname,
              be.bstrerror());
         jcr->JobErrors++;
         if (tid) {
            stop_thread_timer(tid);
            tid = NULL;
         }
         goto good_rtn;
      }
      if (tid) {
         stop_thread_timer(tid);
         tid = NULL;
      }

      stat = send_data(jcr, data_stream, ff_pkt, digest, signing_digest);

      if (ff_pkt->flags & FO_CHKCHANGES) {
         has_file_changed(jcr, ff_pkt);
      }

      bclose(&ff_pkt->bfd);
      
      if (!stat) {
         goto bail_out;
      }
   }

#ifdef HAVE_DARWIN_OS
   /* Regular files can have resource forks and Finder Info */
   if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
            ff_pkt->flags & FO_HFSPLUS)) {
      if (ff_pkt->hfsinfo.rsrclength > 0) {
         int flags;
         int rsrc_stream;
         if (!bopen_rsrc(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
            ff_pkt->ff_errno = errno;
            berrno be;
            Jmsg(jcr, M_NOTSAVED, -1, _("     Cannot open resource fork for \"%s\": ERR=%s.\n"), 
                 ff_pkt->fname, be.bstrerror());
            jcr->JobErrors++;
            if (is_bopen(&ff_pkt->bfd)) {
               bclose(&ff_pkt->bfd);
            }
            goto good_rtn;
         }
         flags = ff_pkt->flags;
         ff_pkt->flags &= ~(FO_GZIP|FO_SPARSE);
         if (flags & FO_ENCRYPT) {
            rsrc_stream = STREAM_ENCRYPTED_MACOS_FORK_DATA;
         } else {
            rsrc_stream = STREAM_MACOS_FORK_DATA;
         }
         stat = send_data(jcr, rsrc_stream, ff_pkt, digest, signing_digest);
         ff_pkt->flags = flags;
         bclose(&ff_pkt->bfd);
         if (!stat) {
            goto bail_out;
         }
      }

      Dmsg1(300, "Saving Finder Info for \"%s\"\n", ff_pkt->fname);
      sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
      Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
      pm_memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
      sd->msglen = 32;
      if (digest) {
         crypto_digest_update(digest, (uint8_t *)sd->msg, sd->msglen);
      }
      if (signing_digest) {
         crypto_digest_update(signing_digest, (uint8_t *)sd->msg, sd->msglen);
      }
      sd->send();
      sd->signal(BNET_EOD);
   }
#endif

   /*
    * Save ACLs for anything not being a symlink and not being a plugin.
    */
   if (!ff_pkt->cmd_plugin) {
      if (ff_pkt->flags & FO_ACL && ff_pkt->type != FT_LNK) {
         if (!build_acl_streams(jcr, ff_pkt))
            goto bail_out;
      }
   }

   /*
    * Save Extended Attributes for all files not being a plugin.
    */
   if (!ff_pkt->cmd_plugin) {
      if (ff_pkt->flags & FO_XATTR) {
         if (!build_xattr_streams(jcr, ff_pkt))
            goto bail_out;
      }
   }

   /* Terminate the signing digest and send it to the Storage daemon */
   if (signing_digest) {
      uint32_t size = 0;

      if ((sig = crypto_sign_new(jcr)) == NULL) {
         Jmsg(jcr, M_FATAL, 0, _("Failed to allocate memory for crypto signature.\n"));
         goto bail_out;
      }

      if (!crypto_sign_add_signer(sig, signing_digest, jcr->crypto.pki_keypair)) {
         Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
         goto bail_out;
      }

      /* Get signature size */
      if (!crypto_sign_encode(sig, NULL, &size)) {
         Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
         goto bail_out;
      }

      /* Grow the bsock buffer to fit our message if necessary */
      if (sizeof_pool_memory(sd->msg) < (int32_t)size) {
         sd->msg = realloc_pool_memory(sd->msg, size);
      }

      /* Send our header */
      sd->fsend("%ld %ld 0", jcr->JobFiles, STREAM_SIGNED_DIGEST);
      Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);

      /* Encode signature data */
      if (!crypto_sign_encode(sig, (uint8_t *)sd->msg, &size)) {
         Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
         goto bail_out;
      }

      sd->msglen = size;
      sd->send();
      sd->signal(BNET_EOD);              /* end of checksum */
   }

   /* Terminate any digest and send it to Storage daemon */
   if (digest) {
      uint32_t size;

      sd->fsend("%ld %d 0", jcr->JobFiles, digest_stream);
      Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);

      size = CRYPTO_DIGEST_MAX_SIZE;

      /* Grow the bsock buffer to fit our message if necessary */
      if (sizeof_pool_memory(sd->msg) < (int32_t)size) {
         sd->msg = realloc_pool_memory(sd->msg, size);
      }

      if (!crypto_digest_finalize(digest, (uint8_t *)sd->msg, &size)) {
         Jmsg(jcr, M_FATAL, 0, _("An error occurred finalizing signing the stream.\n"));
         goto bail_out;
      }

      sd->msglen = size;
      sd->send();
      sd->signal(BNET_EOD);              /* end of checksum */
   }
   if (ff_pkt->cmd_plugin) {
      send_plugin_name(jcr, sd, false); /* signal end of plugin data */
   }

good_rtn:
   rtnstat = 1;                       /* good return */

bail_out:
   if (digest) {
      crypto_digest_free(digest);
   }
   if (signing_digest) {
      crypto_digest_free(signing_digest);
   }
   if (sig) {
      crypto_sign_free(sig);        
   }
   return rtnstat;
}