1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 */
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/file.h>
35 #include <sys/param.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <errno.h>
40 #include <sys/sysmacros.h>
41 #include <string.h> /* memset, strerror */
42 #include "file_lock.h"
43
44 #ifndef EFSEXCLWR
45 #define EFSEXCLWR 503
46 #endif
47
48 /*
49 * String containing the last system call.
50 *
51 */
52 char Fl_syscall_str[128];
53
54 static char errmsg[256];
55
56 /***********************************************************************
57 *
58 * Test interface to the fcntl system call.
59 * It will loop if the LOCK_NB flags is NOT set.
60 ***********************************************************************/
file_lock(int fd,int flags,char ** errormsg)61 int file_lock(int fd, int flags, char **errormsg)
62 {
63 register int cmd, ret;
64 struct flock flocks;
65
66 memset(&flocks, 0, sizeof(struct flock));
67
68 if (flags & LOCK_NB)
69 cmd = F_SETLK;
70 else
71 cmd = F_SETLKW;
72
73 flocks.l_whence = 0;
74 flocks.l_start = 0;
75 flocks.l_len = 0;
76
77 if (flags & LOCK_UN)
78 flocks.l_type = F_UNLCK;
79 else if (flags & LOCK_EX)
80 flocks.l_type = F_WRLCK;
81 else if (flags & LOCK_SH)
82 flocks.l_type = F_RDLCK;
83 else {
84 errno = EINVAL;
85 if (errormsg != NULL) {
86 sprintf(errmsg,
87 "Programmer error, called file_lock with in valid flags\n");
88 *errormsg = errmsg;
89 }
90 return -1;
91 }
92
93 sprintf(Fl_syscall_str,
94 "fcntl(%d, %d, &flocks): type:%d whence:%d, start:%lld len:%lld\n",
95 fd, cmd, flocks.l_type, flocks.l_whence,
96 (long long)flocks.l_start, (long long)flocks.l_len);
97
98 while (1) {
99 ret = fcntl(fd, cmd, &flocks);
100
101 if (ret < 0) {
102 if (cmd == F_SETLK)
103 switch (errno) {
104 /* these errors are okay */
105 case EACCES: /* Permission denied */
106 case EINTR: /* interrupted system call */
107 #ifdef EFILESH
108 case EFILESH: /* file shared */
109 #endif
110 case EFSEXCLWR: /* File is write protected */
111 continue; /* retry getting lock */
112 }
113 if (errormsg != NULL) {
114 sprintf(errmsg,
115 "fcntl(%d, %d, &flocks): errno:%d %s\n",
116 fd, cmd, errno, strerror(errno));
117 *errormsg = errmsg;
118 }
119 return -1;
120 }
121 break;
122 }
123
124 return ret;
125
126 } /* end of file_lock */
127
128 /***********************************************************************
129 *
130 * Test interface to the fcntl system call.
131 * It will loop if the LOCK_NB flags is NOT set.
132 ***********************************************************************/
record_lock(int fd,int flags,int start,int len,char ** errormsg)133 int record_lock(int fd, int flags, int start, int len, char **errormsg)
134 {
135 register int cmd, ret;
136 struct flock flocks;
137
138 memset(&flocks, 0, sizeof(struct flock));
139
140 if (flags & LOCK_NB)
141 cmd = F_SETLK;
142 else
143 cmd = F_SETLKW;
144
145 flocks.l_whence = 0;
146 flocks.l_start = start;
147 flocks.l_len = len;
148
149 if (flags & LOCK_UN)
150 flocks.l_type = F_UNLCK;
151 else if (flags & LOCK_EX)
152 flocks.l_type = F_WRLCK;
153 else if (flags & LOCK_SH)
154 flocks.l_type = F_RDLCK;
155 else {
156 errno = EINVAL;
157 if (errormsg != NULL) {
158 sprintf(errmsg,
159 "Programmer error, called record_lock with in valid flags\n");
160 *errormsg = errmsg;
161 }
162 return -1;
163 }
164
165 sprintf(Fl_syscall_str,
166 "fcntl(%d, %d, &flocks): type:%d whence:%d, start:%lld len:%lld\n",
167 fd, cmd, flocks.l_type, flocks.l_whence,
168 (long long)flocks.l_start, (long long)flocks.l_len);
169
170 while (1) {
171 ret = fcntl(fd, cmd, &flocks);
172
173 if (ret < 0) {
174 if (cmd == F_SETLK)
175 switch (errno) {
176 /* these errors are okay */
177 case EACCES: /* Permission denied */
178 case EINTR: /* interrupted system call */
179 #ifdef EFILESH
180 case EFILESH: /* file shared */
181 #endif
182 case EFSEXCLWR: /* File is write protected */
183 continue; /* retry getting lock */
184 }
185 if (errormsg != NULL) {
186 sprintf(errmsg,
187 "fcntl(%d, %d, &flocks): errno:%d %s\n",
188 fd, cmd, errno, strerror(errno));
189 *errormsg = errmsg;
190 }
191 return -1;
192 }
193 break;
194 }
195
196 return ret;
197
198 } /* end of record_lock */
199