📄 stdio.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)stdio.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/* * Copyright (c) 1988 Sun Microsystems, Inc. */#include <nse/param.h>#include <nse/stdio.h>#include <nse/util.h>#include <errno.h>#include <sys/stat.h>#include <sys/dir.h>static Nse_err write_error();static Nse_err file_size();/* * Wrapper routines which call the standard stdio library routines and * return an Nse_err struct if a read/write error occurs. */Nse_errnse_fclose(path, stream) char *path; FILE *stream;{ if (EOF == fclose(stream)) { /* * fclose should only fail for streams that have been * written to (because the close will force the kernel to * flush all modified buffers for the file, and this delayed * write may fail.) */#ifdef SUN_OS_4 /* * XXX Get around SunOS 4.0 bug which causes spurious error * return by close(2). (Bug ID 1010171) */ if (errno == -98) { return NULL; }#endif SUN_OS_4 return nse_err_format_errno("Write (fclose) to \"%s\"", path); } else { return NULL; }}Nse_errnse_fflush(path, stream) char *path; FILE *stream;{ if (EOF == fflush(stream)) { return write_error(path, stream, "fflush"); } else { return NULL; }}/* * The character read is returned in '*cp'. EOF is returned at * end-of-file. */Nse_errnse_fgetc(path, stream, cp) char *path; FILE *stream; int *cp;{ *cp = fgetc(stream); if (*cp == EOF && ferror(stream)) { return nse_err_format_errno("Read (fgetc) from \"%s\"", path); } return NULL;}/* * '*eofp' is returned as TRUE when end-of-file reached. */Nse_errnse_fgets(path, buf, n, stream, eofp) char *path; char *buf; int n; FILE *stream; bool_t *eofp;{ if (fgets(buf, n, stream) == NULL) { *eofp = TRUE; if (ferror(stream)) { return nse_err_format_errno("Read (fgets) from \"%s\"", path); } } else { *eofp = FALSE; } return NULL;}Nse_errnse_fopen(path, mode, filep) char *path; char *mode; FILE **filep;{ *filep = fopen(path, mode); if (*filep) { return NULL; } if (NSE_STREQ(mode, "w") || NSE_STREQ(mode, "a")) { return nse_err_format_errno("Open of \"%s\" for writing", path); } else if (errno == ENOENT) { /* * Not an error if the file doesn't exist when * opening for read or update. */ return NULL; } else if (NSE_STREQ(mode, "r")) { return nse_err_format_errno("Open of \"%s\" for reading", path); } else { return nse_err_format_errno( "Open of \"%s\" for reading and writing", path); }}/* VARARGS3 */Nse_errnse_fprintf(path, stream, format, a1, a2, a3, a4, a5, a6, a7, a8, a9) char *path; FILE *stream; char *format; int a1, a2, a3, a4, a5, a6, a7, a8, a9;{ if (EOF == fprintf(stream, format, a1, a2, a3, a4, a5, a6, a7, a8, a9)) { return write_error(path, stream, "fprintf"); } else { return NULL; }}/* * Returns, in *countp, the value returned by fprintf (the number of * characters printed.) *//* VARARGS4 */Nse_errnse_fprintf_value(countp, path, stream, format, a1, a2, a3, a4, a5, a6, a7, a8, a9) int *countp; char *path; FILE *stream; char *format; int a1, a2, a3, a4, a5, a6, a7, a8, a9;{ int cc; cc = fprintf(stream, format, a1, a2, a3, a4, a5, a6, a7, a8, a9); if (cc == EOF) { return write_error(path, stream, "fprintf"); } else { *countp = cc; return NULL; }}Nse_errnse_fputc(path, c, stream) char *path; char c; FILE *stream;{ if (EOF == fputc(c, stream)) { return write_error(path, stream, "fputc"); } else { return NULL; }}Nse_errnse_fputs(path, buf, stream) char *path; char *buf; FILE *stream;{ if (EOF == fputs(buf, stream)) { return write_error(path, stream, "fputs"); } else { return NULL; }}/* * Returns, in *countp, the value returned by fscanf (the number of items * read in.) *countp will be returned as EOF when end-of-file is reached. *//* VARARGS4 */Nse_errnse_fscanf(path, countp, stream, format, a1, a2, a3, a4, a5, a6, a7, a8, a9) char *path; int *countp; FILE *stream; char *format; int a1, a2, a3, a4, a5, a6, a7, a8, a9;{ *countp = fscanf(stream, format, a1, a2, a3, a4, a5, a6, a7, a8, a9); if (*countp == EOF && ferror(stream)) { return nse_err_format_errno("Read (fscanf) from \"%s\"", path); } else { return NULL; }}/* * This routine is called when a write routine returns EOF. Standard * stdio routines can return EOF with ferror() FALSE (and errno = 0) * if the stream wasn't opened for writing, so handle that condition * here. */static Nse_errwrite_error(path, stream, type) char *path; FILE *stream; char *type;{ if (!ferror(stream)) { /* * Return the error code that write(2) returns when called * on an fd that wasn't opened for writing. */ errno = EBADF; } return nse_err_format_errno("Write (%s) to \"%s\"", type, path);}Nse_errnse_readdir(path, dirp, dpp) char *path; DIR *dirp; struct direct **dpp;{ errno = 0; *dpp = readdir(dirp); if (*dpp == NULL && errno != 0) { return nse_err_format_errno("Readdir of \"%s\"", path); } return NULL;}/* * Routines to safely rewrite small ( < 2048 bytes) files in place, which * avoid the overhead of opening a tmp file and then renaming it to the * real file. These routines ensure that the integrity of the file is * preserved if the file system fills up while trying to write the file. * The safe way to do this is to write the file to a tmp file, then rename * the tmp file to the real file only after the tmp file has been written * successfully. If the file to be written is a short file, we can do * better than this. If the whole contents of the file fit within one * buffer, then the write can be done in place. This is because only one * write will be necessary, and if this write fails, the original file will * be left intact. (This is faster than writing to a tmp file, and also * has less likelihood of failing when the filesystem fills up.) * * These routines are useful in cases where the file must be rewritten * (instead of appended to.) The client must keep track of the number of * characters written to the file, and pass the new size into * nse_safe_file_close(). Additionally, any routines which read files * created with these routines must check for NULL characters in the file * -- a NULL character indicates EOF (see comment in * nse_safe_file_close().) */#define BUF_LEN 2048/* * Will file be too big to fit within one buffer? Assume here that at most * one line will be added to the file, and that no line in the file will be * longer than 200 characters. */#define FILE_TOO_BIG(size) (size > BUF_LEN - 200)/* * If '*filep' is NULL, opens the file 'path' and returns the file pointer * in '*filep'; otherwise uses the pre-opened file. The size of the file * (for use in nse_safe_write_close()) is returned in 'old_sizep'. */Nse_errnse_safe_write_open(path, filep, old_sizep) char *path; FILE **filep; long *old_sizep;{ Nse_err err; if (err = file_size(path, *filep, old_sizep)) { return err; } if (!FILE_TOO_BIG(*old_sizep)) { if (!*filep) { if (err = nse_file_open(path, "a", filep)) { return err; } } rewind(*filep); return NULL; } else { if (*filep && (err = nse_fclose(path, *filep))) { return err; } strcat(path, ".tmp"); err = nse_file_open(path, "w", filep); *rindex(path, '.') = '\0'; return err; }}Nse_errnse_safe_write_close(path, file, size, old_size) char *path; FILE *file; long size; long old_size;{ Nse_err err; if (!FILE_TOO_BIG(old_size)) { if (size < old_size) { /* * If the file will be shorter than it used to be, * it needs to be truncated to its new length. To * always leave the file in a consistent state, we * flush the buffer before truncating the file. * Since we stick a NULL character at the end of * the buffer before flushing it, we can recover * if the write happens but the ftruncate doesn't. * In such a case, the file can have some junk * at the end after the NULL. This will not be * a problem as long as input routines check for * NULL's in the file, as tfs_fgets() does. */ if ((err = nse_fputc(path, '\0', file)) || (err = nse_fflush(path, file))) { fclose(file); return err; } if (ftruncate(fileno(file), size) < 0) { err = nse_err_format_errno( "Write to \"%s\" (ftruncate)", path); fclose(file); return err; } } if (err = nse_fclose(path, file)) { return err; } } else { char path_tmp[MAXPATHLEN]; strcpy(path_tmp, path); strcat(path_tmp, ".tmp"); if (err = nse_fclose(path_tmp, file)) { (void) unlink(path_tmp); return err; } if (rename(path_tmp, path) < 0) { return nse_err_format_errno( "Rename of \"%s\" to \"%s\"", path_tmp, path); } } return NULL;}/* * Open a file with a stdio buffer of size BUF_LEN. */Nse_errnse_file_open(path, mode, filep) char *path; char *mode; FILE **filep;{ static char *buf; Nse_err err; if (err = nse_fopen(path, mode, filep)) { return err; } else if (*filep) { if (buf == NULL) { buf = malloc((unsigned) BUF_LEN); } setbuffer(*filep, buf, BUF_LEN); } return NULL;}static Nse_errfile_size(path, file, sizep) char *path; FILE *file; long *sizep;{ struct stat statb; int result; if (file) { result = fstat(fileno(file), &statb); } else { result = lstat(path, &statb); } if (result == 0) { *sizep = statb.st_size; } else if (errno == ENOENT) { *sizep = 0; } else { return nse_err_format_errno("Stat of \"%s\"", path); } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -