char * mgt_VccCompile(struct cli *cli, const char *vclname, const char *vclsrc, int C_flag) { struct vcc_priv vp; struct vsb *sb; unsigned status; AN(cli); sb = VSB_new_auto(); XXXAN(sb); INIT_OBJ(&vp, VCC_PRIV_MAGIC); vp.src = vclsrc; VSB_printf(sb, "./vcl_%s.c", vclname); AZ(VSB_finish(sb)); vp.srcfile = strdup(VSB_data(sb)); AN(vp.srcfile); VSB_clear(sb); VSB_printf(sb, "./vcl_%s.so", vclname); AZ(VSB_finish(sb)); vp.libfile = strdup(VSB_data(sb)); AN(vp.srcfile); VSB_clear(sb); status = mgt_vcc_compile(&vp, sb, C_flag); AZ(VSB_finish(sb)); if (VSB_len(sb) > 0) VCLI_Out(cli, "%s", VSB_data(sb)); VSB_delete(sb); (void)unlink(vp.srcfile); free(vp.srcfile); if (status || C_flag) { (void)unlink(vp.libfile); free(vp.libfile); if (!C_flag) { VCLI_Out(cli, "VCL compilation failed"); VCLI_SetResult(cli, CLIS_PARAM); } return(NULL); } VCLI_Out(cli, "VCL compiled.\n"); return (vp.libfile); }
char * mgt_VccCompile(struct cli *cli, struct vclprog *vcl, const char *vclname, const char *vclsrc, const char *vclsrcfile, int C_flag) { struct vcc_priv vp; struct vsb *sb; unsigned status; char buf[1024]; FILE *fcs; char **av; int ac; AN(cli); sb = VSB_new_auto(); XXXAN(sb); INIT_OBJ(&vp, VCC_PRIV_MAGIC); vp.vclsrc = vclsrc; vp.vclsrcfile = vclsrcfile; /* * The subdirectory must have a unique name to 100% certain evade * the refcounting semantics of dlopen(3). * * Bad implementations of dlopen(3) think the shlib you are opening * is the same, if the filename is the same as one already opened. * * Sensible implementations do a stat(2) and requires st_ino and * st_dev to also match. * * A correct implementation would run on filesystems which tickle * st_gen, and also insist that be the identical, before declaring * a match. * * Since no correct implementations are known to exist, we are subject * to really interesting races if you do something like: * * (running on 'boot' vcl) * vcl.load foo /foo.vcl * vcl.use foo * few/slow requests * vcl.use boot * vcl.discard foo * vcl.load foo /foo.vcl // dlopen(3) says "same-same" * vcl.use foo * * Because discard of the first 'foo' lingers on non-zero reference * count, and when it finally runs, it trashes the second 'foo' because * dlopen(3) decided they were really the same thing. * * The Best way to reproduce this is to have regexps in the VCL. */ VSB_printf(sb, "vcl_%s.%.9f", vclname, VTIM_real()); AZ(VSB_finish(sb)); vp.dir = strdup(VSB_data(sb)); AN(vp.dir); if (VJ_make_subdir(vp.dir, "VCL", cli->sb)) { free(vp.dir); VSB_destroy(&sb); VCLI_Out(cli, "VCL compilation failed"); VCLI_SetResult(cli, CLIS_PARAM); return (NULL); } VSB_clear(sb); VSB_printf(sb, "%s/%s", vp.dir, VGC_SRC); AZ(VSB_finish(sb)); vp.csrcfile = strdup(VSB_data(sb)); AN(vp.csrcfile); VSB_clear(sb); VSB_printf(sb, "%s/%s", vp.dir, VGC_LIB); AZ(VSB_finish(sb)); vp.libfile = strdup(VSB_data(sb)); AN(vp.csrcfile); VSB_clear(sb); status = mgt_vcc_compile(&vp, sb, C_flag); AZ(VSB_finish(sb)); if (VSB_len(sb) > 0) VCLI_Out(cli, "%s", VSB_data(sb)); VSB_destroy(&sb); if (status || C_flag) { (void)unlink(vp.csrcfile); free(vp.csrcfile); (void)unlink(vp.libfile); free(vp.libfile); (void)rmdir(vp.dir); free(vp.dir); if (status) { VCLI_Out(cli, "VCL compilation failed"); VCLI_SetResult(cli, CLIS_PARAM); } return (NULL); } fcs = fopen(vp.csrcfile, "r"); AN(fcs); while (1) { AN(fgets(buf, sizeof buf, fcs)); if (memcmp(buf, VCC_INFO_PREFIX, strlen(VCC_INFO_PREFIX))) break; av = VAV_Parse(buf, &ac, 0); AN(av); AZ(av[0]); AZ(strcmp(av[1], "/*")); AZ(strcmp(av[ac-1], "*/")); if (!strcmp(av[3], "VCL")) mgt_vcl_depends(vcl, av[4]); else if (!strcmp(av[3], "VMOD")) mgt_vcl_vmod(vcl, av[4], av[5]); else WRONG("Wrong VCCINFO"); VAV_Free(av); } AZ(fclose(fcs)); (void)unlink(vp.csrcfile); free(vp.csrcfile); free(vp.dir); VCLI_Out(cli, "VCL compiled.\n"); return (vp.libfile); }