1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 /*
3  * lib/krb5/os/lock_file.c
4  *
5  * Copyright 1990, 1998 by the Massachusetts Institute of Technology.
6  * All Rights Reserved.
7  *
8  * Export of this software from the United States of America may
9  *   require a specific license from the United States Government.
10  *   It is the responsibility of any person or organization contemplating
11  *   export to obtain such a license before exporting.
12  *
13  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14  * distribute this software and its documentation for any purpose and
15  * without fee is hereby granted, provided that the above copyright
16  * notice appear in all copies and that both that copyright notice and
17  * this permission notice appear in supporting documentation, and that
18  * the name of M.I.T. not be used in advertising or publicity pertaining
19  * to distribution of the software without specific, written prior
20  * permission.  Furthermore if you modify this software you must label
21  * your software as modified software and not distribute it in such a
22  * fashion that it might be confused with the original M.I.T. software.
23  * M.I.T. makes no representations about the suitability of
24  * this software for any purpose.  It is provided "as is" without express
25  * or implied warranty.
26  *
27  *
28  * libos: krb5_lock_file routine
29  */
30 
31 #include <k5-int.h>
32 #include <stdio.h>
33 
34 #if !defined(_WIN32)
35 
36 /* Unix version...  */
37 
38 #if HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41 
42 #include <errno.h>
43 
44 #ifdef HAVE_FCNTL_H
45 #include <fcntl.h>
46 #endif
47 
48 #if defined(HAVE_FCNTL_H) && defined(F_SETLKW) && defined(F_RDLCK)
49 #define POSIX_FILE_LOCKS
50 #endif
51 
52 #ifdef HAVE_FLOCK
53 #ifndef sysvimp
54 #include <sys/file.h>
55 #endif
56 #else
57 #ifndef LOCK_SH
58 #define LOCK_SH 0
59 #define LOCK_EX 0
60 #define LOCK_UN 0
61 #endif
62 #endif
63 
64 /*ARGSUSED*/
65 krb5_error_code
66 krb5_lock_file(krb5_context context, int fd, int mode)
67 {
68     int 		lock_flag = -1;
69     krb5_error_code	retval = 0;
70 #ifdef POSIX_FILE_LOCKS
71     int lock_cmd = F_SETLKW;
72     static struct flock flock_zero;
73     struct flock lock_arg = { 0 };
74 
75     lock_arg = flock_zero;
76 #endif
77 
78     switch (mode & ~KRB5_LOCKMODE_DONTBLOCK) {
79     case KRB5_LOCKMODE_SHARED:
80 #ifdef POSIX_FILE_LOCKS
81 	lock_arg.l_type = F_RDLCK;
82 #endif
83 	lock_flag = LOCK_SH;
84 	break;
85     case KRB5_LOCKMODE_EXCLUSIVE:
86 #ifdef POSIX_FILE_LOCKS
87 	lock_arg.l_type = F_WRLCK;
88 #endif
89 	lock_flag = LOCK_EX;
90 	break;
91     case KRB5_LOCKMODE_UNLOCK:
92 #ifdef POSIX_FILE_LOCKS
93 	lock_arg.l_type = F_UNLCK;
94 #endif
95 	lock_flag = LOCK_UN;
96 	break;
97     }
98 
99     if (lock_flag == -1)
100 	return(KRB5_LIBOS_BADLOCKFLAG);
101 
102     if (mode & KRB5_LOCKMODE_DONTBLOCK) {
103 #ifdef POSIX_FILE_LOCKS
104 	lock_cmd = F_SETLK;
105 #endif
106 #ifdef HAVE_FLOCK
107 	lock_flag |= LOCK_NB;
108 #endif
109     }
110 
111 #ifdef POSIX_FILE_LOCKS
112     lock_arg.l_whence = 0;
113     lock_arg.l_start = 0;
114     lock_arg.l_len = 0;
115     if (fcntl(fd, lock_cmd, &lock_arg) == -1) {
116 	if (errno == EACCES || errno == EAGAIN)	/* see POSIX/IEEE 1003.1-1988,
117 						   6.5.2.4 */
118 	    return(EAGAIN);
119 	if (errno != EINVAL)	/* Fall back to flock if we get EINVAL */
120 	    return(errno);
121 	retval = errno;
122     } else
123 	    return 0;		/* We succeeded.  Yay. */
124 #endif
125 
126 #ifdef HAVE_FLOCK
127     if (flock(fd, lock_flag) == -1)
128 	retval = errno;
129 #endif
130 
131     return retval;
132 }
133 #else   /* Windows or Macintosh */
134 
135 krb5_error_code
136 krb5_lock_file(context, fd, mode)
137     krb5_context context;
138     int fd;
139     int mode;
140 {
141     return 0;
142 }
143 #endif
144