ram_file_drv.c

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

C
712
字号
	if (len > f->end-cur) len = f->end - cur;    } else {	len = 0; /* eof */    }    if ((bin = driver_alloc_binary(len)) == NULL) {	*error = ENOMEM;	return -1;    }    if (len) sys_memcpy(bin->orig_bytes, f->buf+cur, len);    *bp = bin;    if (! location) f->cur = cur + len;    return len;}static int ram_file_seek(RamFile *f, int offset, int whence, int *error){    int pos;    if (f->flags == 0) {	*error = EBADF;	return -1;    }	    switch(whence) {    case RAM_FILE_SEEK_SET: pos = offset; break;    case RAM_FILE_SEEK_CUR: pos = f->cur + offset; break;    case RAM_FILE_SEEK_END: pos = f->end + offset; break;    default: *error = EINVAL; return -1;    }    if (pos < 0) {	*error = EINVAL;	return -1;    }    return f->cur = pos;}#define UUMASK(x)     ((x)&0x3F)#define uu_encode(x)  (UUMASK(x)+32)/* calculate max number of quadrauple bytes given max line length */#define UULINE(n) ( (((n)-1) / 4) * 3)#define UNIX_LINE 61  /* 61 character lines =>  45 uncoded => 60 coded */#define uu_pack(p, c1, c2, c3) \        (p)[0] = uu_encode((c1) >> 2), \        (p)[1] = uu_encode(((c1) << 4) | ((c2) >> 4)), \        (p)[2] = uu_encode(((c2) << 2) | ((c3) >> 6)), \        (p)[3] = uu_encode(c3)static int ram_file_uuencode(RamFile *f){    int code_len = UULINE(UNIX_LINE);    int len = f->end;    int usize = (len*4+2)/3 + 2*(len/code_len+1) + 2 + 1;    ErlDrvBinary* bin;    uchar* inp;    uchar* outp;    int count = 0;    if ((bin = driver_alloc_binary(usize)) == NULL)	return error_reply(f, ENOMEM);    outp = (unsigned char*)bin->orig_bytes;    inp = f->buf;    while(len > 0) {        int c1, c2, c3;        int n = (len >= code_len) ? code_len : len;        len -= n;        *outp++ = uu_encode(UUMASK(n));        count++;        while (n >= 3) {            c1 = inp[0];            c2 = inp[1];            c3 = inp[2];	    uu_pack(outp, c1, c2, c3);            inp += 3; n -= 3;            outp += 4; count += 4;        }        if (n == 2) {            c1 = inp[0];            c2 = inp[1];	    uu_pack(outp, c1, c2, 0);	    inp += 2;            outp += 4; count += 4;        }        else if (n == 1) {            c1 = inp[0];	    uu_pack(outp, c1, 0, 0);	    inp += 1;            outp += 4; count += 4;        }        *outp++ = '\n';        count++;    }    *outp++ = ' ';   /* this end of file 0 length !!! */    *outp++ = '\n';    count += 2;    driver_free_binary(f->bin);    ram_file_set(f, bin, usize, count);    return numeric_reply(f, count);}#define uu_decode(x)  ((x)-32)static int ram_file_uudecode(RamFile *f){    int len = f->end;    int usize = ( (len+3) / 4 ) * 3;    ErlDrvBinary* bin;    uchar* inp;    uchar* outp;    int count = 0;    int n;    if ((bin = driver_alloc_binary(usize)) == NULL)	return error_reply(f, ENOMEM);    outp = (unsigned char*)bin->orig_bytes;    inp  = f->buf;    while(len > 0) {	if ((n = uu_decode(*inp++)) < 0)	    goto error;        len--;	if ((n == 0) && (*inp == '\n'))	    break;        count += n;     /* count characters */        while((n > 0) && (len >= 4)) {            int c1, c2, c3, c4;            c1 = uu_decode(inp[0]);            c2 = uu_decode(inp[1]);            c3 = uu_decode(inp[2]);            c4 = uu_decode(inp[3]);	    inp += 4;            len -= 4;            switch(n) {            case 1:                *outp++ = (c1 << 2) | (c2 >> 4);		n = 0;                break;            case 2:                *outp++ = (c1 << 2) | (c2 >> 4);                *outp++ = (c2 << 4) | (c3 >> 2);		n = 0;                break;            default:                *outp++ = (c1 << 2) | (c2 >> 4);                *outp++ = (c2 << 4) | (c3 >> 2);                *outp++ = (c3 << 6) | c4;                n -= 3;                break;            }        }	if ((n != 0) || (*inp++ != '\n'))	    goto error;        len--;    }    driver_free_binary(f->bin);    ram_file_set(f, bin, usize, count);    return numeric_reply(f, count); error:    driver_free_binary(bin);    return error_reply(f, EINVAL);}static int ram_file_compress(RamFile *f){    int size = f->end;    ErlDrvBinary* bin;    if ((bin = erts_gzdeflate_buffer(f->buf, size)) == NULL) {	return error_reply(f, EINVAL);    }    driver_free_binary(f->bin);    size = bin->orig_size;    ram_file_set(f, bin, size, size);    return numeric_reply(f, size);}/* Tricky since we dont know the expanded size !!! *//* First attempt is to double the size of input *//* loop until we don't get Z_BUF_ERROR */static int ram_file_uncompress(RamFile *f){    int size = f->end;    ErlDrvBinary* bin;    if ((bin = erts_gzinflate_buffer(f->buf, size)) == NULL) {	return error_reply(f, EINVAL);    }    driver_free_binary(f->bin);    size = bin->orig_size;    ram_file_set(f, bin, size, size);    return numeric_reply(f, size);}static void rfile_command(ErlDrvData e, char* buf, int count){    RamFile* f = (RamFile*)e;    int error = 0;    ErlDrvBinary* bin;    char header[5];     /* result code + count */    int offset;    int origin;		/* Origin of seek. */    int n;    count--;    switch(*(uchar*)buf++) {    case RAM_FILE_OPEN:  /* args is initial data */	f->flags = get_int32(buf);	if (ram_file_init(f, buf+4, count-4, &error) < 0)	    error_reply(f, error);	else	    numeric_reply(f, 0); /* 0 is not used */	break;    case RAM_FILE_FSYNC:	if (f->flags == 0)	    error_reply(f, EBADF);	else	    reply(f, 1, 0);	break;    case RAM_FILE_WRITE:	if (ram_file_write(f, buf, count, NULL, &error) < 0)	    error_reply(f, error);	else	    numeric_reply(f, count);	break;    case RAM_FILE_PWRITE:        if ((offset = get_int32(buf)) < 0)	    error_reply(f, EINVAL);	else if (ram_file_write(f, buf+4, count-4, &offset, &error) < 0)	    error_reply(f, error);	else	    numeric_reply(f, count-4);	break;    case RAM_FILE_LSEEK:	offset = get_int32(buf);	origin = get_int32(buf+4);	if ((offset = ram_file_seek(f, offset, origin, &error)) < 0)	    error_reply(f, error);	else	    numeric_reply(f, offset);	break;    case RAM_FILE_PREAD:	if ((offset = get_int32(buf)) < 0) {	    error_reply(f, EINVAL);	    break;	}		count = get_int32(buf+4);	if ((n = ram_file_read(f, count, &bin, &offset, &error)) < 0) {	    error_reply(f, error);	} else {	    header[0] = RAM_FILE_RESP_DATA;	    put_int32(n, header+1);	    driver_output_binary(f->port, header, sizeof(header),				 bin, 0, n);	    driver_free_binary(bin);	}	break;    case RAM_FILE_READ:	count = get_int32(buf);	if ((n = ram_file_read(f, count, &bin, NULL, &error)) < 0)	    error_reply(f, error);	else {	    header[0] = RAM_FILE_RESP_DATA;	    put_int32(n, header+1);	    driver_output_binary(f->port, header, sizeof(header),				 bin, 0, n);	    driver_free_binary(bin);	}	break;    case RAM_FILE_TRUNCATE:	if (!(f->flags & RAM_FILE_MODE_WRITE)) {	    error_reply(f, EACCES);	    break;	}	if (f->end > f->cur)	    sys_memzero(f->buf + f->cur, f->end - f->cur);	f->end = f->cur;	reply(f, 1, 0);	break;    case RAM_FILE_GET:        /* return a copy of the file */	n = f->end;  /* length */	if ((bin = driver_alloc_binary(n)) == NULL) {	    error_reply(f, ENOMEM);	    break;	}	sys_memcpy(bin->orig_bytes, f->buf, n);		header[0] = RAM_FILE_RESP_DATA;	put_int32(n, header+1);	driver_output_binary(f->port, header, sizeof(header),			     bin, 0, n);	driver_free_binary(bin);	break;    case RAM_FILE_GET_CLOSE:  /* return the file and close driver */	n = f->end;  /* length */	bin = f->bin;	f->bin = NULL;  /* NUKE IT */	header[0] = RAM_FILE_RESP_DATA;	put_int32(n, header+1);	driver_output_binary(f->port, header, sizeof(header),			     bin, 0, n);	driver_free_binary(bin);	driver_failure(f->port, 0);	break;    case RAM_FILE_SIZE:	numeric_reply(f, f->end);	break;	    case RAM_FILE_SET:        /* re-init file with new data */	if ((n = ram_file_init(f, buf, count, &error)) < 0)	    error_reply(f, error);	else	    numeric_reply(f, n); /* 0 is not used */	break;	    case RAM_FILE_COMPRESS:   /* inline compress the file */	ram_file_compress(f);	break;    case RAM_FILE_UNCOMPRESS: /* inline uncompress file */	ram_file_uncompress(f);	break;    case RAM_FILE_UUENCODE:   /* uuencode file */	ram_file_uuencode(f);	break;	    case RAM_FILE_UUDECODE:   /* uudecode file */	ram_file_uudecode(f);	break;    }    /*     * Ignore anything else -- let the caller hang.     */}

⌨️ 快捷键说明

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