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 + -
显示快捷键?