Home | History | Annotate | Download | only in doio
      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  ***********************************************************************/
     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  ***********************************************************************/
    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