bin_drv.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 223 行
C
223 行
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ *//* Purpose: Binary file driver interface , used for code loading */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "sys.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include "erl_driver.h"#include <errno.h>#ifdef NO_UMASK#define FILE_MODE 0644#else#define FILE_MODE 0666#endifstatic int this_port;static long bin_start();static int bin_init(),bin_stop(),bin_erlang_read();static int read_fill(), write_fill();const struct erl_drv_entry bin_driver_entry = { bin_init, bin_start, bin_stop, bin_erlang_read, NULL, NULL, "binary_filer"};static int bin_init(){ this_port = -1;}static long bin_start(port,buf) int port;char *buf;{ if (this_port != -1) return(-1); this_port = port; return(port);}static int bin_stop(){ this_port = -1;} static int bin_erlang_read(port,buf,count)long port;char *buf;int count;{ struct stat statbuf; int i,size,fd,rval; char *t,*rbuf; buf[count] = '\0'; switch (*buf) { case 'c' : if (chdir(buf+1) == 0) /* sucsess */ driver_output(this_port,"y",1); else driver_output(this_port,"n",1); return 0; case 'f':#ifdef MSDOS if ((fd = open(buf+1,O_RDONLY|O_BINARY)) < 0) {#else if ((fd = open(buf+1,O_RDONLY, 0)) < 0) {#endif driver_output(this_port,"n",1); return 0; } if (stat(buf+1,&statbuf) < 0) { driver_output(this_port,"n",1); close(fd); return 0; } if (S_ISREG(statbuf.st_mode)) size = statbuf.st_size; else size = BUFSIZ; if ((rbuf = (char*) driver_alloc(1 + size)) == NULL) { fprintf(stderr,"Out of memory\n"); close(fd); driver_output(this_port,"n",1); return 0; } if (S_ISREG(statbuf.st_mode)) { if (read_fill(fd,1+rbuf,size) != size) { driver_free(rbuf); close(fd); driver_output(this_port,"n",1); return 0;; } } /* The idea here is that if it's a regular file read the entire * entire file and if it's a device file or a tty try to read * until errno != EINTR */ else { while (1) { rval = read(fd,1+rbuf,size); if (rval < 0 && errno == EINTR) continue; if (rval < 0) { driver_free(rbuf); close(fd); driver_output(this_port,"n",1); return 0; } size = rval; break; } } rbuf[0] = 'y'; driver_output(this_port,rbuf,1+size); driver_free(rbuf); close(fd); return 0; case 'w':#ifdef MSDOS if ((fd = open(buf+1, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, FILE_MODE)) < 0) {#else if ((fd = open(buf+1, O_WRONLY | O_CREAT | O_TRUNC, FILE_MODE)) < 0) {#endif driver_output(this_port,"n",1); return 0; } t = buf+1; i = 1; while(*t && i++ < count) t++; t++; /* t now points to the contents of what we shall write */ size = count - 1 - i; /* gotta write_fill if we are writing to a slow device such as /dev/audio */ if (write_fill (fd,t,size) != size) { driver_output(this_port,"n",1); close(fd); return 0; } driver_output(this_port,"y",1); close(fd); return 0; default: driver_failure(this_port,-1); return 0; }}static int write_fill(fd, buf, len)char *buf;{ int i, done = 0; do { if ((i = write(fd, buf+done, len-done)) < 0) { if (errno != EINTR) return (i); i = 0; } done += i; } while (done < len); return (len);}static int read_fill(fd, buf, len)char *buf;{ int i, got = 0; do { if ((i = read(fd, buf+got, len-got)) <= 0) { if (i == 0 || errno != EINTR) return (i); i = 0; } got += i; } while (got < len); return (len);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?