17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 22*61961e0fSrobinson 237c478bd9Sstevel@tonic-gate /* 24*61961e0fSrobinson * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25*61961e0fSrobinson * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 30*61961e0fSrobinson #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include "uucp.h" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <unistd.h> 35*61961e0fSrobinson #include <stdlib.h> 367c478bd9Sstevel@tonic-gate /* #include <sys/types.h> */ 377c478bd9Sstevel@tonic-gate /* #include <sys/stat.h> */ 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #undef _STAT 407c478bd9Sstevel@tonic-gate #undef _FSTAT 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #define _STAT stat64 437c478bd9Sstevel@tonic-gate #define _FSTAT fstat64 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate static void stlock(); 467c478bd9Sstevel@tonic-gate static int onelock(); 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * make a lock file with given 'name' 507c478bd9Sstevel@tonic-gate * If one already exists, send a signal 0 to the process--if 517c478bd9Sstevel@tonic-gate * it fails, then unlink it and make a new one. 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * input: 547c478bd9Sstevel@tonic-gate * name - name of the lock file to make 557c478bd9Sstevel@tonic-gate * 567c478bd9Sstevel@tonic-gate * return: 577c478bd9Sstevel@tonic-gate * 0 -> success 587c478bd9Sstevel@tonic-gate * FAIL -> failure 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate 61*61961e0fSrobinson static int 62*61961e0fSrobinson mklock(char *name) 637c478bd9Sstevel@tonic-gate { 647c478bd9Sstevel@tonic-gate static char pid[SIZEOFPID+2] = { '\0' }; /* +2 for '\n' and NULL */ 657c478bd9Sstevel@tonic-gate static char *tempfile; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate if (pid[0] == '\0') { 68*61961e0fSrobinson tempfile = malloc(MAXNAMESIZE); 697c478bd9Sstevel@tonic-gate if (tempfile == NULL) 707c478bd9Sstevel@tonic-gate return (FAIL); 717c478bd9Sstevel@tonic-gate (void) sprintf(pid, "%*ld\n", SIZEOFPID, (long)getpid()); 72*61961e0fSrobinson (void) snprintf(tempfile, MAXNAMESIZE, "%s/LTMP.%ld", X_LOCKDIR, 73*61961e0fSrobinson (long)getpid()); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, name) == -1) { 777c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 78*61961e0fSrobinson if (cklock(name)) 797c478bd9Sstevel@tonic-gate return (FAIL); 807c478bd9Sstevel@tonic-gate else { 817c478bd9Sstevel@tonic-gate if (onelock(pid, tempfile, name)) { 827c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 837c478bd9Sstevel@tonic-gate DEBUG(4, "ulockf failed in onelock()\n%s", ""); 847c478bd9Sstevel@tonic-gate return (FAIL); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate stlock(name); 897c478bd9Sstevel@tonic-gate return (0); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * check to see if the lock file exists and is still active 947c478bd9Sstevel@tonic-gate * - use kill(pid, 0) 957c478bd9Sstevel@tonic-gate * 967c478bd9Sstevel@tonic-gate * return: 977c478bd9Sstevel@tonic-gate * 0 -> success (lock file removed - no longer active 987c478bd9Sstevel@tonic-gate * FAIL -> lock file still active 997c478bd9Sstevel@tonic-gate */ 100*61961e0fSrobinson static int 101*61961e0fSrobinson cklock(char *name) 1027c478bd9Sstevel@tonic-gate { 103*61961e0fSrobinson int ret; 1047c478bd9Sstevel@tonic-gate pid_t lpid = -1; 1057c478bd9Sstevel@tonic-gate char alpid[SIZEOFPID+2]; /* +2 for '\n' and NULL */ 1067c478bd9Sstevel@tonic-gate int fd; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate fd = open(name, O_RDONLY); 1097c478bd9Sstevel@tonic-gate DEBUG(4, "ulockf name %s\n", name); 1107c478bd9Sstevel@tonic-gate if (fd == -1) { 1117c478bd9Sstevel@tonic-gate if (errno == ENOENT) { /* file does not exist -- OK */ 1127c478bd9Sstevel@tonic-gate return (0); 1137c478bd9Sstevel@tonic-gate } 114*61961e0fSrobinson DEBUG(4, "Lock File--can't read (errno %d) --remove it!\n", 115*61961e0fSrobinson errno); 1167c478bd9Sstevel@tonic-gate goto unlk; 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate ret = read(fd, (char *)alpid, SIZEOFPID + 1); /* +1 for '\n' */ 1197c478bd9Sstevel@tonic-gate (void) close(fd); 1207c478bd9Sstevel@tonic-gate if (ret != (SIZEOFPID+1)) { 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate DEBUG(4, "Lock File--bad format--remove it!\n%s", ""); 1237c478bd9Sstevel@tonic-gate goto unlk; 1247c478bd9Sstevel@tonic-gate } 125*61961e0fSrobinson lpid = (pid_t)strtol(alpid, NULL, 10); 1267c478bd9Sstevel@tonic-gate if ((ret = kill(lpid, 0)) == 0 || errno == EPERM) { 127*61961e0fSrobinson DEBUG(4, "Lock File--process still active--not removed\n%s", 128*61961e0fSrobinson ""); 1297c478bd9Sstevel@tonic-gate return (FAIL); 1307c478bd9Sstevel@tonic-gate } 131*61961e0fSrobinson /* process no longer active */ 1327c478bd9Sstevel@tonic-gate DEBUG(4, "kill pid (%ld), ", (long)lpid); 1337c478bd9Sstevel@tonic-gate DEBUG(4, "returned %d", ret); 1347c478bd9Sstevel@tonic-gate DEBUG(4, "--ok to remove lock file (%s)\n", name); 1357c478bd9Sstevel@tonic-gate unlk: 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate if (unlink(name) != 0) { 1387c478bd9Sstevel@tonic-gate DEBUG(4, "ulockf failed in unlink()\n%s", ""); 1397c478bd9Sstevel@tonic-gate return (FAIL); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate return (0); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate #define MAXLOCKS 10 /* maximum number of lock files */ 1457c478bd9Sstevel@tonic-gate static char *Lockfile[MAXLOCKS]; 146*61961e0fSrobinson static int Nlocks = 0; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * put name in list of lock files 1507c478bd9Sstevel@tonic-gate * return: 1517c478bd9Sstevel@tonic-gate * none 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate static void 154*61961e0fSrobinson stlock(char *name) 1557c478bd9Sstevel@tonic-gate { 156*61961e0fSrobinson int i; 1577c478bd9Sstevel@tonic-gate char *p; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) { 1607c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL) 1617c478bd9Sstevel@tonic-gate break; 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", "", i); 1647c478bd9Sstevel@tonic-gate if (i >= Nlocks) 1657c478bd9Sstevel@tonic-gate i = Nlocks++; 166*61961e0fSrobinson p = calloc((unsigned)strlen(name) + 1, sizeof (char)); 1677c478bd9Sstevel@tonic-gate ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0); 1687c478bd9Sstevel@tonic-gate (void) strcpy(p, name); 1697c478bd9Sstevel@tonic-gate Lockfile[i] = p; 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * remove the named lock. If named lock is NULL, 1747c478bd9Sstevel@tonic-gate * then remove all locks currently in list. 1757c478bd9Sstevel@tonic-gate * return: 1767c478bd9Sstevel@tonic-gate * none 1777c478bd9Sstevel@tonic-gate */ 178*61961e0fSrobinson static void 179*61961e0fSrobinson rmlock(char *name) 1807c478bd9Sstevel@tonic-gate { 181*61961e0fSrobinson int i; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate for (i = 0; i < Nlocks; i++) { 1847c478bd9Sstevel@tonic-gate if (Lockfile[i] == NULL) 1857c478bd9Sstevel@tonic-gate continue; 1867c478bd9Sstevel@tonic-gate if (name == NULL || EQUALS(name, Lockfile[i])) { 1877c478bd9Sstevel@tonic-gate (void) unlink(Lockfile[i]); 1887c478bd9Sstevel@tonic-gate free(Lockfile[i]); 1897c478bd9Sstevel@tonic-gate Lockfile[i] = NULL; 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * makes a lock on behalf of pid. 1967c478bd9Sstevel@tonic-gate * input: 1977c478bd9Sstevel@tonic-gate * pid - process id 1987c478bd9Sstevel@tonic-gate * tempfile - name of a temporary in the same file system 1997c478bd9Sstevel@tonic-gate * name - lock file name (full path name) 2007c478bd9Sstevel@tonic-gate * return: 2017c478bd9Sstevel@tonic-gate * -1 - failed 2027c478bd9Sstevel@tonic-gate * 0 - lock made successfully 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate static int 205*61961e0fSrobinson onelock(char *pid, char *tempfile, char *name) 2067c478bd9Sstevel@tonic-gate { 207*61961e0fSrobinson int fd; 2087c478bd9Sstevel@tonic-gate char cb[100]; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate fd = creat(tempfile, (mode_t)0444); 2117c478bd9Sstevel@tonic-gate if (fd < 0) { 212*61961e0fSrobinson (void) snprintf(cb, sizeof (cb), 213*61961e0fSrobinson "%s %s %d", tempfile, name, errno); 2147c478bd9Sstevel@tonic-gate logent("ULOCKC", cb); 2157c478bd9Sstevel@tonic-gate if ((errno == EMFILE) || (errno == ENFILE)) 2167c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 2177c478bd9Sstevel@tonic-gate return (-1); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate /* +1 for '\n' */ 2207c478bd9Sstevel@tonic-gate if (write(fd, pid, SIZEOFPID+1) != (SIZEOFPID+1)) { 221*61961e0fSrobinson (void) snprintf(cb, sizeof (cb), 222*61961e0fSrobinson "%s %s %d", tempfile, name, errno); 2237c478bd9Sstevel@tonic-gate logent("ULOCKW", cb); 2247c478bd9Sstevel@tonic-gate (void) unlink(tempfile); 2257c478bd9Sstevel@tonic-gate return (-1); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate (void) chmod(tempfile, (mode_t)0444); 2287c478bd9Sstevel@tonic-gate (void) chown(tempfile, UUCPUID, UUCPGID); 2297c478bd9Sstevel@tonic-gate (void) close(fd); 2307c478bd9Sstevel@tonic-gate if (link(tempfile, name) < 0) { 2317c478bd9Sstevel@tonic-gate DEBUG(4, "%s: ", strerror(errno)); 2327c478bd9Sstevel@tonic-gate DEBUG(4, "link(%s, ", tempfile); 2337c478bd9Sstevel@tonic-gate DEBUG(4, "%s)\n", name); 2347c478bd9Sstevel@tonic-gate if (unlink(tempfile) < 0) { 235*61961e0fSrobinson (void) snprintf(cb, sizeof (cb), 236*61961e0fSrobinson "ULK err %s %d", tempfile, errno); 2377c478bd9Sstevel@tonic-gate logent("ULOCKLNK", cb); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate return (-1); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate if (unlink(tempfile) < 0) { 242*61961e0fSrobinson (void) snprintf(cb, sizeof (cb), "%s %d", tempfile, errno); 2437c478bd9Sstevel@tonic-gate logent("ULOCKF", cb); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate return (0); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * fd_mklock(fd) - lock the device indicated by fd is possible 2507c478bd9Sstevel@tonic-gate * 2517c478bd9Sstevel@tonic-gate * return - 2527c478bd9Sstevel@tonic-gate * SUCCESS - this process now has the fd locked 2537c478bd9Sstevel@tonic-gate * FAIL - this process was not able to lock the fd 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate 256*61961e0fSrobinson static int 257*61961e0fSrobinson fd_mklock(int fd) 2587c478bd9Sstevel@tonic-gate { 2597c478bd9Sstevel@tonic-gate int tries = 0; 2607c478bd9Sstevel@tonic-gate struct stat64 _st_buf; 2617c478bd9Sstevel@tonic-gate char lockname[BUFSIZ]; 2627c478bd9Sstevel@tonic-gate 263*61961e0fSrobinson if (_FSTAT(fd, &_st_buf) != 0) 2647c478bd9Sstevel@tonic-gate return (FAIL); 2657c478bd9Sstevel@tonic-gate 266*61961e0fSrobinson (void) snprintf(lockname, sizeof (lockname), 267*61961e0fSrobinson "%s.%3.3lu.%3.3lu.%3.3lu", L_LOCK, 2687c478bd9Sstevel@tonic-gate (unsigned long)major(_st_buf.st_dev), 2697c478bd9Sstevel@tonic-gate (unsigned long)major(_st_buf.st_rdev), 2707c478bd9Sstevel@tonic-gate (unsigned long)minor(_st_buf.st_rdev)); 2717c478bd9Sstevel@tonic-gate 272*61961e0fSrobinson if (mklock(lockname) == FAIL) 2737c478bd9Sstevel@tonic-gate return (FAIL); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate while (lockf(fd, F_TLOCK, 0L) != 0) { 2767c478bd9Sstevel@tonic-gate DEBUG(7, "fd_mklock: lockf returns %d\n", errno); 2777c478bd9Sstevel@tonic-gate if ((++tries >= MAX_LOCKTRY) || (errno != EAGAIN)) { 2787c478bd9Sstevel@tonic-gate rmlock(lockname); 2797c478bd9Sstevel@tonic-gate logent("fd_mklock", "lockf failed"); 2807c478bd9Sstevel@tonic-gate return (FAIL); 2817c478bd9Sstevel@tonic-gate } 282*61961e0fSrobinson (void) sleep(2); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate DEBUG(7, "fd_mklock: ok\n%s", ""); 2857c478bd9Sstevel@tonic-gate return (SUCCESS); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * remove the locks associated with the device file descriptor 2907c478bd9Sstevel@tonic-gate * 2917c478bd9Sstevel@tonic-gate * return - 2927c478bd9Sstevel@tonic-gate * SUCCESS - both BNU lock file and advisory locks removed 2937c478bd9Sstevel@tonic-gate * FAIL - 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate 296*61961e0fSrobinson static void 297*61961e0fSrobinson fd_rmlock(int fd) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate struct stat64 _st_buf; 3007c478bd9Sstevel@tonic-gate char lockname[BUFSIZ]; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (_FSTAT(fd, &_st_buf) == 0) { 303*61961e0fSrobinson (void) snprintf(lockname, sizeof (lockname), 304*61961e0fSrobinson "%s.%3.3lu.%3.3lu.%3.3lu", L_LOCK, 3057c478bd9Sstevel@tonic-gate (unsigned long)major(_st_buf.st_dev), 3067c478bd9Sstevel@tonic-gate (unsigned long)major(_st_buf.st_rdev), 3077c478bd9Sstevel@tonic-gate (unsigned long)minor(_st_buf.st_rdev)); 3087c478bd9Sstevel@tonic-gate rmlock(lockname); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate (void) lockf(fd, F_ULOCK, 0L); 3117c478bd9Sstevel@tonic-gate } 312