From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Thu, 22 Feb 2001 22:52:10 -0500 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: O_TEMPORARY v2 Message-ID: <3A95981A.14546.31CA2@localhost> X-mailer: Pegasus Mail for Win32 (v3.12c) Reply-To: djgpp-workers AT delorie DOT com Hello, Revision two of O_TEMPORARY support is ready for inspection. I've generalized the code to permit much more than O_TEMPORARY to be supported if desired. Support for handling a file opened with O_TEMPORARY and opened with or without O_TEMPORARY has been added. I also added caching so time isn't wasted allocating memory over and over to somewhat like how a FILE struct is allocated. I have tested this the following small program: #include #include #include const char temp_file[]="test.txt"; int main() { int fd, fd2, fd3, fd4; fd = open(temp_file, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR); fd2 = dup(fd); fd3 = dup2(fd, 127); fd4 = open(temp_file, O_RDWR | O_CREAT | O_TRUNC | O_TEMPORARY, S_IWUSR); write(fd, temp_file, sizeof(temp_file) - 1); close(fd); close(fd3); close(fd2); close(fd4); fd = open(temp_file, O_RDWR | O_CREAT | O_TRUNC | O_TEMPORARY, S_IWUSR); fd2 = dup(fd); fd3 = dup2(fd, 127); fd4 = open(temp_file, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR); write(fd, temp_file, sizeof(temp_file) - 1); close(fd); close(fd3); close(fd2); close(fd4); return 0; } *** /dev/null Thu Feb 22 00:41:21 2001 --- /djgpp/include/libc/fdprops.h Tue Feb 20 12:07:56 2001 *************** *** 0 **** --- 1,42 ---- + /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ + #ifndef __dj_include_libc_fdprops_h__ + #define __dj_include_libc_fdprops_h__ + + #ifdef __cplusplus + extern "C" { + #endif + + #ifndef __dj_ENFORCE_ANSI_FREESTANDING + + #ifndef __STRICT_ANSI__ + + #ifndef _POSIX_SOURCE + + /* Delete file when the last descriptor referencing it is closed. */ + #define FILE_DESC_TEMPORARY 1 + + typedef struct fd_properties fd_properties; + + typedef struct fd_properties + { + unsigned char ref_count; + unsigned long flags; + char *filename; + fd_properties *prev; + fd_properties *next; + }; + + int _set_fd_properties(int _fd, const char * _file, int _oflags); + void _dup_fd_properties(int _from, int _to); + + extern fd_properties ** __fd_properties; + + #endif /* !_POSIX_SOURCE */ + #endif /* !__STRICT_ANSI__ */ + #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + + #ifdef __cplusplus + } + #endif + + #endif /* __dj_include_libc_fdprops_h__ */ *** /dev/null Thu Feb 22 00:41:21 2001 --- fdprops.c Thu Feb 22 00:40:58 2001 *************** *** 0 **** --- 1,204 ---- + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + static void open_fd(fd_properties *fd, int open_flags); + static void close_fd(fd_properties *fd); + static fd_properties * find_eq_filename(const fd_properties *fd); + static fd_properties * alloc_fd_properties(); + static void free_fd_properties(fd_properties *); + static void insert_1ist(fd_properties **, fd_properties *); + static void remove_1ist(fd_properties **, fd_properties *); + + /* Array of pointers to fd_properties objects associated + with a file descriptor. */ + fd_properties **__fd_properties = NULL; + + /* 1ist of fd_properties objects associated with at least + one file descriptor. */ + static fd_properties *active_fds; + + /* 1ist of fd_properties objects currently not in use. */ + static fd_properties *cached_fds; + + static int old_bss_count; + + /* Set or clear the properties associated with a file descriptor. */ + int + _set_fd_properties(int fd, const char *file, int open_flags) + { + if (file) + { + char buffer[FILENAME_MAX + 1]; + int len; + + if (old_bss_count != __bss_count) + { + size_t size = 255 * sizeof(fd_properties *); + old_bss_count = __bss_count; + __fd_properties = malloc(size); + active_fds = NULL; + cached_fds = NULL; + if (__fd_properties == NULL) + return -1; + memset(__fd_properties, 0, size); + } + + _truename(file, buffer); + len = strlen(buffer); + __fd_properties[fd] = alloc_fd_properties(); + if (__fd_properties[fd] == NULL) + return -1; + + /* Initialize the object and insert it into 1ist. */ + __fd_properties[fd]->ref_count = 1; + __fd_properties[fd]->flags = 0; + __fd_properties[fd]->filename = strdup(buffer); + + insert_1ist(&active_fds, __fd_properties[fd]); + + open_fd(__fd_properties[fd], open_flags); + } + else + { + /* There are no properties with this descriptor. Punt. */ + if (__fd_properties[fd] == NULL) + return -1; + + if (--(__fd_properties[fd]->ref_count) == 0) + { + /* The last file descriptor using this object has closed. Perform + any final actions before the object is put into the cache. */ + close_fd(__fd_properties[fd]); + + free(__fd_properties[fd]->filename); + __fd_properties[fd]->filename = NULL; + free_fd_properties(__fd_properties[fd]); + } + __fd_properties[fd] = NULL; + } + return 0; + } + + /* Set properties of a file descriptor returned by dup or dup2. */ + void + _dup_fd_properties(int from, int to) + { + if (__fd_properties[from]) + { + __fd_properties[to] = __fd_properties[from]; + ++(__fd_properties[to]->ref_count); + } + } + + /* Perform file descriptor specific initialization. */ + static void + open_fd(fd_properties *cur_fd, int open_flags) + { + if (cur_fd->filename && open_flags & O_TEMPORARY) + cur_fd->flags |= FILE_DESC_TEMPORARY; + } + + /* Perform file descriptor specific finalization. */ + static void + close_fd(fd_properties *cur_fd) + { + /* Delete the file if no other descriptors use the file. Otherwise, + mark the other descriptor with the temporary flag. */ + if (cur_fd->flags & FILE_DESC_TEMPORARY) + { + fd_properties *ptr = find_eq_filename(cur_fd); + if (ptr) + ptr->flags |= FILE_DESC_TEMPORARY; + else + remove(cur_fd->filename); + } + } + + /* Find another properties object using the same filename. */ + static + fd_properties * find_eq_filename(const fd_properties *fd) + { + fd_properties *ptr = active_fds; + + while (ptr) + { + if ((ptr != fd) && (strcmp(fd->filename, ptr->filename) == 0)) + return ptr; + ptr = ptr->next; + } + return NULL; + } + + /* Return a properties object to be used with one or more file descriptors. + */ static fd_properties * alloc_fd_properties() { + fd_properties *ptr; + + if (cached_fds == NULL) + { + ptr = malloc(sizeof(fd_properties)); + if (ptr == NULL) + return ptr; + } + else + { + ptr = cached_fds; + remove_1ist(&cached_fds, cached_fds); + } + ptr->prev = NULL; + ptr->next = NULL; + ptr->ref_count = 1; + + return ptr; + } + + /* Remove the object from the active 1ist, and insert it into the cache. */ + static void free_fd_properties(fd_properties *fd) { + remove_1ist(&active_fds, fd); + insert_1ist(&cached_fds, fd); + } + + /* Insert a properties object into a 1ist. */ + static void + insert_1ist(fd_properties **head_ptr, fd_properties *item) + { + fd_properties *head = *head_ptr; + item->next = head; + item->prev = NULL; + if (head) + head->prev = item; + *head_ptr = item; + } + + /* Remove a properties object from a 1ist. */ + static void + remove_1ist(fd_properties **head_ptr, fd_properties *item) + { + fd_properties *head = *head_ptr; + + if (item->prev) + { + (item->prev)->next = item->next; + item->prev = NULL; + } + if (item->next) + { + (item->next)->prev = item->prev; + item->next = NULL; + } + if (head == item) + head = head->next; + + *head_ptr = head; + } *** open.c.orig Mon Aug 28 10:22:34 2000 --- open.c Mon Feb 19 20:20:04 2001 *************** *** 18,23 **** --- 18,24 ---- #include #include + #include /* Extra share flags that can be indicated by the user */ int __djgpp_share_flags; *************** open(const char* filename, int oflag, .. *** 152,157 **** --- 153,161 ---- if(oflag & O_APPEND) lseek(fd, 0, SEEK_END); + if (oflag) + _set_fd_properties(fd, real_name, oflag); + return fd; } *** _close.c.orig Thu Jan 1 19:12:50 1998 --- _close.c Mon Feb 19 20:18:16 2001 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include *************** *** 7,13 **** --- 8,16 ---- #include #include + #include #include + #include int _close(int handle) *************** _close(int handle) *** 37,41 **** --- 40,49 ---- errno = EBADF; return -1; } + + if (__fd_properties && __fd_properties[handle]) + _set_fd_properties(handle, NULL, 0); + return 0; } + *** dup.c.orig Sun Feb 26 19:43:08 1995 --- dup.c Mon Feb 19 20:19:18 2001 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include *************** *** 5,10 **** --- 6,12 ---- #include #include #include + #include int dup(int fd) *************** dup(int fd) *** 19,23 **** --- 21,29 ---- return -1; } setmode(r.x.ax, __file_handle_modes[fd]); + + if (__fd_properties && __fd_properties[fd]) + _dup_fd_properties(fd, r.x.ax); + return r.x.ax; } *** dup2.c.orig Sun Sep 29 06:20:56 1996 --- dup2.c Mon Feb 19 20:19:30 2001 *************** *** 1,3 **** --- 1,4 ---- + /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include *************** *** 7,12 **** --- 8,14 ---- #include #include #include + #include int dup2(int fd, int newfd) *************** dup2(int fd, int newfd) *** 25,29 **** --- 27,39 ---- return -1; } setmode(newfd, __file_handle_modes[fd]); + + if (__fd_properties) + { + if (__fd_properties[newfd]) + _set_fd_properties(newfd, NULL, 0); + _dup_fd_properties(fd, newfd); + } + return newfd; } *** /djgpp/include/fcntl.h.orig Wed Feb 14 14:30:06 2001 --- /djgpp/include/fcntl.h Sat Feb 10 11:24:04 2001 *************** int fcntl(int _fildes, int _cmd, ...); *** 77,82 **** --- 77,84 ---- #define O_NOLINK 0x4000 #define O_NOFOLLOW 0x8000 + #define O_TEMPORARY 0x10000 /* Delete file after closing. */ + #define SH_COMPAT 0x0000 #define SH_DENYRW 0x0010 #define SH_DENYWR 0x0020