ram_file_drv.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 712 行 · 第 1/2 页

C
712
字号
/* ``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$ *//* * RAM File operations */#ifdef HAVE_CONFIG_H#  include "config.h"#endif/* Operations *//* defined "file" functions  */#define RAM_FILE_OPEN		1#define RAM_FILE_READ		2#define RAM_FILE_LSEEK		3#define RAM_FILE_WRITE		4#define RAM_FILE_FSYNC          9#define RAM_FILE_TRUNCATE      14#define RAM_FILE_PREAD         17#define RAM_FILE_PWRITE        18/* other operations */#define RAM_FILE_GET           30#define RAM_FILE_SET           31#define RAM_FILE_GET_CLOSE     32  /* get_file/close */#define RAM_FILE_COMPRESS      33  /* compress file */#define RAM_FILE_UNCOMPRESS    34  /* uncompress file */#define RAM_FILE_UUENCODE      35  /* uuencode file */#define RAM_FILE_UUDECODE      36  /* uudecode file */#define RAM_FILE_SIZE          37  /* get file size *//* possible new operations include:   DES_ENCRYPT   DES_DECRYPT   CRC-32, CRC-16, CRC-CCITT   IP-CHECKSUM*//* * Open modes for RAM_FILE_OPEN. */#define RAM_FILE_MODE_READ       1#define RAM_FILE_MODE_WRITE      2  /* Implies truncating file 				     * when used alone. */#define RAM_FILE_MODE_READ_WRITE 3/* * Seek modes for RAM_FILE_LSEEK. */#define	RAM_FILE_SEEK_SET	0#define	RAM_FILE_SEEK_CUR	1#define	RAM_FILE_SEEK_END	2/* Return codes */#define RAM_FILE_RESP_OK         0#define RAM_FILE_RESP_ERROR      1#define RAM_FILE_RESP_DATA       2#define RAM_FILE_RESP_NUMBER     3#define RAM_FILE_RESP_INFO       4#include <stdio.h>#include <ctype.h>#include <limits.h>#include "sys.h"#include "erl_driver.h"#include "zlib.h"#include "gzio.h"#ifndef NULL#define NULL ((void*)0)#endif#define BFILE_BLOCK  1024#define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \                      (((unsigned char*) (s))[1] << 16) | \                      (((unsigned char*) (s))[2] << 8)  | \                      (((unsigned char*) (s))[3]))#define put_int32(i, s) {((char*)(s))[0] = (char)((i) >> 24) & 0xff; \                        ((char*)(s))[1] = (char)((i) >> 16) & 0xff; \                        ((char*)(s))[2] = (char)((i) >> 8)  & 0xff; \                        ((char*)(s))[3] = (char)((i)        & 0xff);}#define get_int16(s) ((((unsigned char*)  (s))[0] << 8) | \                      (((unsigned char*)  (s))[1]))#define put_int16(i, s) {((unsigned char*)(s))[0] = ((i) >> 8) & 0xff; \                        ((unsigned char*)(s))[1] = (i)         & 0xff;}#define get_int8(s) ((((unsigned char*)  (s))[0] ))#define put_int8(i, s) { ((unsigned char*)(s))[0] = (i)         & 0xff;}typedef unsigned char uchar;static ErlDrvData rfile_start(ErlDrvPort, char*);static int rfile_init(void);static void rfile_stop(ErlDrvData);static void rfile_command(ErlDrvData, char*, int);struct erl_drv_entry ram_file_driver_entry = {    rfile_init,    rfile_start,    rfile_stop,    rfile_command,    NULL,    NULL,    "ram_file_drv"};/* A File is represented as a array of bytes, this array is   reallocated when needed. A possibly better implementation   whould be to have a vector of blocks. This may be implemented   when we have the commandv/driver_outputv*/typedef struct ram_file {    ErlDrvPort port;	/* the associcated port */    int flags;          /* flags read/write */    ErlDrvBinary* bin;  /* binary to hold binary file */    uchar* buf;         /* buffer start (in binary) */    int size;           /* buffer size (allocated) */    int cur;            /* current position in buffer */    int end;            /* end position in buffer */} RamFile;#ifdef LOADABLEstatic int rfile_finish(DriverEntry* drv){    return 0;}DriverEntry* driver_init(void *handle){    ram_file_driver_entry.handle = handle;    ram_file_driver_entry.driver_name = "ram_file_drv";    ram_file_driver_entry.finish = rfile_finish;    ram_file_driver_entry.init = rfile_init;    ram_file_driver_entry.start = rfile_start;    ram_file_driver_entry.stop = rfile_stop;    ram_file_driver_entry.output = rfile_command;    ram_file_driver_entry.ready_input = NULL;    ram_file_driver_entry.ready_output = NULL;    return &ram_file_driver_entry;}#endifstatic int rfile_init(void){    return 0;}static ErlDrvData rfile_start(ErlDrvPort port, char* buf){    RamFile* f;    if ((f = (RamFile*) driver_alloc(sizeof(RamFile))) == NULL)	return ERL_DRV_ERROR_GENERAL;    f->port = port;    f->flags = 0;    f->bin = NULL;    f->buf = NULL;    f->size = f->cur = f->end = 0;    return (ErlDrvData)f;}static void rfile_stop(ErlDrvData e){    RamFile* f = (RamFile*)e;    if (f->bin != NULL) 	driver_free_binary(f->bin);    driver_free(f);}/* * Sends back an error reply to Erlang. */static int error_reply(RamFile *f, int err){    char response[256];		/* Response buffer. */    char* s;    char* t;        /*     * Contents of buffer sent back:     *     * +-----------------------------------------+     * | RAM_FILE_RESP_ERROR | Posix error id string |     * +-----------------------------------------+     */    response[0] = RAM_FILE_RESP_ERROR;    for (s = erl_errno_id(err), t = response+1; *s; s++, t++)	*t = tolower(*s);    driver_output2(f->port, response, t-response, NULL, 0);    return 0;}static int reply(RamFile *f, int ok, int err){    if (!ok)	error_reply(f, err);    else {	char c = RAM_FILE_RESP_OK;        driver_output2(f->port, &c, 1, NULL, 0);    }    return 0;}static int numeric_reply(RamFile *f, int result){    char tmp[5];    /*     * Contents of buffer sent back:     *     * +-----------------------------------------------+     * | RAM_FILE_RESP_NUMBER | 32-bit number (big-endian) |     * +-----------------------------------------------+     */    tmp[0] = RAM_FILE_RESP_NUMBER;    put_int32(result, tmp+1);    driver_output2(f->port, tmp, sizeof(tmp), NULL, 0);    return 0;}/* install bin as the new binary reset all pointer */static void ram_file_set(RamFile *f, ErlDrvBinary *bin, int bsize, int len){    f->size = bsize;    f->buf = bin->orig_bytes;    f->cur = 0;    f->end = len;    f->bin = bin;}static int ram_file_init(RamFile *f, char *buf, int count, int *error){    int bsize;    ErlDrvBinary* bin;        if (count < 0) {	*error = EINVAL;	return -1;    }    if ((bsize = (count+BFILE_BLOCK+(BFILE_BLOCK>>1)) & ~(BFILE_BLOCK-1))	< 0) {	bsize = INT_MAX;    }    if (f->bin == NULL)	bin = driver_alloc_binary(bsize);    else 	bin = driver_realloc_binary(f->bin, bsize);    if (bin == NULL) {	*error = ENOMEM;	return -1;    }    sys_memzero(bin->orig_bytes, bsize);    sys_memcpy(bin->orig_bytes, buf, count);    ram_file_set(f, bin, bsize, count);    return count;}static int ram_file_expand(RamFile *f, int size, int *error){    int bsize;    ErlDrvBinary* bin;        if (size < 0) {	*error = EINVAL;	return -1;    }    if ((bsize = (size+BFILE_BLOCK+(BFILE_BLOCK>>1)) & ~(BFILE_BLOCK-1))	< 0) {	bsize = INT_MAX;    }        if (bsize <= f->size)	return f->size;    else {	if ((bin = driver_realloc_binary(f->bin, bsize)) == NULL) {	    *error = ENOMEM;	    return -1;	}	sys_memzero(bin->orig_bytes+f->size, bsize - f->size);	f->size = bsize;	f->buf = bin->orig_bytes;	f->bin = bin;	return bsize;    }}static int ram_file_write(RamFile *f, uchar *buf, int len, 			  int *location, int *error){    int cur = f->cur;        if (!(f->flags & RAM_FILE_MODE_WRITE)) {	*error = EBADF;	return -1;    }    if (location) cur = *location;    if (cur < 0 || len < 0 || cur+len < 0) {	*error = EINVAL;	return -1;    }    if (cur+len > f->size && ram_file_expand(f, cur+len, error) < 0) {	return -1;    }    if (len) sys_memcpy(f->buf+cur, buf, len);    cur += len;    if (cur > f->end) f->end = cur;    if (! location) f->cur = cur;    return len;}static int ram_file_read(RamFile *f, int len, ErlDrvBinary **bp, 			 int *location, int *error){    ErlDrvBinary* bin;    int cur = f->cur;        if (!(f->flags & RAM_FILE_MODE_READ)) {	*error = EBADF;	return -1;    }    if (location) cur = *location;    if (cur < 0 || len < 0) {	*error = EINVAL;	return -1;    }    if (cur < f->end) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?