📄 opentmp.c
字号:
#ifdef __DJGPP__
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <dos.h>
#include <libc/local.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <sys/fsext.h>
#include <sys/stat.h>
#include <stdarg.h>
#ifdef SHELL
#include "dosutil.h"
extern int debugging_login_shell;
#else
#include "opentmp.h"
#endif
extern int _dup(int);
extern int _dup2(int, int);
typedef unsigned char byte;
typedef struct
{
char * file;
byte ref_count_index;
} tmpfile_data;
#define HANDLE_MAX 255
#define REF_COUNT_ERROR 255
static byte ref_count[256];
static byte total_used;
static byte max_index;
static int fsext_handler (__FSEXT_Fnumber action, int *rv, va_list args);
static byte get_open_ref_count_index(void);
static void free_ref_count_index(byte);
/* Open a temporary file and set it up to be automatically deleted
it after it is closed. */
int _opentmp (const char *path, int flags, ...)
{
int fd;
va_list arg_list;
mode_t mode;
int arg_count;
if (flags & O_RDONLY)
flags |= O_EXCL;
arg_count = 0;
if (arg_count == 0)
fd = open(path, flags, S_IWUSR);
else
{
va_start(arg_list, flags);
mode = va_arg(arg_list, mode_t);
va_end(arg_list);
fd = open(path, flags, mode);
}
if (fd < 0)
return fd;
if (_remove_on_close(fd, path) < 0)
{
close(fd);
return -1;
}
return fd;
}
/* Obtain and fill in FILE struct so the file associated with the
descriptor is automatically removed when it is closed.
Does the dirty work for _opentmp. */
int _remove_on_close (int fd, const char *path)
{
char buffer[PATH_MAX];
FILE *f;
tmpfile_data *data;
__FSEXT_set_function (fd, fsext_handler);
/* Store an absolute path. */
_fixpath (path, buffer);
data = (tmpfile_data *)malloc (sizeof(tmpfile_data));
if (data == NULL)
return -1;
data->ref_count_index = get_open_ref_count_index();
if (data->ref_count_index == REF_COUNT_ERROR)
return -1;
ref_count[data->ref_count_index] = 1;
data->file = strdup (buffer);
__FSEXT_set_data (fd, (void *)data);
return 0;
}
/* Closes and removes a temporary file. */
static int _closetmp (int fd, tmpfile_data *data)
{
__file_rec *fr;
int index;
int ret;
int errno_save;
__FSEXT_set_data(fd, NULL); /* Prevent recursion. */
__FSEXT_set_function(fd, NULL);
if (!data)
{
errno = ENOENT;
return -1;
}
ret = _dos_close(fd);
errno_save = errno;
/* It is possible the handle has been dup()'ed.
If so, don't let the file be removed. */
if (--(ref_count[data->ref_count_index]) == 0)
{
errno = 0;
remove(data->file);
if (errno)
perror (data->file);
free_ref_count_index(data->ref_count_index);
}
errno = errno_save;
free(data);
return ret;
}
static int _duptmp (int fd, int new_fd, tmpfile_data *data)
{
tmpfile_data *new_data;
new_data = (tmpfile_data *)malloc (sizeof(tmpfile_data));
if (new_data == NULL)
return -1;
new_data->file = data->file;
new_data->ref_count_index = data->ref_count_index;
ref_count[new_data->ref_count_index] += 1;
__FSEXT_set_function(new_fd, fsext_handler);
__FSEXT_set_data(new_fd, (void *)new_data);
return 0;
}
static
int fsext_handler (__FSEXT_Fnumber action, int *rv, va_list args)
{
int handle = va_arg(args, int);
tmpfile_data *data;
if ((data = __FSEXT_get_data(handle)) == NULL)
return 0;
switch (action)
{
case __FSEXT_close:
{
*rv = _closetmp(handle, data);
return 1;
}
case __FSEXT_fcntl:
{
int ret_val;
unsigned third_arg;
int cmd;
__FSEXT_set_function(handle, NULL);
cmd = va_arg(args, int);
third_arg = va_arg(args, int);
ret_val = fcntl(handle, cmd, third_arg);
__FSEXT_set_function(handle, fsext_handler);
if ((cmd == F_DUPFD)
&& (ret_val < 0 || _duptmp(handle, ret_val, data) < 0))
*rv = -1;
else
*rv = ret_val;
return 1;
}
case __FSEXT_dup:
{
int to_handle;
to_handle = _dup(handle);
if (_duptmp(handle, to_handle, data) < 0)
{
_dos_close(to_handle);
*rv = -1;
}
else
*rv = to_handle;
return 1;
}
case __FSEXT_dup2:
{
int to_handle, ret;
to_handle = va_arg(args, int);
#if 0
close (to_handle);
#endif
ret = _dup2(handle, to_handle);
if (ret < 0 || _duptmp(handle, to_handle, data) < 0)
*rv = -1;
else
*rv = ret;
return 1;
}
default:
break;
}
return 0;
}
/* Find a free reference count index. */
static byte get_open_ref_count_index(void)
{
int i;
while (max_index > 0 && ref_count[max_index - 1] == 0)
--max_index;
if (max_index < HANDLE_MAX)
{
byte ref_index = max_index;
++max_index;
++total_used;
return ref_index;
}
if (total_used >= HANDLE_MAX)
return REF_COUNT_ERROR;
for (i = 0; i < HANDLE_MAX; i++)
{
if (ref_count[i] == 0)
{
++total_used;
return i;
}
}
return REF_COUNT_ERROR;
}
/* A reference count index has become free. */
static void free_ref_count_index(byte index)
{
if (ref_count[index] != 0)
abort();
--total_used;
while (max_index > 0 && ref_count[max_index - 1] == 0)
--max_index;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -