ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / um / os-Linux / file.c
1 /* 
2  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3  * Licensed under the GPL
4  */
5
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <signal.h>
11 #include <sys/socket.h>
12 #include <sys/un.h>
13 #include <sys/ioctl.h>
14 #include <sys/mount.h>
15 #include <sys/uio.h>
16 #include "os.h"
17 #include "user.h"
18 #include "kern_util.h"
19
20 int os_file_type(char *file)
21 {
22         struct stat64 buf;
23
24         if(stat64(file, &buf) == -1)
25                 return(-errno);
26
27         if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
28         else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
29         else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
30         else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
31         else if(S_ISFIFO(buf.st_mode)) return(OS_TYPE_FIFO);
32         else if(S_ISSOCK(buf.st_mode)) return(OS_TYPE_SOCK);
33         else return(OS_TYPE_FILE);
34 }
35
36 int os_file_mode(char *file, struct openflags *mode_out)
37 {
38         *mode_out = OPENFLAGS();
39
40         if(!access(file, W_OK)) *mode_out = of_write(*mode_out);
41         else if(errno != EACCES) 
42                 return(-errno);
43
44         if(!access(file, R_OK)) *mode_out = of_read(*mode_out);
45         else if(errno != EACCES) 
46                 return(-errno);
47
48         return(0);
49 }
50
51 int os_open_file(char *file, struct openflags flags, int mode)
52 {
53         int fd, f = 0;
54
55         if(flags.r && flags.w) f = O_RDWR;
56         else if(flags.r) f = O_RDONLY;
57         else if(flags.w) f = O_WRONLY;
58         else f = 0;
59
60         if(flags.s) f |= O_SYNC;
61         if(flags.c) f |= O_CREAT;
62         if(flags.t) f |= O_TRUNC;
63         if(flags.e) f |= O_EXCL;
64
65         fd = open64(file, f, mode);
66         if(fd < 0) return(-errno);
67         
68         if(flags.cl){
69                 if(fcntl(fd, F_SETFD, 1)){
70                         close(fd);
71                         return(-errno);
72                 }
73         }
74
75         return(fd);
76         return(fd);
77 }
78
79 int os_connect_socket(char *name)
80 {
81         struct sockaddr_un sock;
82         int fd, err;
83
84         sock.sun_family = AF_UNIX;
85         snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
86
87         fd = socket(AF_UNIX, SOCK_STREAM, 0);
88         if(fd < 0)
89                 return(fd);
90
91         err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
92         if(err)
93                 return(err);
94
95         return(fd);
96 }
97
98 void os_close_file(int fd)
99 {
100         close(fd);
101 }
102
103 int os_seek_file(int fd, __u64 offset)
104 {
105         __u64 actual;
106
107         actual = lseek64(fd, offset, SEEK_SET);
108         if(actual != offset) return(-errno);
109         return(0);
110 }
111
112 int os_read_file(int fd, void *buf, int len)
113 {
114         int n;
115
116         /* Force buf into memory if it's not already. */
117
118         /* XXX This fails if buf is kernel memory */
119 #ifdef notdef
120         if(copy_to_user_proc(buf, &c, sizeof(c)))
121                 return(-EFAULT);
122 #endif
123
124         n = read(fd, buf, len);
125         if(n < 0)
126                 return(-errno);
127         return(n);
128 }
129
130 int os_write_file(int fd, void *buf, int count)
131 {
132         int n;
133
134         /* Force buf into memory if it's not already. */
135         
136         /* XXX This fails if buf is kernel memory */
137 #ifdef notdef
138         if(copy_to_user_proc(buf, buf, buf[0]))
139                 return(-EFAULT);
140 #endif
141
142         n = write(fd, buf, count);
143         if(n < 0)
144                 return(-errno);
145         return(n);
146 }
147
148 int os_file_size(char *file, long long *size_out)
149 {
150         struct stat64 buf;
151
152         if(stat64(file, &buf) == -1){
153                 printk("Couldn't stat \"%s\" : errno = %d\n", file, errno);
154                 return(-errno);
155         }
156         if(S_ISBLK(buf.st_mode)){
157                 int fd, blocks;
158
159                 if((fd = open64(file, O_RDONLY)) < 0){
160                         printk("Couldn't open \"%s\", errno = %d\n", file,
161                                errno);
162                         return(-errno);
163                 }
164                 if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
165                         printk("Couldn't get the block size of \"%s\", "
166                                "errno = %d\n", file, errno);
167                         close(fd);
168                         return(-errno);
169                 }
170                 *size_out = ((long long) blocks) * 512;
171                 close(fd);
172                 return(0);
173         }
174         *size_out = buf.st_size;
175         return(0);
176 }
177
178 int os_pipe(int *fds, int stream, int close_on_exec)
179 {
180         int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
181
182         err = socketpair(AF_UNIX, type, 0, fds);
183         if(err) 
184                 return(-errno);
185
186         if(!close_on_exec)
187                 return(0);
188
189         if((fcntl(fds[0], F_SETFD, 1) < 0) || (fcntl(fds[1], F_SETFD, 1) < 0))
190                 printk("os_pipe : Setting FD_CLOEXEC failed, errno = %d", 
191                        errno);
192
193         return(0);
194 }
195
196 int os_set_fd_async(int fd, int owner)
197 {
198         /* XXX This should do F_GETFL first */
199         if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
200                 printk("os_set_fd_async : failed to set O_ASYNC and "
201                        "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
202                 return(-errno);
203         }
204 #ifdef notdef
205         if(fcntl(fd, F_SETFD, 1) < 0){
206                 printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
207                        "errno = %d\n", errno);
208         }
209 #endif
210
211         if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
212            (fcntl(fd, F_SETOWN, owner) < 0)){
213                 printk("os_set_fd_async : Failed to fcntl F_SETOWN "
214                        "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, 
215                        owner, errno);
216                 return(-errno);
217         }
218
219         return(0);
220 }
221
222 int os_set_fd_block(int fd, int blocking)
223 {
224         int flags;
225
226         flags = fcntl(fd, F_GETFL);
227
228         if(blocking) flags &= ~O_NONBLOCK;
229         else flags |= O_NONBLOCK;
230
231         if(fcntl(fd, F_SETFL, flags) < 0){
232                 printk("Failed to change blocking on fd # %d, errno = %d\n",
233                        fd, errno);
234                 return(-errno);
235         }
236         return(0);
237 }
238
239 int os_accept_connection(int fd)
240 {
241         int new;
242
243         new = accept(fd, NULL, 0);
244         if(new < 0) 
245                 return(-errno);
246         return(new);
247 }
248
249 #ifndef SHUT_RD
250 #define SHUT_RD 0
251 #endif
252
253 #ifndef SHUT_WR
254 #define SHUT_WR 1
255 #endif
256
257 #ifndef SHUT_RDWR
258 #define SHUT_RDWR 2
259 #endif
260
261 int os_shutdown_socket(int fd, int r, int w)
262 {
263         int what, err;
264
265         if(r && w) what = SHUT_RDWR;
266         else if(r) what = SHUT_RD;
267         else if(w) what = SHUT_WR;
268         else {
269                 printk("os_shutdown_socket : neither r or w was set\n");
270                 return(-EINVAL);
271         }
272         err = shutdown(fd, what);
273         if(err)
274                 return(-errno);
275         return(0);
276 }
277
278 int os_rcv_fd(int fd, int *helper_pid_out)
279 {
280         int new, n;
281         char buf[CMSG_SPACE(sizeof(new))];
282         struct msghdr msg;
283         struct cmsghdr *cmsg;
284         struct iovec iov;
285
286         msg.msg_name = NULL;
287         msg.msg_namelen = 0;
288         iov = ((struct iovec) { .iov_base  = helper_pid_out,
289                                 .iov_len   = sizeof(*helper_pid_out) });
290         msg.msg_iov = &iov;
291         msg.msg_iovlen = 1;
292         msg.msg_control = buf;
293         msg.msg_controllen = sizeof(buf);
294         msg.msg_flags = 0;
295
296         n = recvmsg(fd, &msg, 0);
297         if(n < 0)
298                 return(-errno);
299
300         else if(n != sizeof(iov.iov_len))
301                 *helper_pid_out = -1;
302
303         cmsg = CMSG_FIRSTHDR(&msg);
304         if(cmsg == NULL){
305                 printk("rcv_fd didn't receive anything, error = %d\n", errno);
306                 return(-1);
307         }
308         if((cmsg->cmsg_level != SOL_SOCKET) || 
309            (cmsg->cmsg_type != SCM_RIGHTS)){
310                 printk("rcv_fd didn't receive a descriptor\n");
311                 return(-1);
312         }
313
314         new = ((int *) CMSG_DATA(cmsg))[0];
315         return(new);
316 }
317
318 int create_unix_socket(char *file, int len)
319 {
320         struct sockaddr_un addr;
321         int sock, err;
322
323         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
324         if (sock < 0){
325                 printk("create_unix_socket - socket failed, errno = %d\n",
326                        errno);
327                 return(-errno);
328         }
329
330         addr.sun_family = AF_UNIX;
331
332         /* XXX Be more careful about overflow */
333         snprintf(addr.sun_path, len, "%s", file);
334
335         err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
336         if (err < 0){
337                 printk("create_listening_socket - bind failed, errno = %d\n",
338                        errno);
339                 return(-errno);
340         }
341
342         return(sock);
343 }
344
345 /*
346  * Overrides for Emacs so that we follow Linus's tabbing style.
347  * Emacs will notice this stuff at the end of the file and automatically
348  * adjust the settings for this buffer only.  This must remain at the end
349  * of the file.
350  * ---------------------------------------------------------------------------
351  * Local variables:
352  * c-file-style: "linux"
353  * End:
354  */