📄 diskwrit.c
字号:
/* ---------------------- DATA FILE WRITE ROUTINES ---------------------- *//* ------ designed by dpk, rpc & committee; coded by rpc ------------ *//* --------------------- Version 1.4 August 1988 --------------------- *//* ------------------------------------------------------------------------ *//* RELEASE NOTES: Version 1.1: Eliminated large fixed-size buffers for default values bywriting them after values were saved, rather than before. Eliminated largefixed-size buffers for saved values, by using malloc and realloc. Version 1.2: Added the auto error reporting feature. This feature isenabled or disabled via disk_io_erh(flag) which is in its own source file.Changed the algorithm for assigning buffers for saved values. Also fixed a fewsubtle bugs and made minor code changes. Version 1.3: Increased the amount of text in error reporting and changedit to print on stderr instead of stdout. Version 1.4: Fixed bug in end_block that made 0 length format file whenopen_type is 3.*/#include "diskio.h"#include <stdio.h>#include <strings.h>#include <sys/file.h>/* variable type definitions: * * TYPE # | C TYPE | # of BYTES | FORTRAN TYPE * -------------------------------------------------- * 1 | short | 2 | integer*2 * 2 | int | 4 | integer*4 * 3 | float | 4 | real*4 */static short bytes_in[] = { 2, 4, 4 }; /* number of bytes in the data types */#define MAX_BYTES_PER_VAL 4 /* must be set to max value of bytes_in[] */#define NUM_DATA_TYPES sizeof(bytes_in)/sizeof(bytes_in[0]) /* elements in bytes_in */struct file_data { char filename[MAX_FILENAME_LENG + 1]; /* file name, without extension */ int fd; /* file descriptor */ short format[2 + 2*MAX_VARS_PER_BLK]; /* block information */ char vnames[MAX_VARS_PER_BLK][MAX_VARNAME_LENG];/* variable names in block */ short open_type; /* file open type */ int bytes_p_blk; /* bytes per block */ short defined; /* =1 when block defined */ short var_count; /* inc when variable added */ };static struct file_data fd[MAX_FILES];struct variable_data { short number; /* number of values per block */ short bytes; /* number of bytes per value */ char *base_addr; /* pointer to location for first saved value */ short num_saved; /* number of values saved since last block end */ char *bufp; /* pointer to location for next saved value */ char def_val[MAX_BYTES_PER_VAL]; /* storage for default value */ };static struct variable_data vd[MAX_FILES * MAX_VARS_PER_BLK];#define PARAM_OK -999struct errs { char routine[20]; /* name of routine where error was */ char name[MAX_FILENAME_LENG+1]; /* filename or variable name */ int param; /* illegal argument of call in error */ };static struct errs ervar = { "", "", PARAM_OK };#define DFE ".sg_data"#define FFE ".sg_format"extern int errno;extern short auto_er; /* flag to enable/disable auto error report & halt */extern long lseek();extern char *malloc(), *realloc();extern char *strcat(), *strcpy(), *strncpy();/* ------------------------- OPEN FILE ROUTINE ------------------------- *//* DESCRIPTION: file_id = open_file ( filename, open_type ) This routine opens the file "filename" so that data may be written to it.The parameter "open_type" specifies the following: 1 - delete any prior contents of specified file 2 - append to prior contents of specified file 3 - if specified file doesn't exist: delete any prior contents if specified file does exist: don't open it and return an appropriate error messageReturned value: If there are no errors, the returned value is a file id which is used toidentify this open file when using several other of the disk write routines.A valid file id is >= 0. If an error occurs, the returned value is < 0.The following errors are detected: - file "filename" is already open - filename is too long - the number of files currently open is the maximum - could not create a format file - could not create a data file - could not open filename.sg_format for reading - could not open filename.sg_data for writing - file "filename" exists and open_type prohibits overwriting - invalid open_type*/open_file ( filename, open_type )char filename[];int open_type;{ int file_id, i, tempfd; char dname[MAX_FILENAME_LENG + sizeof(DFE)]; char fname[MAX_FILENAME_LENG + sizeof(FFE)]; strcpy(ervar.routine, "open_file"); strncpy(ervar.name, filename, MAX_FILENAME_LENG); strcat(ervar.name, "");/* * check to see if this file has already been opened: * NOTE: The first call relies on open_type set to 0 by the compiler */ for (i=0; i<MAX_FILES; i++) { if (fd[i].open_type != 0) /* this file_id is in use, so check name */ { if (strcmp(filename, fd[i].filename) == 0) /* file already open */ { if (auto_er) error_exit(-8); return(-8); } } }/* * look for the first available file_id: */ file_id = -1; for (i=0; i<MAX_FILES; i++) { if (fd[i].open_type == 0) /* this file_id is available */ { file_id = i; break; } } if (file_id == -1) /* all files are currently open */ { if (auto_er) error_exit(-1); return(-1); }/* * append the data and format extensions to requested filename: */ if (strlen(filename) > MAX_FILENAME_LENG) /* filename too long */ { if (auto_er) error_exit(-9); return(-9); } strcpy(dname, filename); strcat(dname, DFE); strcpy(fname, filename); strcat(fname, FFE); if (open_type == 1 || open_type == 3) /* new file or check for file */ { if ( (open_type==3) && (access(dname, F_OK)==0) ) /* file exists */ { if (auto_er) error_exit(-6); return(-6); }/* * create an empty format file (to be written in first end_block call): */ tempfd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (tempfd == -1) /* can't create format file */ { perror("The system call error in disk write is"); if (auto_er) error_exit(-2); return(-2); } close(tempfd); /* close the format file *//* * create an empty data file: */ tempfd = open(dname, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (tempfd == -1) /* can't create data file */ { perror("The system call error in disk write is"); if (auto_er) error_exit(-3); return(-3); } } else if (open_type == 2) /* append to file 'filename' */ { if (access(fname, R_OK) == -1) /* can't read format file */ { perror("The system call error in disk write is"); if (auto_er) error_exit(-4); return(-4); } tempfd = open(dname, O_WRONLY); /* open data file for writing */ if (tempfd == -1) /* couldn't open data file for writing */ { perror("The system call error in disk write is"); if (auto_er) error_exit(-5); return(-5); } lseek(tempfd, (long) 0 , 2); /* go to end of file to append */ } else /* invalid open_type */ { ervar.param = open_type; if (auto_er) error_exit(-7); return(-7); }/* * define the fd variables: */ strcpy(fd[file_id].filename, filename); fd[file_id].open_type = open_type; fd[file_id].fd = tempfd; fd[file_id].defined = 0; fd[file_id].var_count = 0; fd[file_id].bytes_p_blk = 0;/* * For each variable this file may have, set vd[i].bytes = 0. This enables * the error of saving before defining to be detected. */ for(i=0; i<MAX_VARS_PER_BLK; i++) vd[var_id_gen(file_id, i+1)].bytes = 0; return(file_id);}/* ---------------------- DEFINE VARIABLE ROUTINE ---------------------- *//* DESCRIPTION: var_id = def_variable ( file_id, name, type, number, def_val ) This routine defines parameters of a variable to be saved. Theparameters are the variable's name, data type, number per block, and defaultvalue. Variables may be defined until the first call to end_block, which endsthe variable definition process. The string used as the variable's name doesnot have to be the name the calling program uses to reference the variable'svalues. It can be some other string of the programmer's choosing. This nameis used to select the variable for reading by the disk read routines. It isalso used to select and label variables in SUNGRAPH. This routine does NOTcheck for duplication of variable names, so be sure that each file variable hasa unique name. The default value is a pointer to a variable that has beeninitialized to the desired default value. This variable must be of the typespecified in the argument list of this function (i.e. "type"). It is NOT apointer to a character string. The default value is written if the user savesfewer than "number" values per block. Returned value: When no error occurs, the returned value is a variable id which is usedto identify this variable when saving its values with the save variable routine.A valid variable id is >= 0. If an error occurs, the returned value is < 0.The following errors are detected: - 'file_id' is out of range - 'file_id' corresponds to an unopened file - the file variables have already been defined - invalid data type specified - invalid number of values specified - the maximum number of variables have already been defined - variable name is too long - could not get a buffer for saved values*/def_variable ( file_id, name, type, number, def_val )char name[], def_val[];int file_id, type, number;{ int i, var_id, var_num, var; char *base, *tpntr; strcpy(ervar.routine, "def_variable"); strncpy(ervar.name, name, MAX_FILENAME_LENG); strcat(ervar.name, "");/* * do the easy error checking: */ if (file_id < 0 || file_id >= MAX_FILES) /* invalid id */ { ervar.param = file_id; if (auto_er) error_exit(-11); return(-11); } if (fd[file_id].open_type == 0) /* file not open */ { ervar.param = file_id; if (auto_er) error_exit(-12); return(-12); } if (fd[file_id].defined == 1) /* all variables defined */ { if (auto_er) error_exit(-13); return(-13); } if (type < 1 || type > NUM_DATA_TYPES) /* invalid type */ { ervar.param = type; if (auto_er) error_exit(-14); return(-14); } if (number < 1 || number > MAX_VALUES_PER_VAR) /* invalid number */ { ervar.param = number; if (auto_er) error_exit(-15); return(-15); } if (fd[file_id].var_count == MAX_VARS_PER_BLK) /* too many variables */ { if (auto_er) error_exit(-16); return(-16); } if (strlen(name) > MAX_VARNAME_LENG) /* name too long */ { if (auto_er) error_exit(-17); return(-17); }/* * assign a variable id and set fd variables: */ var_num = 1 + fd[file_id].var_count++; var_id = var_id_gen( file_id, var_num ); fd[file_id].format[2*var_num] = type; fd[file_id].format[2*var_num+1] = number; fd[file_id].bytes_p_blk += bytes_in[type-1] * number; strcpy(&fd[file_id].vnames[var_num-1][0], name);/* * set vd variables: */ vd[var_id].number = number; vd[var_id].num_saved = 0; vd[var_id].bytes = bytes_in[type-1]; for (i=0; i<vd[var_id].bytes; i++) vd[var_id].def_val[i] = def_val[i];/* * allocate memory and assign base address: */ if (var_num == 1) /* first variable in this file */ { vd[var_id].base_addr = malloc( (unsigned) fd[file_id].bytes_p_blk); if (vd[var_id].base_addr == 0) /* couldn't get memory */ { if (auto_er) error_exit(-10); return(-10); } } else /* add a variable to the file */ { base = vd[var_id_gen(file_id, 1)].base_addr; tpntr = realloc(base, (unsigned) fd[file_id].bytes_p_blk); if (tpntr == 0) /* could not get memory */ { if (auto_er) error_exit(-10); return(-10); } if (tpntr != base) /* buffer was moved by realloc */ { /* so, move pointers for prior variables */ for (i=1; i<fd[file_id].var_count; i++) { var = var_id_gen(file_id, i); vd[var].base_addr += tpntr - base; vd[var].bufp += tpntr - base; } free(base); /* and release the old buffer */ } vd[var_id].base_addr = vd[var_id-1].base_addr + vd[var_id-1].bytes * vd[var_id-1].number; } vd[var_id].bufp = vd[var_id].base_addr; return(var_id);}/* ----------------------- SAVE VARIABLE ROUTINE ----------------------- *//* DESCRIPTION: status = save_variable ( var_id, values, num ) This routine saves values of a variable that has been defined. "values"is the array of which "num" values will be saved. The data type of the valuesarray must match that declared when the variable was defined. The routine doesNOT test for such a match. The number of values saved per call can be from 1to the number per block specified when the variable was defined via def_var.The total number of values saved per variable cannot exceed the number definedwhen the variable was defined. When saving a single value, be sure that"values" is a POINTER to that value.Returned value: The returned value indicates whether or not the routine encountered anerror. If no error occurs, the returned value is 0. If an error occurs, thereturned value is < 0.The following errors are detected: - attempt to save less than one variable - 'var_id' is out of range
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -