* Fix some compiler warnings for bad casting in some functions in the file
[alpine.git] / imap / src / osdep / unix / flocklnx.c
blob3dc6b5dc4d3ea3e9361544d84516d7474095b8b1
1 /* ========================================================================
2 * Copyright 2008-2009 Mark Crispin
3 * ========================================================================
4 */
6 /*
7 * Program: Safe File Lock for Linux
9 * Author: Mark Crispin
11 * Date: 20 April 2005
12 * Last Edited: 18 May 2009
14 * Previous versions of this file were:
16 * Copyright 1988-2006 University of Washington
18 * Licensed under the Apache License, Version 2.0 (the "License");
19 * you may not use this file except in compliance with the License.
20 * You may obtain a copy of the License at
22 * http://www.apache.org/licenses/LICENSE-2.0
25 \f
26 #undef flock
28 #include <sys/vfs.h>
29 #ifndef NFS_SUPER_MAGIC
30 #define NFS_SUPER_MAGIC 0x6969
31 #endif
33 int safe_flock (int fd,int op)
35 struct statfs sfbuf;
36 char tmp[MAILTMPLEN];
37 int e;
38 int logged = 0;
39 /* Check for NFS because Linux 2.6 broke flock() on NFS. Instead of being
40 * a no-op, flock() on NFS now returns ENOLCK. Read
41 * https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=123415
42 * for the gruesome details.
44 /* check filesystem type */
45 while ((e = fstatfs (fd,&sfbuf)) && (errno == EINTR));
46 if (!e) switch (sfbuf.f_type) {
47 case NFS_SUPER_MAGIC: /* always a fast no-op on NFS */
48 break;
49 default: /* allow on other filesystem types */
50 /* do the lock */
51 while (flock (fd,op)) switch (errno) {
52 case EINTR: /* interrupt */
53 break;
54 case ENOLCK: /* lock table is full */
55 sprintf (tmp,"File locking failure: %s",strerror (errno));
56 mm_log (tmp,WARN); /* give the user a warning of what happened */
57 if (!logged++) syslog (LOG_ERR,"%s",tmp);
58 /* return failure if non-blocking lock */
59 if (op & LOCK_NB) return -1;
60 sleep (5); /* slow down in case it loops */
61 break;
62 case EWOULDBLOCK: /* file is locked, LOCK_NB should be set */
63 if (op & LOCK_NB) return -1;
64 case EBADF: /* not valid open file descriptor */
65 case EINVAL: /* invalid operator */
66 default: /* other error code? */
67 sprintf (tmp,"Unexpected file locking failure: %s",strerror (errno));
68 fatal (tmp);
70 break;
72 return 0; /* success */