1*b30d1939SAndy Fiddaman /*********************************************************************** 2*b30d1939SAndy Fiddaman * * 3*b30d1939SAndy Fiddaman * This software is part of the ast package * 4*b30d1939SAndy Fiddaman * Copyright (c) 1985-2012 AT&T Intellectual Property * 5*b30d1939SAndy Fiddaman * and is licensed under the * 6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 * 7*b30d1939SAndy Fiddaman * by AT&T Intellectual Property * 8*b30d1939SAndy Fiddaman * * 9*b30d1939SAndy Fiddaman * A copy of the License is available at * 10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html * 11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12*b30d1939SAndy Fiddaman * * 13*b30d1939SAndy Fiddaman * Information and Software Systems Research * 14*b30d1939SAndy Fiddaman * AT&T Research * 15*b30d1939SAndy Fiddaman * Florham Park NJ * 16*b30d1939SAndy Fiddaman * * 17*b30d1939SAndy Fiddaman * Glenn Fowler <gsf@research.att.com> * 18*b30d1939SAndy Fiddaman * David Korn <dgk@research.att.com> * 19*b30d1939SAndy Fiddaman * Phong Vo <kpv@research.att.com> * 20*b30d1939SAndy Fiddaman * * 21*b30d1939SAndy Fiddaman ***********************************************************************/ 22*b30d1939SAndy Fiddaman #pragma prototyped 23*b30d1939SAndy Fiddaman 24*b30d1939SAndy Fiddaman #include "asohdr.h" 25*b30d1939SAndy Fiddaman 26*b30d1939SAndy Fiddaman #if defined(_UWIN) && defined(_BLD_ast) || !_aso_fcntl 27*b30d1939SAndy Fiddaman 28*b30d1939SAndy Fiddaman NoN(aso_meth_fcntl) 29*b30d1939SAndy Fiddaman 30*b30d1939SAndy Fiddaman #else 31*b30d1939SAndy Fiddaman 32*b30d1939SAndy Fiddaman #include <sys/stat.h> 33*b30d1939SAndy Fiddaman #include <fcntl.h> 34*b30d1939SAndy Fiddaman #include <unistd.h> 35*b30d1939SAndy Fiddaman 36*b30d1939SAndy Fiddaman typedef struct APL_s 37*b30d1939SAndy Fiddaman { 38*b30d1939SAndy Fiddaman int fd; 39*b30d1939SAndy Fiddaman size_t size; 40*b30d1939SAndy Fiddaman char path[1]; 41*b30d1939SAndy Fiddaman } APL_t; 42*b30d1939SAndy Fiddaman 43*b30d1939SAndy Fiddaman static void* 44*b30d1939SAndy Fiddaman aso_init_fcntl(void* data, const char* details) 45*b30d1939SAndy Fiddaman { 46*b30d1939SAndy Fiddaman APL_t* apl = (APL_t*)data; 47*b30d1939SAndy Fiddaman char* path; 48*b30d1939SAndy Fiddaman char* opt; 49*b30d1939SAndy Fiddaman size_t size; 50*b30d1939SAndy Fiddaman size_t references; 51*b30d1939SAndy Fiddaman int n; 52*b30d1939SAndy Fiddaman int fd; 53*b30d1939SAndy Fiddaman int drop; 54*b30d1939SAndy Fiddaman int perm; 55*b30d1939SAndy Fiddaman struct flock lock; 56*b30d1939SAndy Fiddaman char buf[PATH_MAX]; 57*b30d1939SAndy Fiddaman char tmp[64]; 58*b30d1939SAndy Fiddaman 59*b30d1939SAndy Fiddaman if (apl) 60*b30d1939SAndy Fiddaman { 61*b30d1939SAndy Fiddaman lock.l_type = F_WRLCK; 62*b30d1939SAndy Fiddaman lock.l_whence = SEEK_SET; 63*b30d1939SAndy Fiddaman lock.l_start = apl->size; 64*b30d1939SAndy Fiddaman lock.l_len = sizeof(references); 65*b30d1939SAndy Fiddaman if (fcntl(apl->fd, F_SETLKW, &lock) >= 0) 66*b30d1939SAndy Fiddaman { 67*b30d1939SAndy Fiddaman if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size) 68*b30d1939SAndy Fiddaman references = 0; 69*b30d1939SAndy Fiddaman else if (read(apl->fd, &references, sizeof(references)) != sizeof(references)) 70*b30d1939SAndy Fiddaman references = 0; 71*b30d1939SAndy Fiddaman else if (references > 0) 72*b30d1939SAndy Fiddaman { 73*b30d1939SAndy Fiddaman references--; 74*b30d1939SAndy Fiddaman if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size) 75*b30d1939SAndy Fiddaman references = 0; 76*b30d1939SAndy Fiddaman else if (write(apl->fd, &references, sizeof(references)) != sizeof(references)) 77*b30d1939SAndy Fiddaman references = 0; 78*b30d1939SAndy Fiddaman } 79*b30d1939SAndy Fiddaman lock.l_type = F_UNLCK; 80*b30d1939SAndy Fiddaman fcntl(apl->fd, F_SETLK, &lock); 81*b30d1939SAndy Fiddaman if (!references) 82*b30d1939SAndy Fiddaman remove(apl->path); 83*b30d1939SAndy Fiddaman } 84*b30d1939SAndy Fiddaman close(apl->fd); 85*b30d1939SAndy Fiddaman free(apl); 86*b30d1939SAndy Fiddaman return 0; 87*b30d1939SAndy Fiddaman } 88*b30d1939SAndy Fiddaman fd = -1; 89*b30d1939SAndy Fiddaman perm = S_IRUSR|S_IWUSR; 90*b30d1939SAndy Fiddaman drop = 0; 91*b30d1939SAndy Fiddaman size = 32 * 1024 - sizeof(references); 92*b30d1939SAndy Fiddaman if (path = (char*)details) 93*b30d1939SAndy Fiddaman while (opt = strchr(path, ',')) 94*b30d1939SAndy Fiddaman { 95*b30d1939SAndy Fiddaman if (strneq(path, "perm=", 5)) 96*b30d1939SAndy Fiddaman { 97*b30d1939SAndy Fiddaman if ((n = opt - (path + 5)) >= sizeof(tmp)) 98*b30d1939SAndy Fiddaman n = sizeof(tmp) - 1; 99*b30d1939SAndy Fiddaman memcpy(tmp, path + 5, n); 100*b30d1939SAndy Fiddaman tmp[n] = 0; 101*b30d1939SAndy Fiddaman perm = strperm(tmp, NiL, perm); 102*b30d1939SAndy Fiddaman } 103*b30d1939SAndy Fiddaman else if (strneq(path, "size=", 5)) 104*b30d1939SAndy Fiddaman { 105*b30d1939SAndy Fiddaman size = strtoul(path + 5, NiL, 0); 106*b30d1939SAndy Fiddaman if (size <= sizeof(references)) 107*b30d1939SAndy Fiddaman goto bad; 108*b30d1939SAndy Fiddaman size -= sizeof(references); 109*b30d1939SAndy Fiddaman } 110*b30d1939SAndy Fiddaman path = opt + 1; 111*b30d1939SAndy Fiddaman } 112*b30d1939SAndy Fiddaman if (!path || !*path) 113*b30d1939SAndy Fiddaman { 114*b30d1939SAndy Fiddaman if (!(path = pathtemp(buf, sizeof(buf), NiL, "aso", &fd))) 115*b30d1939SAndy Fiddaman return 0; 116*b30d1939SAndy Fiddaman drop = 1; 117*b30d1939SAndy Fiddaman } 118*b30d1939SAndy Fiddaman if (!(apl = newof(0, APL_t, 1, strlen(path)))) 119*b30d1939SAndy Fiddaman goto bad; 120*b30d1939SAndy Fiddaman if (fd >= 0 || (fd = open(path, O_RDWR|O_cloexec)) < 0 && (fd = open(path, O_CREAT|O_RDWR|O_cloexec, perm)) >= 0) 121*b30d1939SAndy Fiddaman { 122*b30d1939SAndy Fiddaman if (lseek(fd, size, SEEK_SET) != size) 123*b30d1939SAndy Fiddaman goto bad; 124*b30d1939SAndy Fiddaman references = 1; 125*b30d1939SAndy Fiddaman if (write(fd, &references, sizeof(references)) != sizeof(references)) 126*b30d1939SAndy Fiddaman goto bad; 127*b30d1939SAndy Fiddaman } 128*b30d1939SAndy Fiddaman else 129*b30d1939SAndy Fiddaman { 130*b30d1939SAndy Fiddaman if ((size = lseek(fd, 0, SEEK_END)) <= sizeof(references)) 131*b30d1939SAndy Fiddaman goto bad; 132*b30d1939SAndy Fiddaman size -= sizeof(references); 133*b30d1939SAndy Fiddaman lock.l_type = F_WRLCK; 134*b30d1939SAndy Fiddaman lock.l_whence = SEEK_SET; 135*b30d1939SAndy Fiddaman lock.l_start = 0; 136*b30d1939SAndy Fiddaman lock.l_len = sizeof(references); 137*b30d1939SAndy Fiddaman if (fcntl(fd, F_SETLKW, &lock) < 0) 138*b30d1939SAndy Fiddaman goto bad; 139*b30d1939SAndy Fiddaman if (lseek(fd, size, SEEK_SET) != size) 140*b30d1939SAndy Fiddaman goto bad; 141*b30d1939SAndy Fiddaman if (read(fd, &references, sizeof(references)) != sizeof(references)) 142*b30d1939SAndy Fiddaman goto bad; 143*b30d1939SAndy Fiddaman references++; 144*b30d1939SAndy Fiddaman if (lseek(fd, size, SEEK_SET) != size) 145*b30d1939SAndy Fiddaman goto bad; 146*b30d1939SAndy Fiddaman if (write(fd, &references, sizeof(references)) != sizeof(references)) 147*b30d1939SAndy Fiddaman goto bad; 148*b30d1939SAndy Fiddaman lock.l_type = F_UNLCK; 149*b30d1939SAndy Fiddaman fcntl(fd, F_SETLK, &lock); 150*b30d1939SAndy Fiddaman } 151*b30d1939SAndy Fiddaman apl->fd = fd; 152*b30d1939SAndy Fiddaman apl->size = size; 153*b30d1939SAndy Fiddaman strcpy(apl->path, path); 154*b30d1939SAndy Fiddaman return apl; 155*b30d1939SAndy Fiddaman bad: 156*b30d1939SAndy Fiddaman if (apl) 157*b30d1939SAndy Fiddaman free(apl); 158*b30d1939SAndy Fiddaman if (fd >= 0) 159*b30d1939SAndy Fiddaman close(fd); 160*b30d1939SAndy Fiddaman if (drop) 161*b30d1939SAndy Fiddaman remove(path); 162*b30d1939SAndy Fiddaman return 0; 163*b30d1939SAndy Fiddaman } 164*b30d1939SAndy Fiddaman 165*b30d1939SAndy Fiddaman static ssize_t 166*b30d1939SAndy Fiddaman aso_lock_fcntl(void* data, ssize_t k, void volatile* p) 167*b30d1939SAndy Fiddaman { 168*b30d1939SAndy Fiddaman APL_t* apl = (APL_t*)data; 169*b30d1939SAndy Fiddaman struct flock lock; 170*b30d1939SAndy Fiddaman 171*b30d1939SAndy Fiddaman if (!apl) 172*b30d1939SAndy Fiddaman return -1; 173*b30d1939SAndy Fiddaman if (k > 0) 174*b30d1939SAndy Fiddaman lock.l_type = F_UNLCK; 175*b30d1939SAndy Fiddaman else 176*b30d1939SAndy Fiddaman { 177*b30d1939SAndy Fiddaman lock.l_type = F_WRLCK; 178*b30d1939SAndy Fiddaman k = HASH(p, apl->size) + 1; 179*b30d1939SAndy Fiddaman } 180*b30d1939SAndy Fiddaman lock.l_whence = SEEK_SET; 181*b30d1939SAndy Fiddaman lock.l_start = k - 1; 182*b30d1939SAndy Fiddaman lock.l_len = 1; 183*b30d1939SAndy Fiddaman return fcntl(apl->fd, F_SETLKW, &lock) < 0 ? -1 : k; 184*b30d1939SAndy Fiddaman } 185*b30d1939SAndy Fiddaman 186*b30d1939SAndy Fiddaman Asometh_t _aso_meth_fcntl = { "fcntl", ASO_PROCESS, aso_init_fcntl, aso_lock_fcntl }; 187*b30d1939SAndy Fiddaman 188*b30d1939SAndy Fiddaman #endif 189