value netsys_peek_peer_credentials(value fd) { CAMLparam1(fd); CAMLlocal1(result); int uid; int gid; #ifdef SO_PASSCRED /* Linux */ { int one = 1; struct msghdr msg; struct cmsghdr *cmp; struct ucred *sc; char buf[CMSG_SPACE(sizeof(*sc))]; struct iovec iov; char iovbuf[1]; if (setsockopt(Int_val(fd), SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) { uerror("setsockopt", Nothing); }; memset(&msg, 0, sizeof msg); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = buf; msg.msg_controllen = sizeof(buf); iov.iov_base = iovbuf; iov.iov_len = 1; /* Linux requires that at least one byte must be transferred. * So we initialize the iovector for exactly one byte. */ if (recvmsg(Int_val(fd), &msg, MSG_PEEK) < 0) { uerror("recvmsg", Nothing); }; if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) { raise_not_found(); }; cmp = CMSG_FIRSTHDR(&msg); if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDENTIALS) { raise_not_found(); }; sc = (struct ucred *) CMSG_DATA(cmp); uid = sc->uid; gid = sc->gid; } #else #ifdef LOCAL_CREDS /* NetBSD */ /* The following code has been copied from libc: rpc/svc_vc.c * TODO: The following code does not work. No idea why. * msg_controllen is always 0. Maybe the socket option must be * set earlier (but that would be very strange). */ { int one = 1; struct msghdr msg; struct cmsghdr *cmp; void *crmsg = NULL; struct sockcred *sc; socklen_t crmsgsize; struct iovec iov; char buf; if (setsockopt(Int_val(fd), SOL_SOCKET, LOCAL_CREDS, &one, sizeof(one)) < 0) { uerror("setsockopt", Nothing); }; memset(&msg, 0, sizeof msg); crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)); crmsg = stat_alloc(crmsgsize); memset(crmsg, 0, crmsgsize); msg.msg_control = crmsg; msg.msg_controllen = crmsgsize; msg.msg_iov = &iov; msg.msg_iovlen = 1; iov.iov_base = &buf; iov.iov_len = 1; if (recvmsg(Int_val(fd), &msg, MSG_PEEK) < 0) { stat_free(crmsg); uerror("recvmsg", Nothing); }; if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) { stat_free(crmsg); raise_not_found(); }; cmp = CMSG_FIRSTHDR(&msg); if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDS) { stat_free(crmsg); raise_not_found(); }; sc = (struct sockcred *)(void *)CMSG_DATA(cmp); uid = sc->sc_euid; gid = sc->sc_egid; free(crmsg); } #else invalid_argument("peek_peer_credentials"); #endif #endif /* Allocate a pair, and put the result into it: */ result = alloc_tuple(2); Store_field(result, 0, Val_int(uid)); Store_field(result, 1, Val_int(gid)); CAMLreturn(result); }
read_JPEG_file (value name) { CAMLparam1(name); CAMLlocal1(res); char *filename; /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; /* More stuff */ FILE * infile; /* source file */ JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ int i; filename= String_val( name ); /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if ((infile = fopen(filename, "rb")) == NULL) { failwith("failed to open jpeg file"); } /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ fprintf(stderr, "Exiting..."); jpeg_destroy_decompress(&cinfo); fclose(infile); exit(-1); failwith(jpg_error_message); } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src(&cinfo, infile); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ cinfo.out_color_space = JCS_RGB; /* Step 5: Start decompressor */ (void) jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ if( oversized(cinfo.output_width, cinfo.output_components) ){ jpeg_destroy_decompress(&cinfo); fclose(infile); failwith_oversized("jpeg"); } row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, cinfo.output_height ); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ jpeg_read_scanlines(&cinfo, buffer + cinfo.output_scanline, 1); } if( oversized(row_stride, cinfo.output_height) ){ jpeg_destroy_decompress(&cinfo); fclose(infile); failwith_oversized("jpeg"); } { CAMLlocalN(r,3); r[0] = Val_int(cinfo.output_width); r[1] = Val_int(cinfo.output_height); r[2] = alloc_string ( row_stride * cinfo.output_height ); for(i=0; i<cinfo.output_height; i++){ memcpy( String_val(r[2]) + i * row_stride, buffer[i], row_stride); } res = alloc_tuple(3); for(i=0; i<3; i++) Field(res, i) = r[i]; } /* Step 7: Finish decompression */ (void) jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ /* And we're done! */ CAMLreturn(res); }
value ml_getrlimit(value resource) { #ifdef HAVE_GETRLIMIT CAMLparam1(resource); CAMLlocal1(retval); int r; struct rlimit lim; switch (Int_val(resource)) { case 0: #ifdef RLIMIT_CPU r = RLIMIT_CPU; #else r = -1; #endif break; case 1: #ifdef RLIMIT_FSIZE r = RLIMIT_FSIZE; #else r = -1; #endif break; case 2: #ifdef RLIMIT_DATA r = RLIMIT_DATA; #else r = -1; #endif break; case 3: #ifdef RLIMIT_STACK r = RLIMIT_STACK; #else r = -1; #endif break; case 4: #ifdef RLIMIT_CORE r = RLIMIT_CORE; #else r = -1; #endif break; case 5: #ifdef RLIMIT_RSS r = RLIMIT_RSS; #else r = -1; #endif break; case 6: #ifdef RLIMIT_NPROC r = RLIMIT_NPROC; #else r = -1; #endif break; case 7: #ifdef RLIMIT_NOFILE r = RLIMIT_NOFILE; #elif RLIMIT_OFILE r = RLIMIT_OFILE: #else r = -1; #endif break; case 8: #ifdef RLIMIT_MEMLOCK r = RLIMIT_MEMLOCK; #else r = -1; #endif break; case 9: #ifdef RLIMIT_AS r = RLIMIT_AS; #else r = -1; #endif break; default: errno = EINVAL; uerror("getrlimit", Nothing); } if (getrlimit(r, &lim) < 0) uerror("getrlimit", Nothing); retval = alloc_tuple(2); Field(retval, 0) = Val_int(lim.rlim_cur); Field(retval, 1) = Val_int(lim.rlim_max); CAMLreturn(retval); #else failwith("getrlimit unimplemented"); #endif }
value xdiff_revpatch( value old_data, value patch) { CAMLparam2 (old_data, patch); CAMLlocal1(res); mmfile_t mf1, mf2, mf3, mf4; xdemitcb_t ecb, rjecb; long new_size, rej_size; res = alloc_tuple(2); if (xdlt_store_mmfile(String_val(old_data), string_length(old_data), &mf1) < 0) { sprintf(ELINE, "%s:%d failed", __FILE__, __LINE__); failwith(ELINE); } if (xdlt_store_mmfile(String_val(patch), string_length(patch), &mf2) < 0) { xdl_free_mmfile(&mf1); sprintf(ELINE, "%s:%d failed", __FILE__, __LINE__); failwith(ELINE); } if (xdl_init_mmfile(&mf3, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { xdl_free_mmfile(&mf1); xdl_free_mmfile(&mf2); sprintf(ELINE, "%s:%d failed", __FILE__, __LINE__); failwith(ELINE); } if (xdl_init_mmfile(&mf4, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { xdl_free_mmfile(&mf1); xdl_free_mmfile(&mf2); xdl_free_mmfile(&mf3); sprintf(ELINE, "%s:%d failed", __FILE__, __LINE__); failwith(ELINE); } ecb.priv = &mf3; ecb.outf = xdlt_outf; rjecb.priv = &mf4; rjecb.outf = xdlt_outf; if (xdl_patch(&mf1, &mf2, XDL_PATCH_REVERSE, &ecb, &rjecb) < 0) { xdl_free_mmfile(&mf1); xdl_free_mmfile(&mf2); xdl_free_mmfile(&mf3); xdl_free_mmfile(&mf4); sprintf(ELINE, "%s:%d failed", __FILE__, __LINE__); failwith(ELINE); } new_size = xdlt_mmfile_size(&mf3); rej_size = xdlt_mmfile_size(&mf4); Field(res, 0) = alloc_string(new_size); Field(res, 1) = alloc_string(rej_size); if (xdlt_read_mmfile(String_val(Field(res, 0)), &mf3) < 0) { xdl_free_mmfile(&mf1); xdl_free_mmfile(&mf2); xdl_free_mmfile(&mf3); xdl_free_mmfile(&mf4); sprintf(ELINE, "%s:%d failed", __FILE__, __LINE__); failwith(ELINE); } if (xdlt_read_mmfile(String_val(Field(res, 1)), &mf4) < 0) { xdl_free_mmfile(&mf1); xdl_free_mmfile(&mf2); xdl_free_mmfile(&mf3); xdl_free_mmfile(&mf4); sprintf(ELINE, "%s:%d failed", __FILE__, __LINE__); failwith(ELINE); } xdl_free_mmfile(&mf1); xdl_free_mmfile(&mf2); xdl_free_mmfile(&mf3); xdl_free_mmfile(&mf4); CAMLreturn(res); }
value netsys_get_peer_credentials(value fd) { CAMLparam1(fd); CAMLlocal1(result); #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED) uid_t uid; gid_t gid; #else int uid; int gid; #endif #if defined(HAVE_GETPEEREID) /* BSD, AIX, Cygwin */ /* http://cr.yp.to/docs/secureipc.html */ if (getpeereid(Int_val(fd), &uid, &gid) != 0) { uerror("getpeereid", Nothing); } #elif defined(SO_PEERCRED) /* Linux */ { socklen_t len; struct ucred credentials; len = sizeof(struct ucred); if (getsockopt(Int_val(fd), SOL_SOCKET, SO_PEERCRED, &credentials, &len) == -1) { uerror("getsockopt",Nothing); }; uid = credentials.uid; /* Effective user ID */ gid = credentials.gid; /* Effective group ID */ } #elif defined(HAVE_GETPEERUCRED) /* Solaris */ { ucred_t *ucred; ucred = NULL; /* must be initialized to NULL */ if (getpeerucred(Int_val(fd), &ucred) == -1) { uerror("getpeerucred",Nothing); }; if ((uid = ucred_geteuid(ucred)) == -1) { uerror("ucred_geteuid",Nothing); ucred_free(ucred); }; if ((gid = ucred_getegid(ucred)) == -1) { uerror("ucred_getegid",Nothing); ucred_free(ucred); }; ucred_free(ucred); } #else invalid_argument("get_peer_credentials"); #endif /* Allocate a pair, and put the result into it: */ result = alloc_tuple(2); Store_field(result, 0, Val_int(uid)); Store_field(result, 1, Val_int(gid)); CAMLreturn(result); }
s->sockaddr_inet.sin_addr.s_addr = *((s_addr_t*) Mlsaddr_sapval(sinaddrport)); /* Maybe this should be htonl? / sestoft */ s->sockaddr_inet.sin_port = htons(Int_val(Port_sapval(sinaddrport))); break; } } } /* Warning: allocates in the heap, may cause a GC */ /* ML result type: addr */ static value newaddr(int len, int namespace, value addrdata) { value res; Push_roots(r,1) r[0] = addrdata; res = alloc_tuple(3); Data_addrval(res) = r[0]; Size_addrval(res) = Val_int(len); Nspace_addrval(res) = Val_int(namespace); Pop_roots(); return (value) res; } /* Warning: allocates in the heap, may cause a GC */ /* Return type: sinaddrport = int * ml_s_addr */ value newsinaddrport(s_addr_t sa, value port) { value res; Push_roots(r,1); r[0] = alloc_tuple(2); Field(r[0], 0) = 0; /* to please the gc */
CAMLprim value open_jpeg_file_for_read_start(value jpegh) { CAMLparam1(jpegh); CAMLlocal1(res); struct jpeg_decompress_struct* cinfop; struct my_error_mgr *jerrp; FILE *infile; int i; cinfop = (struct jpeg_decompress_struct *) Field(jpegh, 0); infile = (FILE *) Field(jpegh, 1); jerrp = (struct my_error_mgr *) Field(jpegh, 2); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ cinfop->out_color_space = JCS_RGB; /* Step 5: Start decompressor */ (void) jpeg_start_decompress(cinfop); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ /* row_stride = cinfop->output_width * cinfop->output_components; */ { CAMLlocalN(r,3); // CR jfuruse: integer overflow r[0] = Val_int(cinfop->output_width); r[1] = Val_int(cinfop->output_height); r[2] = alloc_tuple(3); Field(r[2], 0) = (value)cinfop; Field(r[2], 1) = (value)infile; Field(r[2], 2) = (value)jerrp; res = alloc_tuple(3); for(i=0; i<3; i++) Field(res, i) = r[i]; } #ifdef DEBUG_JPEG fprintf(stderr, "cinfop= %d infile= %d %d %d \n", cinfop, infile, cinfop->output_scanline, cinfop->output_height); fflush(stderr); #endif CAMLreturn(res); }
CAMLprim value open_jpeg_file_for_read(value name) { CAMLparam1(name); CAMLlocal1(res); char *filename; /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct* cinfop; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr *jerrp; /* More stuff */ FILE * infile; /* source file */ int i; filename= String_val(name); if ((infile = fopen(filename, "rb")) == NULL) { failwith("failed to open jpeg file"); } cinfop = malloc(sizeof (struct jpeg_decompress_struct)); jerrp = malloc(sizeof (struct my_error_mgr)); /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfop->err = jpeg_std_error(&jerrp->pub); jerrp->pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerrp->setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress(cinfop); free(jerrp); fclose(infile); failwith(jpg_error_message); } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(cinfop); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src(cinfop, infile); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header(cinfop, TRUE); { CAMLlocalN(r,3); r[0] = Val_int(cinfop->image_width); r[1] = Val_int(cinfop->image_height); r[2] = alloc_tuple(3); Field(r[2], 0) = (value)cinfop; Field(r[2], 1) = (value)infile; Field(r[2], 2) = (value)jerrp; res = alloc_tuple(3); for(i=0; i<3; i++) Field(res, i) = r[i]; } CAMLreturn(res); }
value mkexn0val(value exnname) { value exnval = alloc_tuple(2); modify(&Field(exnval, 0), Field(global_data, exnname)); modify(&Field(exnval, 1), Val_unit); return exnval; }
EXTERNML value msocket_rtsignals(value dummy) { value res = alloc_tuple(2); Field(res, 0) = Val_long(SIGRTMIN); Field(res, 1) = Val_long(SIGRTMAX); return res; }