comctl32: toolbar: Fix buttons heights.
[wine.git] / server / fd.c
blob03347238caefe03ca8c64e7d7b4948e51182d815
1 /*
2 * Server-side file descriptor management
4 * Copyright (C) 2000, 2003 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <assert.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <limits.h>
29 #include <signal.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #ifdef HAVE_POLL_H
35 #include <poll.h>
36 #endif
37 #ifdef HAVE_SYS_POLL_H
38 #include <sys/poll.h>
39 #endif
40 #ifdef HAVE_LINUX_MAJOR_H
41 #include <linux/major.h>
42 #endif
43 #ifdef HAVE_SYS_STATVFS_H
44 #include <sys/statvfs.h>
45 #endif
46 #ifdef HAVE_SYS_VFS_H
47 #include <sys/vfs.h>
48 #endif
49 #ifdef HAVE_SYS_MOUNT_H
50 #include <sys/mount.h>
51 #endif
52 #ifdef HAVE_SYS_STATFS_H
53 #include <sys/statfs.h>
54 #endif
55 #ifdef HAVE_SYS_EVENT_H
56 #include <sys/event.h>
57 #undef LIST_INIT
58 #undef LIST_ENTRY
59 #endif
60 #ifdef HAVE_STDINT_H
61 #include <stdint.h>
62 #endif
63 #include <sys/stat.h>
64 #include <sys/time.h>
65 #include <sys/types.h>
66 #include <unistd.h>
68 #include "ntstatus.h"
69 #define WIN32_NO_STATUS
70 #include "object.h"
71 #include "file.h"
72 #include "handle.h"
73 #include "process.h"
74 #include "request.h"
76 #include "winternl.h"
78 #if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL_CREATE)
79 # include <sys/epoll.h>
80 # define USE_EPOLL
81 #elif defined(linux) && defined(__i386__) && defined(HAVE_STDINT_H)
82 # define USE_EPOLL
83 # define EPOLLIN POLLIN
84 # define EPOLLOUT POLLOUT
85 # define EPOLLERR POLLERR
86 # define EPOLLHUP POLLHUP
87 # define EPOLL_CTL_ADD 1
88 # define EPOLL_CTL_DEL 2
89 # define EPOLL_CTL_MOD 3
91 typedef union epoll_data
93 void *ptr;
94 int fd;
95 uint32_t u32;
96 uint64_t u64;
97 } epoll_data_t;
99 struct epoll_event
101 uint32_t events;
102 epoll_data_t data;
105 #define SYSCALL_RET(ret) do { \
106 if (ret < 0) { errno = -ret; ret = -1; } \
107 return ret; \
108 } while(0)
110 static inline int epoll_create( int size )
112 int ret;
113 __asm__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
114 : "=a" (ret) : "0" (254 /*NR_epoll_create*/), "r" (size) );
115 SYSCALL_RET(ret);
118 static inline int epoll_ctl( int epfd, int op, int fd, const struct epoll_event *event )
120 int ret;
121 __asm__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
122 : "=a" (ret)
123 : "0" (255 /*NR_epoll_ctl*/), "r" (epfd), "c" (op), "d" (fd), "S" (event), "m" (*event) );
124 SYSCALL_RET(ret);
127 static inline int epoll_wait( int epfd, struct epoll_event *events, int maxevents, int timeout )
129 int ret;
130 __asm__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
131 : "=a" (ret)
132 : "0" (256 /*NR_epoll_wait*/), "r" (epfd), "c" (events), "d" (maxevents), "S" (timeout)
133 : "memory" );
134 SYSCALL_RET(ret);
136 #undef SYSCALL_RET
138 #endif /* linux && __i386__ && HAVE_STDINT_H */
141 /* Because of the stupid Posix locking semantics, we need to keep
142 * track of all file descriptors referencing a given file, and not
143 * close a single one until all the locks are gone (sigh).
146 /* file descriptor object */
148 /* closed_fd is used to keep track of the unix fd belonging to a closed fd object */
149 struct closed_fd
151 struct list entry; /* entry in inode closed list */
152 int unix_fd; /* the unix file descriptor */
153 char unlink[1]; /* name to unlink on close (if any) */
156 struct fd
158 struct object obj; /* object header */
159 const struct fd_ops *fd_ops; /* file descriptor operations */
160 struct inode *inode; /* inode that this fd belongs to */
161 struct list inode_entry; /* entry in inode fd list */
162 struct closed_fd *closed; /* structure to store the unix fd at destroy time */
163 struct object *user; /* object using this file descriptor */
164 struct list locks; /* list of locks on this fd */
165 unsigned int access; /* file access (FILE_READ_DATA etc.) */
166 unsigned int sharing; /* file sharing mode */
167 int unix_fd; /* unix file descriptor */
168 int fs_locks :1; /* can we use filesystem locks for this fd? */
169 int unmounted :1;/* has the device been unmounted? */
170 int poll_index; /* index of fd in poll array */
171 struct list read_q; /* async readers of this fd */
172 struct list write_q; /* async writers of this fd */
175 static void fd_dump( struct object *obj, int verbose );
176 static void fd_destroy( struct object *obj );
178 static const struct object_ops fd_ops =
180 sizeof(struct fd), /* size */
181 fd_dump, /* dump */
182 no_add_queue, /* add_queue */
183 NULL, /* remove_queue */
184 NULL, /* signaled */
185 NULL, /* satisfied */
186 no_signal, /* signal */
187 no_get_fd, /* get_fd */
188 no_map_access, /* map_access */
189 no_lookup_name, /* lookup_name */
190 no_close_handle, /* close_handle */
191 fd_destroy /* destroy */
194 /* device object */
196 #define DEVICE_HASH_SIZE 7
197 #define INODE_HASH_SIZE 17
199 struct device
201 struct object obj; /* object header */
202 struct list entry; /* entry in device hash list */
203 dev_t dev; /* device number */
204 int removable; /* removable device? (or -1 if unknown) */
205 struct list inode_hash[INODE_HASH_SIZE]; /* inodes hash table */
208 static void device_dump( struct object *obj, int verbose );
209 static void device_destroy( struct object *obj );
211 static const struct object_ops device_ops =
213 sizeof(struct device), /* size */
214 device_dump, /* dump */
215 no_add_queue, /* add_queue */
216 NULL, /* remove_queue */
217 NULL, /* signaled */
218 NULL, /* satisfied */
219 no_signal, /* signal */
220 no_get_fd, /* get_fd */
221 no_map_access, /* map_access */
222 no_lookup_name, /* lookup_name */
223 no_close_handle, /* close_handle */
224 device_destroy /* destroy */
227 /* inode object */
229 struct inode
231 struct object obj; /* object header */
232 struct list entry; /* inode hash list entry */
233 struct device *device; /* device containing this inode */
234 ino_t ino; /* inode number */
235 struct list open; /* list of open file descriptors */
236 struct list locks; /* list of file locks */
237 struct list closed; /* list of file descriptors to close at destroy time */
240 static void inode_dump( struct object *obj, int verbose );
241 static void inode_destroy( struct object *obj );
243 static const struct object_ops inode_ops =
245 sizeof(struct inode), /* size */
246 inode_dump, /* dump */
247 no_add_queue, /* add_queue */
248 NULL, /* remove_queue */
249 NULL, /* signaled */
250 NULL, /* satisfied */
251 no_signal, /* signal */
252 no_get_fd, /* get_fd */
253 no_map_access, /* map_access */
254 no_lookup_name, /* lookup_name */
255 no_close_handle, /* close_handle */
256 inode_destroy /* destroy */
259 /* file lock object */
261 struct file_lock
263 struct object obj; /* object header */
264 struct fd *fd; /* fd owning this lock */
265 struct list fd_entry; /* entry in list of locks on a given fd */
266 struct list inode_entry; /* entry in inode list of locks */
267 int shared; /* shared lock? */
268 file_pos_t start; /* locked region is interval [start;end) */
269 file_pos_t end;
270 struct process *process; /* process owning this lock */
271 struct list proc_entry; /* entry in list of locks owned by the process */
274 static void file_lock_dump( struct object *obj, int verbose );
275 static int file_lock_signaled( struct object *obj, struct thread *thread );
277 static const struct object_ops file_lock_ops =
279 sizeof(struct file_lock), /* size */
280 file_lock_dump, /* dump */
281 add_queue, /* add_queue */
282 remove_queue, /* remove_queue */
283 file_lock_signaled, /* signaled */
284 no_satisfied, /* satisfied */
285 no_signal, /* signal */
286 no_get_fd, /* get_fd */
287 no_map_access, /* map_access */
288 no_lookup_name, /* lookup_name */
289 no_close_handle, /* close_handle */
290 no_destroy /* destroy */
294 #define OFF_T_MAX (~((file_pos_t)1 << (8*sizeof(off_t)-1)))
295 #define FILE_POS_T_MAX (~(file_pos_t)0)
297 static file_pos_t max_unix_offset = OFF_T_MAX;
299 #define DUMP_LONG_LONG(val) do { \
300 if (sizeof(val) > sizeof(unsigned long) && (val) > ~0UL) \
301 fprintf( stderr, "%lx%08lx", (unsigned long)((unsigned long long)(val) >> 32), (unsigned long)(val) ); \
302 else \
303 fprintf( stderr, "%lx", (unsigned long)(val) ); \
304 } while (0)
308 /****************************************************************/
309 /* timeouts support */
311 struct timeout_user
313 struct list entry; /* entry in sorted timeout list */
314 struct timeval when; /* timeout expiry (absolute time) */
315 timeout_callback callback; /* callback function */
316 void *private; /* callback private data */
319 static struct list timeout_list = LIST_INIT(timeout_list); /* sorted timeouts list */
320 struct timeval current_time;
322 /* add a timeout user */
323 struct timeout_user *add_timeout_user( const struct timeval *when, timeout_callback func,
324 void *private )
326 struct timeout_user *user;
327 struct list *ptr;
329 if (!(user = mem_alloc( sizeof(*user) ))) return NULL;
330 user->when = *when;
331 user->callback = func;
332 user->private = private;
334 /* Now insert it in the linked list */
336 LIST_FOR_EACH( ptr, &timeout_list )
338 struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
339 if (!time_before( &timeout->when, when )) break;
341 list_add_before( ptr, &user->entry );
342 return user;
345 /* remove a timeout user */
346 void remove_timeout_user( struct timeout_user *user )
348 list_remove( &user->entry );
349 free( user );
352 /* add a timeout in milliseconds to an absolute time */
353 void add_timeout( struct timeval *when, int timeout )
355 if (timeout)
357 long sec = timeout / 1000;
358 if ((when->tv_usec += (timeout - 1000*sec) * 1000) >= 1000000)
360 when->tv_usec -= 1000000;
361 when->tv_sec++;
363 when->tv_sec += sec;
368 /****************************************************************/
369 /* poll support */
371 static struct fd **poll_users; /* users array */
372 static struct pollfd *pollfd; /* poll fd array */
373 static int nb_users; /* count of array entries actually in use */
374 static int active_users; /* current number of active users */
375 static int allocated_users; /* count of allocated entries in the array */
376 static struct fd **freelist; /* list of free entries in the array */
378 static int get_next_timeout(void);
380 #ifdef USE_EPOLL
382 static int epoll_fd = -1;
384 static inline void init_epoll(void)
386 epoll_fd = epoll_create( 128 );
389 /* set the events that epoll waits for on this fd; helper for set_fd_events */
390 static inline void set_fd_epoll_events( struct fd *fd, int user, int events )
392 struct epoll_event ev;
393 int ctl;
395 if (epoll_fd == -1) return;
397 if (events == -1) /* stop waiting on this fd completely */
399 if (pollfd[user].fd == -1) return; /* already removed */
400 ctl = EPOLL_CTL_DEL;
402 else if (pollfd[user].fd == -1)
404 if (pollfd[user].events) return; /* stopped waiting on it, don't restart */
405 ctl = EPOLL_CTL_ADD;
407 else
409 if (pollfd[user].events == events) return; /* nothing to do */
410 ctl = EPOLL_CTL_MOD;
413 ev.events = events;
414 memset(&ev.data, 0, sizeof(ev.data));
415 ev.data.u32 = user;
417 if (epoll_ctl( epoll_fd, ctl, fd->unix_fd, &ev ) == -1)
419 if (errno == ENOMEM) /* not enough memory, give up on epoll */
421 close( epoll_fd );
422 epoll_fd = -1;
424 else perror( "epoll_ctl" ); /* should not happen */
428 static inline void remove_epoll_user( struct fd *fd, int user )
430 if (epoll_fd == -1) return;
432 if (pollfd[user].fd != -1)
434 struct epoll_event dummy;
435 epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd->unix_fd, &dummy );
439 static inline void main_loop_epoll(void)
441 int i, ret, timeout;
442 struct epoll_event events[128];
444 assert( POLLIN == EPOLLIN );
445 assert( POLLOUT == EPOLLOUT );
446 assert( POLLERR == EPOLLERR );
447 assert( POLLHUP == EPOLLHUP );
449 if (epoll_fd == -1) return;
451 while (active_users)
453 timeout = get_next_timeout();
455 if (!active_users) break; /* last user removed by a timeout */
456 if (epoll_fd == -1) break; /* an error occurred with epoll */
458 ret = epoll_wait( epoll_fd, events, sizeof(events)/sizeof(events[0]), timeout );
459 gettimeofday( &current_time, NULL );
461 /* put the events into the pollfd array first, like poll does */
462 for (i = 0; i < ret; i++)
464 int user = events[i].data.u32;
465 pollfd[user].revents = events[i].events;
468 /* read events from the pollfd array, as set_fd_events may modify them */
469 for (i = 0; i < ret; i++)
471 int user = events[i].data.u32;
472 if (pollfd[user].revents) fd_poll_event( poll_users[user], pollfd[user].revents );
477 #elif defined(HAVE_KQUEUE)
479 static int kqueue_fd = -1;
481 static inline void init_epoll(void)
483 #ifndef __APPLE__ /* kqueue support is broken in the MacOS kernel so we can't use it */
484 kqueue_fd = kqueue();
485 #endif
488 static inline void set_fd_epoll_events( struct fd *fd, int user, int events )
490 struct kevent ev[2];
492 if (kqueue_fd == -1) return;
494 EV_SET( &ev[0], fd->unix_fd, EVFILT_READ, 0, NOTE_LOWAT, 1, (void *)user );
495 EV_SET( &ev[1], fd->unix_fd, EVFILT_WRITE, 0, NOTE_LOWAT, 1, (void *)user );
497 if (events == -1) /* stop waiting on this fd completely */
499 if (pollfd[user].fd == -1) return; /* already removed */
500 ev[0].flags |= EV_DELETE;
501 ev[1].flags |= EV_DELETE;
503 else if (pollfd[user].fd == -1)
505 if (pollfd[user].events) return; /* stopped waiting on it, don't restart */
506 ev[0].flags |= EV_ADD | ((events & POLLIN) ? EV_ENABLE : EV_DISABLE);
507 ev[1].flags |= EV_ADD | ((events & POLLOUT) ? EV_ENABLE : EV_DISABLE);
509 else
511 if (pollfd[user].events == events) return; /* nothing to do */
512 ev[0].flags |= (events & POLLIN) ? EV_ENABLE : EV_DISABLE;
513 ev[1].flags |= (events & POLLOUT) ? EV_ENABLE : EV_DISABLE;
516 if (kevent( kqueue_fd, ev, 2, NULL, 0, NULL ) == -1)
518 if (errno == ENOMEM) /* not enough memory, give up on kqueue */
520 close( kqueue_fd );
521 kqueue_fd = -1;
523 else perror( "kevent" ); /* should not happen */
527 static inline void remove_epoll_user( struct fd *fd, int user )
529 if (kqueue_fd == -1) return;
531 if (pollfd[user].fd != -1)
533 struct kevent ev[2];
535 EV_SET( &ev[0], fd->unix_fd, EVFILT_READ, EV_DELETE, 0, 0, 0 );
536 EV_SET( &ev[1], fd->unix_fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0 );
537 kevent( kqueue_fd, ev, 2, NULL, 0, NULL );
541 static inline void main_loop_epoll(void)
543 int i, ret, timeout;
544 struct kevent events[128];
546 if (kqueue_fd == -1) return;
548 while (active_users)
550 timeout = get_next_timeout();
552 if (!active_users) break; /* last user removed by a timeout */
553 if (kqueue_fd == -1) break; /* an error occurred with kqueue */
555 if (timeout != -1)
557 struct timespec ts;
559 ts.tv_sec = timeout / 1000;
560 ts.tv_nsec = (timeout % 1000) * 1000000;
561 ret = kevent( kqueue_fd, NULL, 0, events, sizeof(events)/sizeof(events[0]), &ts );
563 else ret = kevent( kqueue_fd, NULL, 0, events, sizeof(events)/sizeof(events[0]), NULL );
565 gettimeofday( &current_time, NULL );
567 /* put the events into the pollfd array first, like poll does */
568 for (i = 0; i < ret; i++)
570 long user = (long)events[i].udata;
571 pollfd[user].revents = 0;
573 for (i = 0; i < ret; i++)
575 long user = (long)events[i].udata;
576 if (events[i].filter == EVFILT_READ) pollfd[user].revents |= POLLIN;
577 else if (events[i].filter == EVFILT_WRITE) pollfd[user].revents |= POLLOUT;
578 if (events[i].flags & EV_EOF) pollfd[user].revents |= POLLHUP;
579 if (events[i].flags & EV_ERROR) pollfd[user].revents |= POLLERR;
582 /* read events from the pollfd array, as set_fd_events may modify them */
583 for (i = 0; i < ret; i++)
585 long user = (long)events[i].udata;
586 if (pollfd[user].revents) fd_poll_event( poll_users[user], pollfd[user].revents );
587 pollfd[user].revents = 0;
592 #else /* HAVE_KQUEUE */
594 static inline void init_epoll(void) { }
595 static inline void set_fd_epoll_events( struct fd *fd, int user, int events ) { }
596 static inline void remove_epoll_user( struct fd *fd, int user ) { }
597 static inline void main_loop_epoll(void) { }
599 #endif /* USE_EPOLL */
602 /* add a user in the poll array and return its index, or -1 on failure */
603 static int add_poll_user( struct fd *fd )
605 int ret;
606 if (freelist)
608 ret = freelist - poll_users;
609 freelist = (struct fd **)poll_users[ret];
611 else
613 if (nb_users == allocated_users)
615 struct fd **newusers;
616 struct pollfd *newpoll;
617 int new_count = allocated_users ? (allocated_users + allocated_users / 2) : 16;
618 if (!(newusers = realloc( poll_users, new_count * sizeof(*poll_users) ))) return -1;
619 if (!(newpoll = realloc( pollfd, new_count * sizeof(*pollfd) )))
621 if (allocated_users)
622 poll_users = newusers;
623 else
624 free( newusers );
625 return -1;
627 poll_users = newusers;
628 pollfd = newpoll;
629 if (!allocated_users) init_epoll();
630 allocated_users = new_count;
632 ret = nb_users++;
634 pollfd[ret].fd = -1;
635 pollfd[ret].events = 0;
636 pollfd[ret].revents = 0;
637 poll_users[ret] = fd;
638 active_users++;
639 return ret;
642 /* remove a user from the poll list */
643 static void remove_poll_user( struct fd *fd, int user )
645 assert( user >= 0 );
646 assert( poll_users[user] == fd );
648 remove_epoll_user( fd, user );
649 pollfd[user].fd = -1;
650 pollfd[user].events = 0;
651 pollfd[user].revents = 0;
652 poll_users[user] = (struct fd *)freelist;
653 freelist = &poll_users[user];
654 active_users--;
657 /* process pending timeouts and return the time until the next timeout, in milliseconds */
658 static int get_next_timeout(void)
660 if (!list_empty( &timeout_list ))
662 struct list expired_list, *ptr;
664 /* first remove all expired timers from the list */
666 list_init( &expired_list );
667 while ((ptr = list_head( &timeout_list )) != NULL)
669 struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
671 if (!time_before( &current_time, &timeout->when ))
673 list_remove( &timeout->entry );
674 list_add_tail( &expired_list, &timeout->entry );
676 else break;
679 /* now call the callback for all the removed timers */
681 while ((ptr = list_head( &expired_list )) != NULL)
683 struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
684 list_remove( &timeout->entry );
685 timeout->callback( timeout->private );
686 free( timeout );
689 if ((ptr = list_head( &timeout_list )) != NULL)
691 struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
692 int diff = (timeout->when.tv_sec - current_time.tv_sec) * 1000
693 + (timeout->when.tv_usec - current_time.tv_usec + 999) / 1000;
694 if (diff < 0) diff = 0;
695 return diff;
698 return -1; /* no pending timeouts */
701 /* server main poll() loop */
702 void main_loop(void)
704 int i, ret, timeout;
706 gettimeofday( &current_time, NULL );
708 main_loop_epoll();
709 /* fall through to normal poll loop */
711 while (active_users)
713 timeout = get_next_timeout();
715 if (!active_users) break; /* last user removed by a timeout */
717 ret = poll( pollfd, nb_users, timeout );
718 gettimeofday( &current_time, NULL );
720 if (ret > 0)
722 for (i = 0; i < nb_users; i++)
724 if (pollfd[i].revents)
726 fd_poll_event( poll_users[i], pollfd[i].revents );
727 if (!--ret) break;
735 /****************************************************************/
736 /* device functions */
738 static struct list device_hash[DEVICE_HASH_SIZE];
740 static int is_device_removable( dev_t dev, int unix_fd )
742 #if defined(linux) && defined(HAVE_FSTATFS)
743 struct statfs stfs;
745 /* check for floppy disk */
746 if (major(dev) == FLOPPY_MAJOR) return 1;
748 if (fstatfs( unix_fd, &stfs ) == -1) return 0;
749 return (stfs.f_type == 0x9660 || /* iso9660 */
750 stfs.f_type == 0x9fa1 || /* supermount */
751 stfs.f_type == 0x15013346); /* udf */
752 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
753 struct statfs stfs;
755 if (fstatfs( unix_fd, &stfs ) == -1) return 0;
756 return (!strncmp("cd9660", stfs.f_fstypename, sizeof(stfs.f_fstypename)) ||
757 !strncmp("udf", stfs.f_fstypename, sizeof(stfs.f_fstypename)));
758 #elif defined(__NetBSD__)
759 struct statvfs stfs;
761 if (fstatvfs( unix_fd, &stfs ) == -1) return 0;
762 return (!strncmp("cd9660", stfs.f_fstypename, sizeof(stfs.f_fstypename)) ||
763 !strncmp("udf", stfs.f_fstypename, sizeof(stfs.f_fstypename)));
764 #elif defined(sun)
765 # include <sys/dkio.h>
766 # include <sys/vtoc.h>
767 struct dk_cinfo dkinf;
768 if (ioctl( unix_fd, DKIOCINFO, &dkinf ) == -1) return 0;
769 return (dkinf.dki_ctype == DKC_CDROM ||
770 dkinf.dki_ctype == DKC_NCRFLOPPY ||
771 dkinf.dki_ctype == DKC_SMSFLOPPY ||
772 dkinf.dki_ctype == DKC_INTEL82072 ||
773 dkinf.dki_ctype == DKC_INTEL82077);
774 #else
775 return 0;
776 #endif
779 /* retrieve the device object for a given fd, creating it if needed */
780 static struct device *get_device( dev_t dev, int unix_fd )
782 struct device *device;
783 unsigned int i, hash = dev % DEVICE_HASH_SIZE;
785 if (device_hash[hash].next)
787 LIST_FOR_EACH_ENTRY( device, &device_hash[hash], struct device, entry )
788 if (device->dev == dev) return (struct device *)grab_object( device );
790 else list_init( &device_hash[hash] );
792 /* not found, create it */
794 if (unix_fd == -1) return NULL;
795 if ((device = alloc_object( &device_ops )))
797 device->dev = dev;
798 device->removable = is_device_removable( dev, unix_fd );
799 for (i = 0; i < INODE_HASH_SIZE; i++) list_init( &device->inode_hash[i] );
800 list_add_head( &device_hash[hash], &device->entry );
802 return device;
805 static void device_dump( struct object *obj, int verbose )
807 struct device *device = (struct device *)obj;
808 fprintf( stderr, "Device dev=" );
809 DUMP_LONG_LONG( device->dev );
810 fprintf( stderr, "\n" );
813 static void device_destroy( struct object *obj )
815 struct device *device = (struct device *)obj;
816 unsigned int i;
818 for (i = 0; i < INODE_HASH_SIZE; i++)
819 assert( list_empty(&device->inode_hash[i]) );
821 list_remove( &device->entry ); /* remove it from the hash table */
825 /****************************************************************/
826 /* inode functions */
828 /* close all pending file descriptors in the closed list */
829 static void inode_close_pending( struct inode *inode, int keep_unlinks )
831 struct list *ptr = list_head( &inode->closed );
833 while (ptr)
835 struct closed_fd *fd = LIST_ENTRY( ptr, struct closed_fd, entry );
836 struct list *next = list_next( &inode->closed, ptr );
838 if (fd->unix_fd != -1)
840 close( fd->unix_fd );
841 fd->unix_fd = -1;
843 if (!keep_unlinks || !fd->unlink[0]) /* get rid of it unless there's an unlink pending on that file */
845 list_remove( ptr );
846 free( fd );
848 ptr = next;
852 static void inode_dump( struct object *obj, int verbose )
854 struct inode *inode = (struct inode *)obj;
855 fprintf( stderr, "Inode device=%p ino=", inode->device );
856 DUMP_LONG_LONG( inode->ino );
857 fprintf( stderr, "\n" );
860 static void inode_destroy( struct object *obj )
862 struct inode *inode = (struct inode *)obj;
863 struct list *ptr;
865 assert( list_empty(&inode->open) );
866 assert( list_empty(&inode->locks) );
868 list_remove( &inode->entry );
870 while ((ptr = list_head( &inode->closed )))
872 struct closed_fd *fd = LIST_ENTRY( ptr, struct closed_fd, entry );
873 list_remove( ptr );
874 if (fd->unix_fd != -1) close( fd->unix_fd );
875 if (fd->unlink[0])
877 /* make sure it is still the same file */
878 struct stat st;
879 if (!stat( fd->unlink, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino)
881 if (S_ISDIR(st.st_mode)) rmdir( fd->unlink );
882 else unlink( fd->unlink );
885 free( fd );
887 release_object( inode->device );
890 /* retrieve the inode object for a given fd, creating it if needed */
891 static struct inode *get_inode( dev_t dev, ino_t ino, int unix_fd )
893 struct device *device;
894 struct inode *inode;
895 unsigned int hash = ino % INODE_HASH_SIZE;
897 if (!(device = get_device( dev, unix_fd ))) return NULL;
899 LIST_FOR_EACH_ENTRY( inode, &device->inode_hash[hash], struct inode, entry )
901 if (inode->ino == ino)
903 release_object( device );
904 return (struct inode *)grab_object( inode );
908 /* not found, create it */
909 if ((inode = alloc_object( &inode_ops )))
911 inode->device = device;
912 inode->ino = ino;
913 list_init( &inode->open );
914 list_init( &inode->locks );
915 list_init( &inode->closed );
916 list_add_head( &device->inode_hash[hash], &inode->entry );
918 else release_object( device );
920 return inode;
923 /* add fd to the inode list of file descriptors to close */
924 static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd )
926 if (!list_empty( &inode->locks ))
928 list_add_head( &inode->closed, &fd->entry );
930 else if (fd->unlink[0]) /* close the fd but keep the structure around for unlink */
932 if (fd->unix_fd != -1) close( fd->unix_fd );
933 fd->unix_fd = -1;
934 list_add_head( &inode->closed, &fd->entry );
936 else /* no locks on this inode and no unlink, get rid of the fd */
938 if (fd->unix_fd != -1) close( fd->unix_fd );
939 free( fd );
944 /****************************************************************/
945 /* file lock functions */
947 static void file_lock_dump( struct object *obj, int verbose )
949 struct file_lock *lock = (struct file_lock *)obj;
950 fprintf( stderr, "Lock %s fd=%p proc=%p start=",
951 lock->shared ? "shared" : "excl", lock->fd, lock->process );
952 DUMP_LONG_LONG( lock->start );
953 fprintf( stderr, " end=" );
954 DUMP_LONG_LONG( lock->end );
955 fprintf( stderr, "\n" );
958 static int file_lock_signaled( struct object *obj, struct thread *thread )
960 struct file_lock *lock = (struct file_lock *)obj;
961 /* lock is signaled if it has lost its owner */
962 return !lock->process;
965 /* set (or remove) a Unix lock if possible for the given range */
966 static int set_unix_lock( struct fd *fd, file_pos_t start, file_pos_t end, int type )
968 struct flock fl;
970 if (!fd->fs_locks) return 1; /* no fs locks possible for this fd */
971 for (;;)
973 if (start == end) return 1; /* can't set zero-byte lock */
974 if (start > max_unix_offset) return 1; /* ignore it */
975 fl.l_type = type;
976 fl.l_whence = SEEK_SET;
977 fl.l_start = start;
978 if (!end || end > max_unix_offset) fl.l_len = 0;
979 else fl.l_len = end - start;
980 if (fcntl( fd->unix_fd, F_SETLK, &fl ) != -1) return 1;
982 switch(errno)
984 case EACCES:
985 /* check whether locks work at all on this file system */
986 if (fcntl( fd->unix_fd, F_GETLK, &fl ) != -1)
988 set_error( STATUS_FILE_LOCK_CONFLICT );
989 return 0;
991 /* fall through */
992 case EIO:
993 case ENOLCK:
994 /* no locking on this fs, just ignore it */
995 fd->fs_locks = 0;
996 return 1;
997 case EAGAIN:
998 set_error( STATUS_FILE_LOCK_CONFLICT );
999 return 0;
1000 case EBADF:
1001 /* this can happen if we try to set a write lock on a read-only file */
1002 /* we just ignore that error */
1003 if (fl.l_type == F_WRLCK) return 1;
1004 set_error( STATUS_ACCESS_DENIED );
1005 return 0;
1006 #ifdef EOVERFLOW
1007 case EOVERFLOW:
1008 #endif
1009 case EINVAL:
1010 /* this can happen if off_t is 64-bit but the kernel only supports 32-bit */
1011 /* in that case we shrink the limit and retry */
1012 if (max_unix_offset > INT_MAX)
1014 max_unix_offset = INT_MAX;
1015 break; /* retry */
1017 /* fall through */
1018 default:
1019 file_set_error();
1020 return 0;
1025 /* check if interval [start;end) overlaps the lock */
1026 inline static int lock_overlaps( struct file_lock *lock, file_pos_t start, file_pos_t end )
1028 if (lock->end && start >= lock->end) return 0;
1029 if (end && lock->start >= end) return 0;
1030 return 1;
1033 /* remove Unix locks for all bytes in the specified area that are no longer locked */
1034 static void remove_unix_locks( struct fd *fd, file_pos_t start, file_pos_t end )
1036 struct hole
1038 struct hole *next;
1039 struct hole *prev;
1040 file_pos_t start;
1041 file_pos_t end;
1042 } *first, *cur, *next, *buffer;
1044 struct list *ptr;
1045 int count = 0;
1047 if (!fd->inode) return;
1048 if (!fd->fs_locks) return;
1049 if (start == end || start > max_unix_offset) return;
1050 if (!end || end > max_unix_offset) end = max_unix_offset + 1;
1052 /* count the number of locks overlapping the specified area */
1054 LIST_FOR_EACH( ptr, &fd->inode->locks )
1056 struct file_lock *lock = LIST_ENTRY( ptr, struct file_lock, inode_entry );
1057 if (lock->start == lock->end) continue;
1058 if (lock_overlaps( lock, start, end )) count++;
1061 if (!count) /* no locks at all, we can unlock everything */
1063 set_unix_lock( fd, start, end, F_UNLCK );
1064 return;
1067 /* allocate space for the list of holes */
1068 /* max. number of holes is number of locks + 1 */
1070 if (!(buffer = malloc( sizeof(*buffer) * (count+1) ))) return;
1071 first = buffer;
1072 first->next = NULL;
1073 first->prev = NULL;
1074 first->start = start;
1075 first->end = end;
1076 next = first + 1;
1078 /* build a sorted list of unlocked holes in the specified area */
1080 LIST_FOR_EACH( ptr, &fd->inode->locks )
1082 struct file_lock *lock = LIST_ENTRY( ptr, struct file_lock, inode_entry );
1083 if (lock->start == lock->end) continue;
1084 if (!lock_overlaps( lock, start, end )) continue;
1086 /* go through all the holes touched by this lock */
1087 for (cur = first; cur; cur = cur->next)
1089 if (cur->end <= lock->start) continue; /* hole is before start of lock */
1090 if (lock->end && cur->start >= lock->end) break; /* hole is after end of lock */
1092 /* now we know that lock is overlapping hole */
1094 if (cur->start >= lock->start) /* lock starts before hole, shrink from start */
1096 cur->start = lock->end;
1097 if (cur->start && cur->start < cur->end) break; /* done with this lock */
1098 /* now hole is empty, remove it */
1099 if (cur->next) cur->next->prev = cur->prev;
1100 if (cur->prev) cur->prev->next = cur->next;
1101 else if (!(first = cur->next)) goto done; /* no more holes at all */
1103 else if (!lock->end || cur->end <= lock->end) /* lock larger than hole, shrink from end */
1105 cur->end = lock->start;
1106 assert( cur->start < cur->end );
1108 else /* lock is in the middle of hole, split hole in two */
1110 next->prev = cur;
1111 next->next = cur->next;
1112 cur->next = next;
1113 next->start = lock->end;
1114 next->end = cur->end;
1115 cur->end = lock->start;
1116 assert( next->start < next->end );
1117 assert( cur->end < next->start );
1118 next++;
1119 break; /* done with this lock */
1124 /* clear Unix locks for all the holes */
1126 for (cur = first; cur; cur = cur->next)
1127 set_unix_lock( fd, cur->start, cur->end, F_UNLCK );
1129 done:
1130 free( buffer );
1133 /* create a new lock on a fd */
1134 static struct file_lock *add_lock( struct fd *fd, int shared, file_pos_t start, file_pos_t end )
1136 struct file_lock *lock;
1138 if (!fd->inode) /* not a regular file */
1140 set_error( STATUS_INVALID_HANDLE );
1141 return NULL;
1144 if (!(lock = alloc_object( &file_lock_ops ))) return NULL;
1145 lock->shared = shared;
1146 lock->start = start;
1147 lock->end = end;
1148 lock->fd = fd;
1149 lock->process = current->process;
1151 /* now try to set a Unix lock */
1152 if (!set_unix_lock( lock->fd, lock->start, lock->end, lock->shared ? F_RDLCK : F_WRLCK ))
1154 release_object( lock );
1155 return NULL;
1157 list_add_head( &fd->locks, &lock->fd_entry );
1158 list_add_head( &fd->inode->locks, &lock->inode_entry );
1159 list_add_head( &lock->process->locks, &lock->proc_entry );
1160 return lock;
1163 /* remove an existing lock */
1164 static void remove_lock( struct file_lock *lock, int remove_unix )
1166 struct inode *inode = lock->fd->inode;
1168 list_remove( &lock->fd_entry );
1169 list_remove( &lock->inode_entry );
1170 list_remove( &lock->proc_entry );
1171 if (remove_unix) remove_unix_locks( lock->fd, lock->start, lock->end );
1172 if (list_empty( &inode->locks )) inode_close_pending( inode, 1 );
1173 lock->process = NULL;
1174 wake_up( &lock->obj, 0 );
1175 release_object( lock );
1178 /* remove all locks owned by a given process */
1179 void remove_process_locks( struct process *process )
1181 struct list *ptr;
1183 while ((ptr = list_head( &process->locks )))
1185 struct file_lock *lock = LIST_ENTRY( ptr, struct file_lock, proc_entry );
1186 remove_lock( lock, 1 ); /* this removes it from the list */
1190 /* remove all locks on a given fd */
1191 static void remove_fd_locks( struct fd *fd )
1193 file_pos_t start = FILE_POS_T_MAX, end = 0;
1194 struct list *ptr;
1196 while ((ptr = list_head( &fd->locks )))
1198 struct file_lock *lock = LIST_ENTRY( ptr, struct file_lock, fd_entry );
1199 if (lock->start < start) start = lock->start;
1200 if (!lock->end || lock->end > end) end = lock->end - 1;
1201 remove_lock( lock, 0 );
1203 if (start < end) remove_unix_locks( fd, start, end + 1 );
1206 /* add a lock on an fd */
1207 /* returns handle to wait on */
1208 obj_handle_t lock_fd( struct fd *fd, file_pos_t start, file_pos_t count, int shared, int wait )
1210 struct list *ptr;
1211 file_pos_t end = start + count;
1213 /* don't allow wrapping locks */
1214 if (end && end < start)
1216 set_error( STATUS_INVALID_PARAMETER );
1217 return 0;
1220 /* check if another lock on that file overlaps the area */
1221 LIST_FOR_EACH( ptr, &fd->inode->locks )
1223 struct file_lock *lock = LIST_ENTRY( ptr, struct file_lock, inode_entry );
1224 if (!lock_overlaps( lock, start, end )) continue;
1225 if (lock->shared && shared) continue;
1226 /* found one */
1227 if (!wait)
1229 set_error( STATUS_FILE_LOCK_CONFLICT );
1230 return 0;
1232 set_error( STATUS_PENDING );
1233 return alloc_handle( current->process, lock, SYNCHRONIZE, 0 );
1236 /* not found, add it */
1237 if (add_lock( fd, shared, start, end )) return 0;
1238 if (get_error() == STATUS_FILE_LOCK_CONFLICT)
1240 /* Unix lock conflict -> tell client to wait and retry */
1241 if (wait) set_error( STATUS_PENDING );
1243 return 0;
1246 /* remove a lock on an fd */
1247 void unlock_fd( struct fd *fd, file_pos_t start, file_pos_t count )
1249 struct list *ptr;
1250 file_pos_t end = start + count;
1252 /* find an existing lock with the exact same parameters */
1253 LIST_FOR_EACH( ptr, &fd->locks )
1255 struct file_lock *lock = LIST_ENTRY( ptr, struct file_lock, fd_entry );
1256 if ((lock->start == start) && (lock->end == end))
1258 remove_lock( lock, 1 );
1259 return;
1262 set_error( STATUS_FILE_LOCK_CONFLICT );
1266 /****************************************************************/
1267 /* asynchronous operations support */
1269 struct async
1271 struct thread *thread;
1272 void *apc;
1273 void *user;
1274 void *sb;
1275 struct timeout_user *timeout;
1276 struct list entry;
1279 /* notifies client thread of new status of its async request */
1280 /* destroys the server side of it */
1281 static void async_terminate( struct async *async, int status )
1283 thread_queue_apc( async->thread, NULL, async->apc, APC_ASYNC_IO,
1284 1, async->user, async->sb, (void *)status );
1286 if (async->timeout) remove_timeout_user( async->timeout );
1287 async->timeout = NULL;
1288 list_remove( &async->entry );
1289 release_object( async->thread );
1290 free( async );
1293 /* cb for timeout on an async request */
1294 static void async_callback(void *private)
1296 struct async *async = (struct async *)private;
1298 /* fprintf(stderr, "async timeout out %p\n", async); */
1299 async->timeout = NULL;
1300 async_terminate( async, STATUS_TIMEOUT );
1303 /* create an async on a given queue of a fd */
1304 struct async *create_async( struct thread *thread, const struct timeval *timeout,
1305 struct list *queue, void *io_apc, void *io_user, void* io_sb )
1307 struct async *async = mem_alloc( sizeof(struct async) );
1309 if (!async) return NULL;
1311 async->thread = (struct thread *)grab_object(thread);
1312 async->apc = io_apc;
1313 async->user = io_user;
1314 async->sb = io_sb;
1316 list_add_tail( queue, &async->entry );
1318 if (timeout) async->timeout = add_timeout_user( timeout, async_callback, async );
1319 else async->timeout = NULL;
1321 return async;
1324 /* terminate the async operation at the head of the queue */
1325 void async_terminate_head( struct list *queue, int status )
1327 struct list *ptr = list_head( queue );
1328 if (ptr) async_terminate( LIST_ENTRY( ptr, struct async, entry ), status );
1331 /****************************************************************/
1332 /* file descriptor functions */
1334 static void fd_dump( struct object *obj, int verbose )
1336 struct fd *fd = (struct fd *)obj;
1337 fprintf( stderr, "Fd unix_fd=%d user=%p", fd->unix_fd, fd->user );
1338 if (fd->inode) fprintf( stderr, " inode=%p unlink='%s'", fd->inode, fd->closed->unlink );
1339 fprintf( stderr, "\n" );
1342 static void fd_destroy( struct object *obj )
1344 struct fd *fd = (struct fd *)obj;
1346 async_terminate_queue( &fd->read_q, STATUS_CANCELLED );
1347 async_terminate_queue( &fd->write_q, STATUS_CANCELLED );
1349 remove_fd_locks( fd );
1350 list_remove( &fd->inode_entry );
1351 if (fd->poll_index != -1) remove_poll_user( fd, fd->poll_index );
1352 if (fd->inode)
1354 inode_add_closed_fd( fd->inode, fd->closed );
1355 release_object( fd->inode );
1357 else /* no inode, close it right away */
1359 if (fd->unix_fd != -1) close( fd->unix_fd );
1363 /* set the events that select waits for on this fd */
1364 void set_fd_events( struct fd *fd, int events )
1366 int user = fd->poll_index;
1367 assert( poll_users[user] == fd );
1369 set_fd_epoll_events( fd, user, events );
1371 if (events == -1) /* stop waiting on this fd completely */
1373 pollfd[user].fd = -1;
1374 pollfd[user].events = POLLERR;
1375 pollfd[user].revents = 0;
1377 else if (pollfd[user].fd != -1 || !pollfd[user].events)
1379 pollfd[user].fd = fd->unix_fd;
1380 pollfd[user].events = events;
1384 /* prepare an fd for unmounting its corresponding device */
1385 static inline void unmount_fd( struct fd *fd )
1387 assert( fd->inode );
1389 async_terminate_queue( &fd->read_q, STATUS_VOLUME_DISMOUNTED );
1390 async_terminate_queue( &fd->write_q, STATUS_VOLUME_DISMOUNTED );
1392 if (fd->poll_index != -1) set_fd_events( fd, -1 );
1394 if (fd->unix_fd != -1) close( fd->unix_fd );
1396 fd->unix_fd = -1;
1397 fd->unmounted = 1;
1398 fd->closed->unix_fd = -1;
1399 fd->closed->unlink[0] = 0;
1401 /* stop using Unix locks on this fd (existing locks have been removed by close) */
1402 fd->fs_locks = 0;
1405 /* allocate an fd object, without setting the unix fd yet */
1406 static struct fd *alloc_fd_object(void)
1408 struct fd *fd = alloc_object( &fd_ops );
1410 if (!fd) return NULL;
1412 fd->fd_ops = NULL;
1413 fd->user = NULL;
1414 fd->inode = NULL;
1415 fd->closed = NULL;
1416 fd->access = 0;
1417 fd->sharing = 0;
1418 fd->unix_fd = -1;
1419 fd->fs_locks = 1;
1420 fd->unmounted = 0;
1421 fd->poll_index = -1;
1422 list_init( &fd->inode_entry );
1423 list_init( &fd->locks );
1424 list_init( &fd->read_q );
1425 list_init( &fd->write_q );
1427 if ((fd->poll_index = add_poll_user( fd )) == -1)
1429 release_object( fd );
1430 return NULL;
1432 return fd;
1435 /* allocate a pseudo fd object, for objects that need to behave like files but don't have a unix fd */
1436 struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user )
1438 struct fd *fd = alloc_object( &fd_ops );
1440 if (!fd) return NULL;
1442 fd->fd_ops = fd_user_ops;
1443 fd->user = user;
1444 fd->inode = NULL;
1445 fd->closed = NULL;
1446 fd->access = 0;
1447 fd->sharing = 0;
1448 fd->unix_fd = -1;
1449 fd->fs_locks = 0;
1450 fd->unmounted = 0;
1451 fd->poll_index = -1;
1452 list_init( &fd->inode_entry );
1453 list_init( &fd->locks );
1454 list_init( &fd->read_q );
1455 list_init( &fd->write_q );
1456 return fd;
1459 /* check if the desired access is possible without violating */
1460 /* the sharing mode of other opens of the same file */
1461 static int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing )
1463 unsigned int existing_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
1464 unsigned int existing_access = 0;
1465 struct list *ptr;
1467 /* if access mode is 0, sharing mode is ignored */
1468 if (!access) sharing = existing_sharing;
1469 fd->access = access;
1470 fd->sharing = sharing;
1472 LIST_FOR_EACH( ptr, &fd->inode->open )
1474 struct fd *fd_ptr = LIST_ENTRY( ptr, struct fd, inode_entry );
1475 if (fd_ptr != fd)
1477 existing_sharing &= fd_ptr->sharing;
1478 existing_access |= fd_ptr->access;
1482 if ((access & FILE_UNIX_READ_ACCESS) && !(existing_sharing & FILE_SHARE_READ)) return 0;
1483 if ((access & FILE_UNIX_WRITE_ACCESS) && !(existing_sharing & FILE_SHARE_WRITE)) return 0;
1484 if ((access & DELETE) && !(existing_sharing & FILE_SHARE_DELETE)) return 0;
1485 if ((existing_access & FILE_UNIX_READ_ACCESS) && !(sharing & FILE_SHARE_READ)) return 0;
1486 if ((existing_access & FILE_UNIX_WRITE_ACCESS) && !(sharing & FILE_SHARE_WRITE)) return 0;
1487 if ((existing_access & DELETE) && !(sharing & FILE_SHARE_DELETE)) return 0;
1488 return 1;
1491 /* sets the user of an fd that previously had no user */
1492 void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *user )
1494 assert( fd->fd_ops == NULL );
1495 fd->fd_ops = user_ops;
1496 fd->user = user;
1499 /* open() wrapper that returns a struct fd with no fd user set */
1500 struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int access,
1501 unsigned int sharing, unsigned int options )
1503 struct stat st;
1504 struct closed_fd *closed_fd;
1505 struct fd *fd;
1506 const char *unlink_name = "";
1507 int rw_mode;
1509 if ((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE))
1511 set_error( STATUS_INVALID_PARAMETER );
1512 return NULL;
1515 if (!(fd = alloc_fd_object())) return NULL;
1517 if (options & FILE_DELETE_ON_CLOSE) unlink_name = name;
1518 if (!(closed_fd = mem_alloc( sizeof(*closed_fd) + strlen(unlink_name) )))
1520 release_object( fd );
1521 return NULL;
1524 /* create the directory if needed */
1525 if ((options & FILE_DIRECTORY_FILE) && (flags & O_CREAT))
1527 if (mkdir( name, 0777 ) == -1)
1529 if (errno != EEXIST || (flags & O_EXCL))
1531 file_set_error();
1532 goto error;
1535 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
1538 if ((access & FILE_UNIX_WRITE_ACCESS) && !(options & FILE_DIRECTORY_FILE))
1540 if (access & FILE_UNIX_READ_ACCESS) rw_mode = O_RDWR;
1541 else rw_mode = O_WRONLY;
1543 else rw_mode = O_RDONLY;
1545 if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1)
1547 /* if we tried to open a directory for write access, retry read-only */
1548 if (errno != EISDIR ||
1549 !(access & FILE_UNIX_WRITE_ACCESS) ||
1550 (fd->unix_fd = open( name, O_RDONLY | (flags & ~O_TRUNC), *mode )) == -1)
1552 file_set_error();
1553 goto error;
1557 closed_fd->unix_fd = fd->unix_fd;
1558 closed_fd->unlink[0] = 0;
1559 fstat( fd->unix_fd, &st );
1560 *mode = st.st_mode;
1562 /* only bother with an inode for normal files and directories */
1563 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
1565 struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );
1567 if (!inode)
1569 /* we can close the fd because there are no others open on the same file,
1570 * otherwise we wouldn't have failed to allocate a new inode
1572 goto error;
1574 fd->inode = inode;
1575 fd->closed = closed_fd;
1576 list_add_head( &inode->open, &fd->inode_entry );
1578 /* check directory options */
1579 if ((options & FILE_DIRECTORY_FILE) && !S_ISDIR(st.st_mode))
1581 release_object( fd );
1582 set_error( STATUS_NOT_A_DIRECTORY );
1583 return NULL;
1585 if ((options & FILE_NON_DIRECTORY_FILE) && S_ISDIR(st.st_mode))
1587 release_object( fd );
1588 set_error( STATUS_FILE_IS_A_DIRECTORY );
1589 return NULL;
1591 if (!check_sharing( fd, access, sharing ))
1593 release_object( fd );
1594 set_error( STATUS_SHARING_VIOLATION );
1595 return NULL;
1597 strcpy( closed_fd->unlink, unlink_name );
1598 if (flags & O_TRUNC) ftruncate( fd->unix_fd, 0 );
1600 else /* special file */
1602 if (options & FILE_DIRECTORY_FILE)
1604 set_error( STATUS_NOT_A_DIRECTORY );
1605 goto error;
1607 if (unlink_name[0]) /* we can't unlink special files */
1609 set_error( STATUS_INVALID_PARAMETER );
1610 goto error;
1612 free( closed_fd );
1614 return fd;
1616 error:
1617 release_object( fd );
1618 free( closed_fd );
1619 return NULL;
1622 /* create an fd for an anonymous file */
1623 /* if the function fails the unix fd is closed */
1624 struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, struct object *user )
1626 struct fd *fd = alloc_fd_object();
1628 if (fd)
1630 set_fd_user( fd, fd_user_ops, user );
1631 fd->unix_fd = unix_fd;
1632 return fd;
1634 close( unix_fd );
1635 return NULL;
1638 /* retrieve the object that is using an fd */
1639 void *get_fd_user( struct fd *fd )
1641 return fd->user;
1644 /* retrieve the unix fd for an object */
1645 int get_unix_fd( struct fd *fd )
1647 if (fd->unix_fd == -1)
1649 if (fd->unmounted) set_error( STATUS_VOLUME_DISMOUNTED );
1650 else set_error( STATUS_BAD_DEVICE_TYPE );
1652 return fd->unix_fd;
1655 /* check if two file descriptors point to the same file */
1656 int is_same_file_fd( struct fd *fd1, struct fd *fd2 )
1658 return fd1->inode == fd2->inode;
1661 /* callback for event happening in the main poll() loop */
1662 void fd_poll_event( struct fd *fd, int event )
1664 return fd->fd_ops->poll_event( fd, event );
1667 /* check if events are pending and if yes return which one(s) */
1668 int check_fd_events( struct fd *fd, int events )
1670 struct pollfd pfd;
1672 if (fd->unix_fd == -1) return POLLERR;
1674 pfd.fd = fd->unix_fd;
1675 pfd.events = events;
1676 if (poll( &pfd, 1, 0 ) <= 0) return 0;
1677 return pfd.revents;
1680 /* default add_queue() routine for objects that poll() on an fd */
1681 int default_fd_add_queue( struct object *obj, struct wait_queue_entry *entry )
1683 struct fd *fd = get_obj_fd( obj );
1685 if (!fd) return 0;
1686 if (!fd->inode && list_empty( &obj->wait_queue )) /* first on the queue */
1687 set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
1688 add_queue( obj, entry );
1689 release_object( fd );
1690 return 1;
1693 /* default remove_queue() routine for objects that poll() on an fd */
1694 void default_fd_remove_queue( struct object *obj, struct wait_queue_entry *entry )
1696 struct fd *fd = get_obj_fd( obj );
1698 grab_object( obj );
1699 remove_queue( obj, entry );
1700 if (!fd->inode && list_empty( &obj->wait_queue )) /* last on the queue is gone */
1701 set_fd_events( fd, 0 );
1702 release_object( obj );
1703 release_object( fd );
1706 /* default signaled() routine for objects that poll() on an fd */
1707 int default_fd_signaled( struct object *obj, struct thread *thread )
1709 int events, ret;
1710 struct fd *fd = get_obj_fd( obj );
1712 if (fd->inode) ret = 1; /* regular files are always signaled */
1713 else
1715 events = fd->fd_ops->get_poll_events( fd );
1716 ret = check_fd_events( fd, events ) != 0;
1718 if (ret)
1720 /* stop waiting on select() if we are signaled */
1721 set_fd_events( fd, 0 );
1723 else if (!list_empty( &obj->wait_queue ))
1725 /* restart waiting on poll() if we are no longer signaled */
1726 set_fd_events( fd, events );
1729 release_object( fd );
1730 return ret;
1733 int default_fd_get_poll_events( struct fd *fd )
1735 int events = 0;
1737 if (!list_empty( &fd->read_q ))
1738 events |= POLLIN;
1739 if (!list_empty( &fd->write_q ))
1740 events |= POLLOUT;
1742 return events;
1745 /* default handler for poll() events */
1746 void default_poll_event( struct fd *fd, int event )
1748 if (!list_empty( &fd->read_q ) && (POLLIN & event) )
1750 async_terminate_head( &fd->read_q, STATUS_ALERTED );
1751 return;
1753 if (!list_empty( &fd->write_q ) && (POLLOUT & event) )
1755 async_terminate_head( &fd->write_q, STATUS_ALERTED );
1756 return;
1759 /* if an error occurred, stop polling this fd to avoid busy-looping */
1760 if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 );
1761 wake_up( fd->user, 0 );
1764 void fd_queue_async_timeout( struct fd *fd, void *apc, void *user, void *io_sb, int type, int count,
1765 const struct timeval *timeout )
1767 struct list *queue;
1768 int events;
1770 if (!(fd->fd_ops->get_file_info( fd ) & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT)))
1772 set_error( STATUS_INVALID_HANDLE );
1773 return;
1776 switch (type)
1778 case ASYNC_TYPE_READ:
1779 queue = &fd->read_q;
1780 break;
1781 case ASYNC_TYPE_WRITE:
1782 queue = &fd->write_q;
1783 break;
1784 default:
1785 set_error( STATUS_INVALID_PARAMETER );
1786 return;
1789 if (!create_async( current, timeout, queue, apc, user, io_sb ))
1790 return;
1792 /* Check if the new pending request can be served immediately */
1793 events = check_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
1794 if (events) fd->fd_ops->poll_event( fd, events );
1796 set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
1799 void default_fd_queue_async( struct fd *fd, void *apc, void *user, void *io_sb, int type, int count )
1801 fd_queue_async_timeout( fd, apc, user, io_sb, type, count, NULL );
1804 void default_fd_cancel_async( struct fd *fd )
1806 async_terminate_queue( &fd->read_q, STATUS_CANCELLED );
1807 async_terminate_queue( &fd->write_q, STATUS_CANCELLED );
1810 /* default flush() routine */
1811 int no_flush( struct fd *fd, struct event **event )
1813 set_error( STATUS_OBJECT_TYPE_MISMATCH );
1814 return 0;
1817 /* default get_file_info() routine */
1818 int no_get_file_info( struct fd *fd )
1820 set_error( STATUS_OBJECT_TYPE_MISMATCH );
1821 return 0;
1824 /* default queue_async() routine */
1825 void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb,
1826 int type, int count)
1828 set_error( STATUS_OBJECT_TYPE_MISMATCH );
1831 /* default cancel_async() routine */
1832 void no_cancel_async( struct fd *fd )
1834 set_error( STATUS_OBJECT_TYPE_MISMATCH );
1837 static inline int is_valid_mounted_device( struct stat *st )
1839 #if defined(linux) || defined(__sun__)
1840 return S_ISBLK( st->st_mode );
1841 #else
1842 /* disks are char devices on *BSD */
1843 return S_ISCHR( st->st_mode );
1844 #endif
1847 /* close all Unix file descriptors on a device to allow unmounting it */
1848 static void unmount_device( struct fd *device_fd )
1850 unsigned int i;
1851 struct stat st;
1852 struct device *device;
1853 struct inode *inode;
1854 struct fd *fd;
1855 int unix_fd = get_unix_fd( device_fd );
1857 if (unix_fd == -1) return;
1859 if (fstat( unix_fd, &st ) == -1 || !is_valid_mounted_device( &st ))
1861 set_error( STATUS_INVALID_PARAMETER );
1862 return;
1865 if (!(device = get_device( st.st_rdev, -1 ))) return;
1867 for (i = 0; i < INODE_HASH_SIZE; i++)
1869 LIST_FOR_EACH_ENTRY( inode, &device->inode_hash[i], struct inode, entry )
1871 LIST_FOR_EACH_ENTRY( fd, &inode->open, struct fd, inode_entry )
1873 unmount_fd( fd );
1875 inode_close_pending( inode, 0 );
1878 /* remove it from the hash table */
1879 list_remove( &device->entry );
1880 list_init( &device->entry );
1881 release_object( device );
1884 /* same as get_handle_obj but retrieve the struct fd associated to the object */
1885 static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handle,
1886 unsigned int access )
1888 struct fd *fd = NULL;
1889 struct object *obj;
1891 if ((obj = get_handle_obj( process, handle, access, NULL )))
1893 fd = get_obj_fd( obj );
1894 release_object( obj );
1896 return fd;
1899 /* flush a file buffers */
1900 DECL_HANDLER(flush_file)
1902 struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
1903 struct event * event = NULL;
1905 if (fd)
1907 fd->fd_ops->flush( fd, &event );
1908 if ( event )
1910 reply->event = alloc_handle( current->process, event, SYNCHRONIZE, 0 );
1912 release_object( fd );
1916 /* open a file object */
1917 DECL_HANDLER(open_file_object)
1919 struct unicode_str name;
1920 struct directory *root = NULL;
1921 struct object *obj;
1923 get_req_unicode_str( &name );
1924 if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
1925 return;
1927 if ((obj = open_object_dir( root, &name, req->attributes, NULL )))
1929 /* make sure this is a valid file object */
1930 struct fd *fd = get_obj_fd( obj );
1931 if (fd)
1933 reply->handle = alloc_handle( current->process, obj, req->access, req->attributes );
1934 release_object( fd );
1936 release_object( obj );
1939 if (root) release_object( root );
1942 /* get a Unix fd to access a file */
1943 DECL_HANDLER(get_handle_fd)
1945 struct fd *fd;
1947 reply->fd = -1;
1949 if ((fd = get_handle_fd_obj( current->process, req->handle, req->access )))
1951 int unix_fd = get_unix_fd( fd );
1952 if (unix_fd != -1)
1954 int cached_fd = get_handle_unix_fd( current->process, req->handle, req->access );
1955 if (cached_fd != -1) reply->fd = cached_fd;
1956 else if (!get_error()) send_client_fd( current->process, unix_fd, req->handle );
1958 if (fd->inode) reply->removable = fd->inode->device->removable;
1959 reply->flags = fd->fd_ops->get_file_info( fd );
1960 release_object( fd );
1964 /* set the cached file descriptor of a handle */
1965 DECL_HANDLER(set_handle_fd)
1967 struct fd *fd;
1969 reply->cur_fd = -1;
1970 if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
1972 struct device *device = fd->inode ? fd->inode->device : NULL;
1974 /* only cache the fd on non-removable devices */
1975 if (!device || !device->removable)
1976 reply->cur_fd = set_handle_unix_fd( current->process, req->handle, req->fd );
1977 release_object( fd );
1981 /* get ready to unmount a Unix device */
1982 DECL_HANDLER(unmount_device)
1984 struct fd *fd;
1986 if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
1988 unmount_device( fd );
1989 release_object( fd );
1993 /* create / reschedule an async I/O */
1994 DECL_HANDLER(register_async)
1996 struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
1999 * The queue_async method must do the following:
2001 * 1. Get the async_queue for the request of given type.
2002 * 2. Create a new asynchronous request for the selected queue
2003 * 3. Carry out any operations necessary to adjust the object's poll events
2004 * Usually: set_elect_events (obj, obj->ops->get_poll_events()).
2005 * 4. When the async request is triggered, then send back (with a proper APC)
2006 * the trigger (STATUS_ALERTED) to the thread that posted the request.
2007 * async_destroy() is to be called: it will both notify the sender about
2008 * the trigger and destroy the request by itself
2009 * See also the implementations in file.c, serial.c, and sock.c.
2012 if (fd)
2014 fd->fd_ops->queue_async( fd, req->io_apc, req->io_user, req->io_sb,
2015 req->type, req->count );
2016 release_object( fd );
2020 /* cancels all async I/O */
2021 DECL_HANDLER(cancel_async)
2023 struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
2024 if (fd)
2026 /* Note: we don't kill the queued APC_ASYNC_IO on this thread because
2027 * NtCancelIoFile() will force the pending APC to be run. Since,
2028 * Windows only guarantees that the current thread will have no async
2029 * operation on the current fd when NtCancelIoFile returns, this shall
2030 * do the work.
2032 fd->fd_ops->cancel_async( fd );
2033 release_object( fd );