bda79c1820300cfbc84b7a6df92d5707e4b3a189
[linux-flexiantxendom0-3.2.10.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 <utime.h>
12 #include <dirent.h>
13 #include <linux/kdev_t.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/socket.h>
17 #include <sys/un.h>
18 #include <sys/ioctl.h>
19 #include <sys/mount.h>
20 #include <sys/uio.h>
21 #include <sys/utsname.h>
22 #include <sys/vfs.h>
23 #include "os.h"
24 #include "user.h"
25 #include "kern_util.h"
26
27 static void copy_stat(struct uml_stat *dst, struct stat64 *src)
28 {
29         *dst = ((struct uml_stat) {
30                 .ust_major   = MAJOR(src->st_dev),     /* device */
31                 .ust_minor   = MINOR(src->st_dev),
32                 .ust_ino     = src->st_ino,     /* inode */
33                 .ust_mode    = src->st_mode,    /* protection */
34                 .ust_nlink   = src->st_nlink,   /* number of hard links */
35                 .ust_uid     = src->st_uid,     /* user ID of owner */
36                 .ust_gid     = src->st_gid,     /* group ID of owner */
37                 .ust_size    = src->st_size,    /* total size, in bytes */
38                 .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
39                 .ust_blocks  = src->st_blocks,  /* number of blocks allocated */
40                 .ust_atime   = src->st_atime,   /* time of last access */
41                 .ust_mtime   = src->st_mtime,   /* time of last modification */
42                 .ust_ctime   = src->st_ctime,   /* time of last change */
43                 .ust_rmajor  = MAJOR(src->st_rdev),
44                 .ust_rminor  = MINOR(src->st_rdev),
45         });
46 }
47
48 int os_stat_fd(const int fd, struct uml_stat *ubuf)
49 {
50         struct stat64 sbuf;
51         int err;
52
53         do {
54                 err = fstat64(fd, &sbuf);
55         } while((err < 0) && (errno == EINTR)) ;
56
57         if(err < 0) 
58                 return(-errno);
59
60         if(ubuf != NULL)
61                 copy_stat(ubuf, &sbuf);
62         return(err);
63 }
64
65 int os_stat_file(const char *file_name, struct uml_stat *ubuf)
66 {
67         struct stat64 sbuf;
68         int err;
69
70         do {
71                 err = stat64(file_name, &sbuf);
72         } while((err < 0) && (errno == EINTR)) ;
73
74         if(err < 0) 
75                 return(-errno);
76
77         if(ubuf != NULL)
78                 copy_stat(ubuf, &sbuf);
79         return(err);
80 }
81
82 int os_lstat_file(const char *file_name, struct uml_stat *ubuf)
83 {
84         struct stat64 sbuf;
85         int err;
86
87         do {
88                 err = lstat64(file_name, &sbuf);
89         } while((err < 0) && (errno == EINTR)) ;
90
91         if(err < 0) 
92                 return(-errno);
93
94         if(ubuf != NULL)
95                 copy_stat(ubuf, &sbuf);
96         return(err);
97 }
98
99 int os_access(const char *file, int mode)
100 {
101         int amode, err;
102
103         amode=(mode& OS_ACC_R_OK ? R_OK : 0) | (mode& OS_ACC_W_OK ? W_OK : 0) |
104               (mode& OS_ACC_X_OK ? X_OK : 0) | (mode& OS_ACC_F_OK ? F_OK : 0) ;
105
106         err = access(file, amode);
107         if(err < 0)
108                 return(-errno);
109
110         return(0);
111 }
112
113 int os_set_file_time(const char *file, unsigned long access, unsigned long mod)
114 {
115         struct utimbuf buf = ((struct utimbuf){ .actime = access, 
116                                                 .modtime = mod });
117         int err;
118
119         err = utime(file, &buf);
120         if(err < 0)
121                 return(-errno);
122
123         return(0);
124 }
125
126 int os_set_file_perms(const char *file, int mode)
127 {
128         int err;
129
130         err = chmod(file, mode);
131         if(err < 0)
132                 return(-errno);
133
134         return(0);
135 }
136
137 int os_set_file_owner(const char *file, int owner, int group)
138 {
139         int err;
140
141         err = chown(file, owner, group);
142         if(err < 0)
143                 return(-errno);
144
145         return(0);
146 }
147
148 void os_print_error(int error, const char* str)
149 {
150         errno = error < 0 ? -error : error;
151
152         perror(str);
153 }
154
155 /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
156 int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
157 {
158         int err;
159
160         err = ioctl(fd, cmd, arg);
161         if(err < 0)
162                 return(-errno);
163
164         return(err);
165 }
166
167 int os_window_size(int fd, int *rows, int *cols)
168 {
169         struct winsize size;
170
171         if(ioctl(fd, TIOCGWINSZ, &size) < 0)
172                 return(-errno);
173
174         *rows = size.ws_row;
175         *cols = size.ws_col;
176
177         return(0);
178 }
179
180 int os_new_tty_pgrp(int fd, int pid)
181 {
182         if(ioctl(fd, TIOCSCTTY, 0) < 0){
183                 printk("TIOCSCTTY failed, errno = %d\n", errno);
184                 return(-errno);
185         }
186
187         if(tcsetpgrp(fd, pid) < 0){
188                 printk("tcsetpgrp failed, errno = %d\n", errno);
189                 return(-errno);
190         }
191
192         return(0);
193 }
194
195 /* FIXME: ensure namebuf in os_get_if_name is big enough */
196 int os_get_ifname(int fd, char* namebuf)
197 {
198         if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
199                 return(-errno);
200
201         return(0);
202 }
203
204 int os_set_slip(int fd)
205 {
206         int disc, sencap;
207
208         disc = N_SLIP;
209         if(ioctl(fd, TIOCSETD, &disc) < 0){
210                 printk("Failed to set slip line discipline - "
211                        "errno = %d\n", errno);
212                 return(-errno);
213         }
214
215         sencap = 0;
216         if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
217                 printk("Failed to set slip encapsulation - "
218                        "errno = %d\n", errno);
219                 return(-errno);
220         }
221
222         return(0);
223 }
224
225 int os_set_owner(int fd, int pid)
226 {
227         if(fcntl(fd, F_SETOWN, pid) < 0){
228                 int save_errno = errno;
229
230                 if(fcntl(fd, F_GETOWN, 0) != pid)
231                         return(-save_errno);
232         }
233
234         return(0);
235 }
236
237 /* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */ 
238 int os_sigio_async(int master, int slave)
239 {
240         int flags;
241
242         flags = fcntl(master, F_GETFL);
243         if(flags < 0) {
244                 printk("fcntl F_GETFL failed, errno = %d\n", errno);
245                 return(-errno);
246         }
247
248         if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
249            (fcntl(master, F_SETOWN, os_getpid()) < 0)){
250                 printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", 
251                        errno);
252                 return(-errno);
253         }
254
255         if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
256                 printk("fcntl F_SETFL failed, errno = %d\n", errno);
257                 return(-errno);
258         }
259
260         return(0);
261 }
262
263 int os_mode_fd(int fd, int mode)
264 {
265         int err;
266
267         do {
268                 err = fchmod(fd, mode);
269         } while((err < 0) && (errno==EINTR)) ;
270
271         if(err < 0)
272                 return(-errno);
273
274         return(0);
275 }
276
277 int os_file_type(char *file)
278 {
279         struct uml_stat buf;
280         int err;
281
282         err = os_lstat_file(file, &buf);
283         if(err < 0)
284                 return(err);
285
286         if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
287         else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
288         else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
289         else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
290         else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
291         else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
292         else return(OS_TYPE_FILE);
293 }
294
295 int os_file_mode(char *file, struct openflags *mode_out)
296 {
297         int err;
298
299         *mode_out = OPENFLAGS();
300
301         err = os_access(file, OS_ACC_W_OK);
302         if((err < 0) && (err != -EACCES))
303                 return(err);
304
305         *mode_out = of_write(*mode_out);
306
307         err = os_access(file, OS_ACC_R_OK);
308         if((err < 0) && (err != -EACCES))
309                 return(err);
310
311         *mode_out = of_read(*mode_out);
312
313         return(0);
314 }
315
316 int os_open_file(char *file, struct openflags flags, int mode)
317 {
318         int fd, f = 0;
319
320         if(flags.r && flags.w) f = O_RDWR;
321         else if(flags.r) f = O_RDONLY;
322         else if(flags.w) f = O_WRONLY;
323         else f = 0;
324
325         if(flags.s) f |= O_SYNC;
326         if(flags.c) f |= O_CREAT;
327         if(flags.t) f |= O_TRUNC;
328         if(flags.e) f |= O_EXCL;
329         if(flags.d) f |= O_DIRECT;
330
331         fd = open64(file, f, mode);
332         if(fd < 0)
333                 return(-errno);
334
335         if(flags.cl && fcntl(fd, F_SETFD, 1)){
336                 os_close_file(fd);
337                 return(-errno);
338         }
339
340         return(fd);
341 }
342
343 void *os_open_dir(char *path, int *err_out)
344 {
345         void *dir;
346
347         dir = opendir(path);
348         *err_out = -errno;
349         return(dir);
350 }
351
352 int os_seek_dir(void *stream, unsigned long long pos)
353 {
354         seekdir(stream, pos);
355         return(0);
356 }
357
358 int os_read_dir(void *stream, unsigned long long *ino_out, char **name_out)
359 {
360         struct dirent *ent;
361
362         errno = 0;
363         ent = readdir(stream);
364         if(ent == NULL){
365                 if(errno != 0)
366                         return(-errno);
367                 *name_out = NULL;
368                 return(0);
369         }
370
371         *ino_out = ent->d_ino;
372         *name_out = ent->d_name;
373         return(0);
374 }
375
376 int os_tell_dir(void *stream)
377 {
378         return(telldir(stream));
379 }
380
381 int os_close_dir(void *stream)
382 {
383         int err;
384
385         err = closedir(stream);
386         if(err < 0)
387                 return(-errno);
388         return(0);
389 }
390
391 int os_remove_file(const char *file)
392 {
393         int err;
394
395         err = unlink(file);
396         if(err)
397                 return(-errno);
398
399         return(0);
400 }
401
402 int os_move_file(const char *from, const char *to)
403 {
404         int err;
405
406         err = rename(from, to);
407         if(err)
408                 return(-errno);
409
410         return(0);
411 }
412
413 int os_truncate_fd(int fd, unsigned long long len)
414 {
415         int err;
416
417         err = ftruncate(fd, len);
418         if(err)
419                 return(-errno);
420         return(0);
421 }
422
423 int os_truncate_file(const char *file, unsigned long long len)
424 {
425         int err;
426
427         err = truncate(file, len);
428         if(err)
429                 return(-errno);
430         return(0);
431 }
432
433 int os_connect_socket(char *name)
434 {
435         struct sockaddr_un sock;
436         int fd, err;
437
438         sock.sun_family = AF_UNIX;
439         snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
440
441         fd = socket(AF_UNIX, SOCK_STREAM, 0);
442         if(fd < 0)
443                 return(fd);
444
445         err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
446         if(err)
447                 return(-errno);
448
449         return(fd);
450 }
451
452 void os_close_file(int fd)
453 {
454         close(fd);
455 }
456
457 int os_seek_file(int fd, __u64 offset)
458 {
459         __u64 actual;
460
461         actual = lseek64(fd, offset, SEEK_SET);
462         if(actual != offset) 
463                 return(-errno);
464         return(0);
465 }
466
467 static int fault_buffer(void *start, int len, 
468                         int (*copy_proc)(void *addr, void *buf, int len))
469 {
470         int page = getpagesize(), i;
471         char c;
472
473         for(i = 0; i < len; i += page){
474                 if((*copy_proc)(start + i, &c, sizeof(c)))
475                         return(-EFAULT);
476         }
477         if((len % page) != 0){
478                 if((*copy_proc)(start + len - 1, &c, sizeof(c)))
479                         return(-EFAULT);
480         }
481         return(0);
482 }
483
484 static int file_io(int fd, void *buf, int len,
485                    int (*io_proc)(int fd, void *buf, int len),
486                    int (*copy_user_proc)(void *addr, void *buf, int len))
487 {
488         int n, err;
489
490         do {
491                 n = (*io_proc)(fd, buf, len);
492                 if((n < 0) && (errno == EFAULT)){
493                         err = fault_buffer(buf, len, copy_user_proc);
494                         if(err)
495                                 return(err);
496                         n = (*io_proc)(fd, buf, len);
497                 }
498         } while((n < 0) && (errno == EINTR));
499
500         if(n < 0)
501                 return(-errno);
502         return(n);
503 }
504
505 int os_read_file(int fd, void *buf, int len)
506 {
507         return(file_io(fd, buf, len, (int (*)(int, void *, int)) read, 
508                        copy_from_user_proc));
509 }
510
511 int os_write_file(int fd, const void *buf, int len)
512 {
513         return(file_io(fd, (void *) buf, len, 
514                        (int (*)(int, void *, int)) write, copy_to_user_proc));
515 }
516
517 int os_file_size(char *file, long long *size_out)
518 {
519         struct uml_stat buf;
520         int err;
521
522         err = os_stat_file(file, &buf);
523         if(err < 0){
524                 printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
525                 return(err);
526         }
527
528         if(S_ISBLK(buf.ust_mode)){
529                 int fd, blocks;
530
531                 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
532                 if(fd < 0){
533                         printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
534                         return(fd);
535                 }
536                 if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
537                         printk("Couldn't get the block size of \"%s\", "
538                                "errno = %d\n", file, errno);
539                         err = -errno;
540                         os_close_file(fd);
541                         return(err);
542                 }
543                 *size_out = ((long long) blocks) * 512;
544                 os_close_file(fd);
545                 return(0);
546         }
547         *size_out = buf.ust_size;
548         return(0);
549 }
550
551 int os_fd_size(int fd, long long *size_out)
552 {
553         struct stat buf;
554         int err;
555
556         err = fstat(fd, &buf);
557         if(err)
558                 return(-errno);
559
560         *size_out = buf.st_size;
561         return(0);
562 }
563
564 int os_file_modtime(char *file, unsigned long *modtime)
565 {
566         struct uml_stat buf;
567         int err;
568
569         err = os_stat_file(file, &buf);
570         if(err < 0){
571                 printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
572                 return(err);
573         }
574
575         *modtime = buf.ust_mtime;
576         return(0);
577 }
578
579 int os_get_exec_close(int fd, int* close_on_exec)
580 {
581         int ret;
582
583         do {
584                 ret = fcntl(fd, F_GETFD);
585         } while((ret < 0) && (errno == EINTR)) ;
586
587         if(ret < 0)
588                 return(-errno);
589
590         *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
591         return(ret);
592 }
593
594 int os_set_exec_close(int fd, int close_on_exec)
595 {
596         int flag, err;
597
598         if(close_on_exec) flag = FD_CLOEXEC;
599         else flag = 0;
600
601         do {
602                 err = fcntl(fd, F_SETFD, flag);
603         } while((err < 0) && (errno == EINTR)) ;
604
605         if(err < 0)
606                 return(-errno);
607         return(err);
608 }
609
610 int os_pipe(int *fds, int stream, int close_on_exec)
611 {
612         int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
613
614         err = socketpair(AF_UNIX, type, 0, fds);
615         if(err < 0) 
616                 return(-errno);
617
618         if(!close_on_exec)
619                 return(0);
620
621         err = os_set_exec_close(fds[0], 1);
622         if(err < 0)
623                 goto error;
624
625         err = os_set_exec_close(fds[1], 1);
626         if(err < 0)
627                 goto error;
628
629         return(0);
630
631  error:
632         printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
633         os_close_file(fds[1]);
634         os_close_file(fds[0]);
635         return(err);
636 }
637
638 int os_set_fd_async(int fd, int owner)
639 {
640         /* XXX This should do F_GETFL first */
641         if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
642                 printk("os_set_fd_async : failed to set O_ASYNC and "
643                        "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
644                 return(-errno);
645         }
646 #ifdef notdef
647         if(fcntl(fd, F_SETFD, 1) < 0){
648                 printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
649                        "errno = %d\n", errno);
650         }
651 #endif
652
653         if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
654            (fcntl(fd, F_SETOWN, owner) < 0)){
655                 printk("os_set_fd_async : Failed to fcntl F_SETOWN "
656                        "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, 
657                        owner, errno);
658                 return(-errno);
659         }
660
661         return(0);
662 }
663
664 int os_clear_fd_async(int fd)
665 {
666         int flags = fcntl(fd, F_GETFL);
667
668         flags &= ~(O_ASYNC | O_NONBLOCK);
669         if(fcntl(fd, F_SETFL, flags) < 0)
670                 return(-errno);
671         return(0);
672 }
673
674 int os_set_fd_block(int fd, int blocking)
675 {
676         int flags;
677
678         flags = fcntl(fd, F_GETFL);
679
680         if(blocking) flags &= ~O_NONBLOCK;
681         else flags |= O_NONBLOCK;
682
683         if(fcntl(fd, F_SETFL, flags) < 0){
684                 printk("Failed to change blocking on fd # %d, errno = %d\n",
685                        fd, errno);
686                 return(-errno);
687         }
688         return(0);
689 }
690
691 int os_accept_connection(int fd)
692 {
693         int new;
694
695         new = accept(fd, NULL, 0);
696         if(new < 0) 
697                 return(-errno);
698         return(new);
699 }
700
701 #ifndef SHUT_RD
702 #define SHUT_RD 0
703 #endif
704
705 #ifndef SHUT_WR
706 #define SHUT_WR 1
707 #endif
708
709 #ifndef SHUT_RDWR
710 #define SHUT_RDWR 2
711 #endif
712
713 int os_shutdown_socket(int fd, int r, int w)
714 {
715         int what, err;
716
717         if(r && w) what = SHUT_RDWR;
718         else if(r) what = SHUT_RD;
719         else if(w) what = SHUT_WR;
720         else {
721                 printk("os_shutdown_socket : neither r or w was set\n");
722                 return(-EINVAL);
723         }
724         err = shutdown(fd, what);
725         if(err < 0)
726                 return(-errno);
727         return(0);
728 }
729
730 int os_rcv_fd(int fd, int *helper_pid_out)
731 {
732         int new, n;
733         char buf[CMSG_SPACE(sizeof(new))];
734         struct msghdr msg;
735         struct cmsghdr *cmsg;
736         struct iovec iov;
737
738         msg.msg_name = NULL;
739         msg.msg_namelen = 0;
740         iov = ((struct iovec) { .iov_base  = helper_pid_out,
741                                 .iov_len   = sizeof(*helper_pid_out) });
742         msg.msg_iov = &iov;
743         msg.msg_iovlen = 1;
744         msg.msg_control = buf;
745         msg.msg_controllen = sizeof(buf);
746         msg.msg_flags = 0;
747
748         n = recvmsg(fd, &msg, 0);
749         if(n < 0)
750                 return(-errno);
751
752         else if(n != sizeof(iov.iov_len))
753                 *helper_pid_out = -1;
754
755         cmsg = CMSG_FIRSTHDR(&msg);
756         if(cmsg == NULL){
757                 printk("rcv_fd didn't receive anything, error = %d\n", errno);
758                 return(-1);
759         }
760         if((cmsg->cmsg_level != SOL_SOCKET) || 
761            (cmsg->cmsg_type != SCM_RIGHTS)){
762                 printk("rcv_fd didn't receive a descriptor\n");
763                 return(-1);
764         }
765
766         new = ((int *) CMSG_DATA(cmsg))[0];
767         return(new);
768 }
769
770 int os_create_unix_socket(char *file, int len, int close_on_exec)
771 {
772         struct sockaddr_un addr;
773         int sock, err;
774
775         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
776         if (sock < 0){
777                 printk("create_unix_socket - socket failed, errno = %d\n",
778                        errno);
779                 return(-errno);
780         }
781
782         if(close_on_exec) {
783                 err = os_set_exec_close(sock, 1);
784                 if(err < 0)
785                         printk("create_unix_socket : close_on_exec failed, "
786                        "err = %d", -err);
787         }
788
789         addr.sun_family = AF_UNIX;
790
791         /* XXX Be more careful about overflow */
792         snprintf(addr.sun_path, len, "%s", file);
793
794         err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
795         if (err < 0){
796                 printk("create_listening_socket at '%s' - bind failed, "
797                        "errno = %d\n", file, errno);
798                 return(-errno);
799         }
800
801         return(sock);
802 }
803
804 int os_make_symlink(const char *to, const char *from)
805 {
806         int err;
807
808         err = symlink(to, from);
809         if(err)
810                 return(-errno);
811
812         return(0);
813 }
814
815 int os_read_symlink(const char *file, char *buf, int size)
816 {
817         int err;
818
819         err = readlink(file, buf, size);
820         if(err < 0)
821                 return(-errno);
822
823         return(err);
824 }
825
826 int os_link_file(const char *to, const char *from)
827 {
828         int err;
829
830         err = link(to, from);
831         if(err)
832                 return(-errno);
833
834         return(0);
835 }
836
837 int os_make_dir(const char *dir, int mode)
838 {
839         int err;
840
841         err = mkdir(dir, mode);
842         if(err)
843                 return(-errno);
844
845         return(0);
846 }
847
848 int os_make_dev(const char *name, int mode, int major, int minor)
849 {
850         int err;
851
852         err = mknod(name, mode, MKDEV(major, minor));
853         if(err)
854                 return(-errno);
855
856         return(0);
857 }
858
859 int os_remove_dir(const char *dir)
860 {
861         int err;
862
863         err = rmdir(dir);
864         if(err)
865                 return(-errno);
866
867         return(0);
868 }
869
870 void os_flush_stdout(void)
871 {
872         fflush(stdout);
873 }
874
875 int os_lock_file(int fd, int excl)
876 {
877         int type = excl ? F_WRLCK : F_RDLCK;
878         struct flock lock = ((struct flock) { .l_type   = type,
879                                               .l_whence = SEEK_SET,
880                                               .l_start  = 0,
881                                               .l_len    = 0 } );
882         int err, save;
883
884         err = fcntl(fd, F_SETLK, &lock);
885         if(!err)
886                 goto out;
887
888         save = -errno;
889         err = fcntl(fd, F_GETLK, &lock);
890         if(err){
891                 err = -errno;
892                 goto out;
893         }
894
895         printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
896         err = save;
897  out:
898         return(err);
899 }
900
901 int os_stat_filesystem(char *path, long *bsize_out, long long *blocks_out, 
902                        long long *bfree_out, long long *bavail_out, 
903                        long long *files_out, long long *ffree_out, 
904                        void *fsid_out, int fsid_size, long *namelen_out, 
905                        long *spare_out)
906 {
907         struct statfs64 buf;
908         int err;
909
910         err = statfs64(path, &buf);
911         if(err < 0)
912                 return(-errno);
913
914         *bsize_out = buf.f_bsize;
915         *blocks_out = buf.f_blocks;
916         *bfree_out = buf.f_bfree;
917         *bavail_out = buf.f_bavail;
918         *files_out = buf.f_files;
919         *ffree_out = buf.f_ffree;
920         memcpy(fsid_out, &buf.f_fsid, 
921                sizeof(buf.f_fsid) > fsid_size ? fsid_size : 
922                sizeof(buf.f_fsid));
923         *namelen_out = buf.f_namelen;
924         spare_out[0] = buf.f_spare[0];
925         spare_out[1] = buf.f_spare[1];
926         spare_out[2] = buf.f_spare[2];
927         spare_out[3] = buf.f_spare[3];
928         spare_out[4] = buf.f_spare[4];
929         spare_out[5] = buf.f_spare[5];
930         return(0);
931 }
932
933 /*
934  * Overrides for Emacs so that we follow Linus's tabbing style.
935  * Emacs will notice this stuff at the end of the file and automatically
936  * adjust the settings for this buffer only.  This must remain at the end
937  * of the file.
938  * ---------------------------------------------------------------------------
939  * Local variables:
940  * c-file-style: "linux"
941  * End:
942  */