Mercurial > gftp.yaz
view lib/fsplib/lock.c @ 839:0d9a3d4188c3
2006-10-31 Brian Masney <masneyb@gftp.org>
WARNING: The CVS version of gFTP is currently broken, especially for
international users. This will be fixed in a few days.
* lib/sshv2.c (sshv2_add_string_to_buf) - added length argument to
this function.
author | masneyb |
---|---|
date | Wed, 01 Nov 2006 02:31:06 +0000 |
parents | db4b34e3f83f |
children | 26fb4e66736c |
line wrap: on
line source
#include <string.h> #include <stdio.h> #include "lock.h" #if defined(__NetBSD__) || defined(sun) || defined(hpux) #define _SEM_SEMUN_UNDEFINED /**/ #endif /* ************ 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 su; 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 */ su.val=1; if(semctl(lock->lock_sem,0,SETVAL,su) == -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