Mercurial > gftp.yaz
diff lib/fsplib/lock.c @ 662:be9663e0be00
2005-1-16 Brian Masney <masneyb@gftp.org>
* lib/fsplib/COPYING lib/fsplib/Makefile.am lib/fsplib/fsplib.c
lib/fsplib/fsplib.h lib/fsplib/lock.c lib/fsplib/lock.h - added FSPLIB
This library is written by Radim Kolar <hsn@netmag.cz> and was included
with his permission
author | masneyb |
---|---|
date | Sun, 16 Jan 2005 16:12:13 +0000 |
parents | |
children | 4029ab7f13e4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fsplib/lock.c Sun Jan 16 16:12:13 2005 +0000 @@ -0,0 +1,285 @@ +#include <string.h> +#include <stdio.h> +#include "lock.h" + +/* ************ Locking functions ***************** */ +#ifndef FSP_NOLOCKING + +static char code_str[] = + "0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void make_key_string( FSP_LOCK *lock, + unsigned long server_addr, + unsigned long server_port) +{ + unsigned long v1, v2; + char *p; + + strcpy(lock->key_string,FSP_KEY_PREFIX); + for(p = lock->key_string; *p; p++); + v1 = server_addr; + v2 = server_port; + + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + v1 = v1 | (v2 << (32-3*6)); + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; + *p = 0; +} +#endif + +/********************************************************************/ +/******* For those systems that has SysV shared memory + semop ******/ +/********************************************************************/ +#ifdef FSP_USE_SHAREMEM_AND_SEMOP + +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> + +#ifdef _SEM_SEMUN_UNDEFINED +union semun +{ + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; +}; +#endif + +unsigned short client_get_key (FSP_LOCK *lock) +{ + struct sembuf sem; + sem.sem_num = 0; + sem.sem_op = -1; + sem.sem_flg = SEM_UNDO; + + if(semop(lock->lock_sem,&sem,1) == -1 ) + { + perror("semop lock"); + } + return(*lock->share_key); +} + +void client_set_key (FSP_LOCK *lock,unsigned short key) +{ + struct sembuf sem; + + sem.sem_num = 0; + sem.sem_op = 1; + sem.sem_flg = SEM_UNDO; + + *lock->share_key = key; + if(semop(lock->lock_sem,&sem,1) == -1) { + perror("semop unlock"); + } +} + +int client_init_key (FSP_LOCK *lock, + unsigned long server_addr, + unsigned short server_port) +{ + mode_t omask; + key_t lock_key; + int fd; + union semun sun; + struct sembuf sem; + + make_key_string(lock,server_addr,server_port); + + omask = umask(0); + fd = open(lock->key_string,O_RDWR|O_CREAT,0666); + umask(omask); + close(fd); + + if((lock_key = ftok(lock->key_string,238)) == -1) { + perror("ftok"); + return -1; + } + + if((lock->lock_shm = shmget(lock_key,2*sizeof(unsigned int),IPC_CREAT|0666)) == -1) { + perror("shmget"); + return -1; + } + + if(!(lock->share_key = (unsigned int *) shmat(lock->lock_shm,NULL,0))) { + perror("shmat"); + return -1; + } + + if((lock->lock_sem = semget(lock_key,0,0)) == -1) { + /* create a new semaphore and init it */ + if((lock->lock_sem = semget(lock_key,2,IPC_CREAT|0666)) == -1) { + perror("semget"); + return -1; + } + /* we need to init this semaphore */ + sun.val=1; + if(semctl(lock->lock_sem,0,SETVAL,sun) == -1) + { + perror("semctl setval"); + return -1; + } + } + + /* increase in use counter */ + sem.sem_num = 1; + sem.sem_op = 1; + sem.sem_flg = SEM_UNDO; + + if(semop(lock->lock_sem,&sem,1) == -1) { + perror("semop incuse"); + } + + return 0; +} + +void client_destroy_key(FSP_LOCK *lock) +{ + int rc; + struct sembuf sem; + + if (shmdt(lock->share_key) < 0) + { + perror("shmdt"); + return; + } + /* check if we are only one process holding lock */ + rc = semctl(lock->lock_sem,1,GETVAL); + if (rc == 1) + { + /* safe to destroy */ + if ( + (semctl(lock->lock_sem,0,IPC_RMID) < 0) || + (shmctl(lock->lock_shm,IPC_RMID,NULL) < 0) || + (unlink(lock->key_string) < 0) ) + rc=0;/* ignore cleanup errors */ + } + else + if(rc > 1) + { + /* we need to decrease sem. */ + sem.sem_num = 1; + sem.sem_op = -1; + sem.sem_flg = SEM_UNDO; + + if(semop(lock->lock_sem,&sem,1) == -1) { + perror("semop decuse"); + } + } +} +#endif + + +/********************************************************************/ +/******* For those who do not want to use locking *******************/ +/********************************************************************/ +#ifdef FSP_NOLOCKING + +unsigned short client_get_key (FSP_LOCK *lock) +{ + return lock->share_key; +} + +void client_set_key (FSP_LOCK *lock,unsigned short key) +{ + lock->share_key=key; +} + +int client_init_key (FSP_LOCK *lock, + unsigned long server_addr, + unsigned short server_port) +{ + return 0; +} + +void client_destroy_key(FSP_LOCK *lock) +{ + return; +} +#endif + +/********************************************************************/ +/******* For those systems that has lockf function call *************/ +/********************************************************************/ +#ifdef FSP_USE_LOCKF + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +unsigned short client_get_key (FSP_LOCK *lock) +{ + unsigned int okey; + + if (lockf(lock->lock_fd, F_LOCK, sizeof(okey)) < 0) + { + perror("lockf"); + } + + if (read(lock->lock_fd, &okey, sizeof(okey)) < 0) + { + perror("readlk"); + } + + if (lseek(lock->lock_fd, 0L, 0) < 0) + { + perror("seek"); + } + + return(okey); +} + +void client_set_key (FSP_LOCK *lock,unsigned short nkey) +{ + unsigned int key; + + key=nkey; + + if (write(lock->lock_fd, &key, sizeof(key)) < 0) + { + perror("write"); + } + if (lseek(lock->lock_fd, 0L, 0) < 0) + { + perror("seek"); + } + if (lockf(lock->lock_fd, F_ULOCK, sizeof(key)) < 0) + { + perror("unlockf"); + } +} + +int client_init_key (FSP_LOCK *lock, + unsigned long server_addr, + unsigned short server_port) +{ + mode_t omask; + + make_key_string(lock,server_addr, server_port); + + omask = umask(0); + lock->lock_fd = open(lock->key_string, O_RDWR | O_CREAT, 0666); + (void)umask(omask); + + if(lock->lock_fd < 0) + return -1; + else + return 0; +} + +void +client_destroy_key(FSP_LOCK *lock) +{ + (void)close(lock->lock_fd); +} +#endif