# HG changeset patch # User masneyb # Date 1105891933 0 # Node ID be9663e0be0080255f13b7245f1f9332b73b3b2e # Parent 2e718fba351e0223e11a0f9e7caaa9b463eae45c 2005-1-16 Brian Masney * 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 and was included with his permission diff -r 2e718fba351e -r be9663e0be00 ChangeLog --- a/ChangeLog Sun Jan 16 15:48:24 2005 +0000 +++ b/ChangeLog Sun Jan 16 16:12:13 2005 +0000 @@ -1,4 +1,9 @@ 2005-1-16 Brian Masney + * 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 and was included + with his permission + * lib/fsp.c lib/options.h lib/gftp.h - added support for the FSP protocol (from Radim Kolar ). Note, I need to update the build system for gftp to compile properly @@ -3212,7 +3217,7 @@ * cvsclean - added this script - * *.[ch] - added $Id: ChangeLog,v 1.391 2005/01/16 15:48:23 masneyb Exp $ tags + * *.[ch] - added $Id: ChangeLog,v 1.392 2005/01/16 16:12:13 masneyb Exp $ tags * debian/* - updated files from Debian maintainer diff -r 2e718fba351e -r be9663e0be00 lib/fsplib/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fsplib/COPYING Sun Jan 16 16:12:13 2005 +0000 @@ -0,0 +1,9 @@ +Copyright (c) 2003-2004 by Radim HSN Kolar + +You may copy or modify this file in any manner you wish, provided +that this notice is always included, and that you hold the author +harmless for any loss or damage resulting from the installation or +use of this software. + + This is a free software. Be creative. + Let me know of any bugs and suggestions. diff -r 2e718fba351e -r be9663e0be00 lib/fsplib/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fsplib/Makefile.am Sun Jan 16 16:12:13 2005 +0000 @@ -0,0 +1,6 @@ +## Process this file with automake to produce Makefile.in + +noinst_LIBRARIES = libfsp.a +libfsp_a_SOURCES=fsplib.c lock.c +INCLUDES=-DFSP_USE_SHAREMEM_AND_SEMOP=1 +noinst_HEADERS=fsplib.h lock.h diff -r 2e718fba351e -r be9663e0be00 lib/fsplib/fsplib.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fsplib/fsplib.c Sun Jan 16 16:12:13 2005 +0000 @@ -0,0 +1,1362 @@ +/* +This file is part of fsplib - FSP protocol stack implemented in C +language. See http://fsp.sourceforge.net for more information. + +Copyright (c) 2003-2004 by Radim HSN Kolar (hsn@netmag.cz) + +You may copy or modify this file in any manner you wish, provided +that this notice is always included, and that you hold the author +harmless for any loss or damage resulting from the installation or +use of this software. + + This is a free software. Be creative. + Let me know of any bugs and suggestions. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fsplib.h" +#include "lock.h" + +/* ************ Internal functions **************** */ + +/* builds filename in packet output buffer, appends password if needed */ +static int buildfilename(const FSP_SESSION *s,FSP_PKT *out,const char *dirname) +{ + int len; + + len=strlen(dirname); + if(len >= FSP_SPACE - 1) + { + errno = ENAMETOOLONG; + return -1; + } + /* copy name + \0 */ + memcpy(out->buf,dirname,len+1); + out->len=len; + if(s->password) + { + out->buf[len]='\n'; + out->len++; + + len=strlen(s->password); + if(out->len+ len >= FSP_SPACE -1 ) + { + errno = ENAMETOOLONG; + return -1; + } + memcpy(out->buf+out->len,s->password,len+1); + out->len+=len; + } + /* add terminating \0 */ + out->len++; + return 0; +} + +/* simple FSP command */ +static int simplecommand(FSP_SESSION *s,const char *directory,unsigned char command) +{ + FSP_PKT in,out; + + if(buildfilename(s,&out,directory)) + return -1; + out.cmd=command; + out.xlen=0; + out.pos=0; + + if(fsp_transaction(s,&out,&in)) + return -1; + + if(in.cmd == FSP_CC_ERR) + { + errno = EPERM; + return -1; + } + + if(in.cmd != command) + { + errno = ENOMSG; + return -1; + } + + errno = 0; + return 0; +} +/* Get directory part of filename. You must free() the result */ +static char * directoryfromfilename(const char *filename) +{ + char *result; + char *tmp; + int pos; + + result=strrchr(filename,'/'); + if (result == NULL) + return strdup(""); + pos=result-filename; + tmp=malloc(pos+1); + if(!tmp) + return NULL; + memcpy(tmp,filename,pos); + tmp[pos]='\0'; + return tmp; +} + +/* ************ Packet encoding / decoding *************** */ + +/* write binary representation of FSP packet p into *space. */ +/* returns number of bytes used or zero on error */ +/* Space must be long enough to hold created packet. */ +/* Maximum created packet size is FSP_MAXPACKET */ + +size_t fsp_pkt_write(const FSP_PKT *p,void *space) +{ + size_t used; + unsigned char *ptr; + int checksum; + size_t i; + + if(p->xlen + p->len > FSP_SPACE ) + { + /* not enough space */ + errno = EMSGSIZE; + return 0; + } + ptr=space; + /* pack header */ + ptr[FSP_OFFSET_CMD]=p->cmd; + ptr[FSP_OFFSET_SUM]=0; + *(uint16_t *)(ptr+FSP_OFFSET_KEY)=htons(p->key); + *(uint16_t *)(ptr+FSP_OFFSET_SEQ)=htons(p->seq); + *(uint16_t *)(ptr+FSP_OFFSET_LEN)=htons(p->len); + *(uint32_t *)(ptr+FSP_OFFSET_POS)=htonl(p->pos); + used=FSP_HSIZE; + /* copy data block */ + memcpy(ptr+FSP_HSIZE,p->buf,p->len); + used+=p->len; + /* copy extra data block */ + memcpy(ptr+used,p->buf+p->len,p->xlen); + used+=p->xlen; + /* compute checksum */ + checksum = 0; + for(i=0;i> 8); + return used; +} + +/* read binary representation of FSP packet received from network into p */ +/* return zero on success */ +int fsp_pkt_read(FSP_PKT *p,const void *space,size_t recv_len) +{ + int mysum; + size_t i; + const unsigned char *ptr; + + if(recv_lenFSP_MAXPACKET) + { + /* too long */ + errno = EMSGSIZE; + return -1; + } + + ptr=space; + /* check sum */ + mysum=-ptr[FSP_OFFSET_SUM]; + for(i=0;i> 8)) & 0xff; + + if(mysum != ptr[FSP_OFFSET_SUM]) + { + /* checksum failed */ + +#ifdef MAINTAINER_MODE + printf("mysum: %x, got %x\n",mysum,ptr[FSP_OFFSET_SUM]); +#endif + errno = EIO; + return -1; + } + + /* unpack header */ + p->cmd=ptr[FSP_OFFSET_CMD]; + p->sum=mysum; + p->key=ntohs( *(const uint16_t *)(ptr+FSP_OFFSET_KEY) ); + p->seq=ntohs( *(const uint16_t *)(ptr+FSP_OFFSET_SEQ) ); + p->len=ntohs( *(const uint16_t *)(ptr+FSP_OFFSET_LEN) ); + p->pos=ntohl( *(const uint32_t *)(ptr+FSP_OFFSET_POS) ); + if(p->len > recv_len) + { + /* bad length field, should not never happen */ + errno = EMSGSIZE; + return -1; + } + p->xlen=recv_len - p->len - FSP_HSIZE; + /* now copy data */ + memcpy(p->buf,ptr+FSP_HSIZE,recv_len - FSP_HSIZE); + return 0; +} + +/* ****************** packet sending functions ************** */ + +/* make one send + receive transaction with server */ +/* outgoing packet is in p, incomming in rpkt */ +int fsp_transaction(FSP_SESSION *s,FSP_PKT *p,FSP_PKT *rpkt) +{ + char buf[FSP_MAXPACKET]; + size_t l; + ssize_t r; + fd_set mask; + struct timeval start[8],stop; + int i; + unsigned int retry,dupes; + int w_delay; /* how long to wait on next packet */ + int f_delay; /* how long to wait after first send */ + int l_delay; /* last delay */ + unsigned int t_delay; /* time from first send */ + + + if(p == rpkt) + { + errno = EINVAL; + return -2; + } + FD_ZERO(&mask); + /* get the next key */ + p->key = client_get_key((FSP_LOCK *)s->lock); + + dupes = retry = 0; + s->seq = (s-> seq + 0x08) & 0xfff8; + t_delay = 0; + /* compute initial delay here */ + /* we are using hardcoded value for now */ + f_delay = 1340; + for(;;retry++) + { + if(t_delay >= s->timeout) + { + client_set_key((FSP_LOCK *)s->lock,p->key); + errno = ETIMEDOUT; + return -1; + } + /* make a packet */ + p->seq = (s->seq) | (retry & 0x7); + l=fsp_pkt_write(p,buf); + + /* We should compute next delay wait time here */ + gettimeofday(&start[retry & 0x7],NULL); + if(retry == 0 ) + w_delay=f_delay; + else + { + w_delay=l_delay*3/2; + } + + l_delay=w_delay; + + /* send packet */ + if( send(s->fd,buf,l,0) < 0 ) + { +#ifdef MAINTAINER_MODE + printf("Send failed.\n"); +#endif + if(errno == EBADF || errno == ENOTSOCK) + { + client_set_key((FSP_LOCK *)s->lock,p->key); + errno = EBADF; + return -1; + } + /* io terror */ + sleep(1); + /* avoid wasting retry slot */ + retry--; + t_delay += 1000; + continue; + } + + /* keep delay value within sane limits */ + if (w_delay > (int) s->maxdelay) + w_delay=s->maxdelay; + else + if(w_delay < 1000 ) + w_delay = 1000; + + t_delay += w_delay; + /* receive loop */ + while(1) + { + if(w_delay <= 0 ) break; + /* convert w_delay to timeval */ + stop.tv_sec=w_delay/1000; + stop.tv_usec=(w_delay % 1000)*1000; + FD_SET(s->fd,&mask); + i=select(s->fd+1,&mask,NULL,NULL,&stop); + if(i==0) + break; /* timed out */ + if(i<0) + { + if(errno==EINTR) + { + /* lower w_delay */ + gettimeofday(&stop,NULL); + w_delay-=1000*(stop.tv_sec - start[retry & 0x7].tv_sec); + w_delay-= (stop.tv_usec - start[retry & 0x7].tv_usec)/1000; + continue; + } + /* hard select error */ + client_set_key((FSP_LOCK *)s->lock,p->key); + return -1; + } + r=recv(s->fd,buf,FSP_MAXPACKET,0); + if(r < 0 ) + { + /* serious recv error */ + client_set_key((FSP_LOCK *)s->lock,p->key); + return -1; + } + + gettimeofday(&stop,NULL); + w_delay-=1000*(stop.tv_sec - start[retry & 0x7].tv_sec); + w_delay-= (stop.tv_usec - start[retry & 0x7].tv_usec)/1000; + + /* process received packet */ + if ( fsp_pkt_read(rpkt,buf,r) < 0) + { + /* unpack failed */ + continue; + } + + /* check sequence number */ + if( (rpkt->seq & 0xfff8) != s->seq ) + { +#ifdef MAINTAINER_MODE + printf("dupe\n"); +#endif + /* duplicate */ + dupes++; + continue; + } + + /* now we have a correct packet */ + + /* compute rtt delay */ + w_delay=1000*(stop.tv_sec - start[retry & 0x7].tv_sec); + w_delay+=(stop.tv_usec - start[retry & 0x7].tv_usec)/1000; + /* update last stats */ + s->last_rtt=w_delay; + s->last_delay=f_delay; + s->last_dupes=dupes; + s->last_resends=retry; + /* update cumul. stats */ + s->dupes+=dupes; + s->resends+=retry; + s->trips++; + s->rtts+=w_delay; + + /* grab a next key */ + client_set_key((FSP_LOCK *)s->lock,rpkt->key); + errno = 0; + return 0; + } + } +} + +/* ******************* Session management functions ************ */ + +/* initializes a session */ +FSP_SESSION * fsp_open_session(const char *host,unsigned short port,const char *password) +{ + FSP_SESSION *s; + int fd; + struct addrinfo hints,*res; + char port_s[6]; + struct sockaddr_in *addrin; + FSP_LOCK *lock; + + memset (&hints, 0, sizeof (hints)); + /* fspd do not supports inet6 */ + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_DGRAM; + + if (port == 0) + strcpy(port_s,"fsp"); + else + sprintf(port_s,"%hu",port); + + if ( getaddrinfo(host,port_s,&hints,&res) ) + { + return NULL; /* host not found */ + } + + /* create socket */ + fd=socket(res->ai_family,res->ai_socktype,res->ai_protocol); + if ( fd < 0) + return NULL; + + /* connect socket */ + if( connect(fd, res->ai_addr, res->ai_addrlen)) + { + close(fd); + return NULL; + } + + /* allocate memory */ + s=calloc(1,sizeof(FSP_SESSION)); + if ( !s ) + { + close(fd); + errno = ENOMEM; + return NULL; + } + + lock=malloc(sizeof(FSP_LOCK)); + + if ( !lock ) + { + close(fd); + free(s); + errno = ENOMEM; + return NULL; + } + + s->lock=lock; + + /* init locking subsystem */ + addrin = (struct sockaddr_in *)res->ai_addr; + if ( client_init_key( (FSP_LOCK *)s->lock,addrin->sin_addr.s_addr,ntohs(addrin->sin_port))) + { + free(s); + close(fd); + free(lock); + return NULL; + } + + s->fd=fd; + s->timeout=300000; /* 5 minutes */ + s->maxdelay=60000; /* 1 minute */ + s->seq=random(); + if ( password ) + s->password = strdup(password); + return s; +} + +/* closes a session */ +void fsp_close_session(FSP_SESSION *s) +{ + FSP_PKT bye,in; + + if( s == NULL) + return; + if ( s->fd == -1) + return; + /* Send bye packet */ + bye.cmd=FSP_CC_BYE; + bye.len=bye.xlen=0; + bye.pos=0; + s->timeout=7000; + fsp_transaction(s,&bye,&in); + + close(s->fd); + if (s->password) free(s->password); + client_destroy_key((FSP_LOCK *)s->lock); + free(s->lock); + memset(s,0,sizeof(FSP_SESSION)); + s->fd=-1; + free(s); +} + +/* *************** Directory listing functions *************** */ + +/* get a directory listing from a server */ +FSP_DIR * fsp_opendir(FSP_SESSION *s,const char *dirname) +{ + FSP_PKT in,out; + int pos; + unsigned short blocksize; + FSP_DIR *dir; + unsigned char *tmp; + + if (s == NULL) return NULL; + if (dirname == NULL) return NULL; + + if(buildfilename(s,&out,dirname)) + { + return NULL; + } + pos=0; + blocksize=0; + dir=NULL; + out.cmd = FSP_CC_GET_DIR; + out.xlen=0; + + /* load directory listing from the server */ + while(1) + { + out.pos=pos; + if ( fsp_transaction(s,&out,&in) ) + { + pos = -1; + break; + } + if ( in.cmd != FSP_CC_GET_DIR ) + { + /* bad reply from the server */ + pos = -1; + break; + } + /* End of directory? */ + if ( in.len == 0) + break; + /* set blocksize */ + if (blocksize == 0 ) + blocksize = in.len; + /* alloc directory */ + if (dir == NULL) + { + dir = calloc(1,sizeof(FSP_DIR)); + if (dir == NULL) + { + pos = -1; + break; + } + } + /* append data */ + tmp=realloc(dir->data,pos+in.len); + if(tmp == NULL) + { + pos = -1; + break; + } + dir->data=tmp; + memcpy(dir->data + pos, in.buf,in.len); + pos += in.len; + if (in.len < blocksize) + /* last block is smaller */ + break; + } + if (pos == -1) + { + /* failure */ + if (dir) + { + if(dir->data) + free(dir->data); + free(dir); + } + return NULL; + } + + dir->inuse=1; + dir->blocksize=blocksize; + dir->dirname=strdup(dirname); + dir->datasize=pos; + + return dir; +} + +int fsp_readdir_r(FSP_DIR *dir,struct dirent *entry, struct dirent **result) +{ + FSP_RDENTRY fentry,*fresult; + int rc; + + if (dir == NULL || entry == NULL || *result == NULL) + return -EINVAL; + if (dir->dirpos<0 || dir->dirpos % 4) + return -ESPIPE; + + rc=fsp_readdir_native(dir,&fentry,&fresult); + + if (rc != 0) + return rc; + + /* convert FSP dirent to OS dirent */ + + if (fentry.type == FSP_RDTYPE_DIR ) + entry->d_type=DT_DIR; + else + entry->d_type=DT_REG; + entry->d_fileno = 10; + entry->d_reclen = fentry.reclen; + strncpy(entry->d_name,fentry.name,MAXNAMLEN); + + if (fentry.namlen > MAXNAMLEN) + { + entry->d_name[MAXNAMLEN + 1 ] = '\0'; +#ifdef HAVE_NAMLEN + entry->d_namlen = MAXNAMLEN; + } else + { + entry->d_namlen = fentry.namlen; +#endif + } + + if (fresult == &fentry ) + { + *result = entry; + } + else + *result = NULL; + + return 0; +} + +/* native FSP directory reader */ +int fsp_readdir_native(FSP_DIR *dir,FSP_RDENTRY *entry, FSP_RDENTRY **result) +{ + unsigned char ftype; + int namelen; + + if (dir == NULL || entry == NULL || *result == NULL) + return -EINVAL; + if (dir->dirpos<0 || dir->dirpos % 4) + return -ESPIPE; + + while(1) + { + if ( dir->dirpos >= (int)dir->datasize ) + { + /* end of the directory */ + *result = NULL; + return 0; + } + if (dir->blocksize - (dir->dirpos % dir->blocksize) < 9) + ftype= FSP_RDTYPE_SKIP; + else + /* get the file type */ + ftype=dir->data[dir->dirpos+8]; + + if (ftype == FSP_RDTYPE_END ) + { + dir->dirpos=dir->datasize; + continue; + } + if (ftype == FSP_RDTYPE_SKIP ) + { + /* skip to next directory block */ + dir->dirpos = ( dir->dirpos / dir->blocksize + 1 ) * dir->blocksize; +#ifdef MAINTAINER_MODE + printf("new block dirpos: %d\n",dir->dirpos); +#endif + continue; + } + /* extract binary data */ + entry->lastmod=ntohl( *(const uint32_t *)( dir->data+ dir->dirpos )); + entry->size=ntohl( *(const uint32_t *)(dir->data+ dir->dirpos +4 )); + entry->type=ftype; + + /* skip file date and file size */ + dir->dirpos += 9; + /* read file name */ + entry->name[255 + 1] = '\0'; + strncpy(entry->name,(char *)( dir->data + dir->dirpos ),MAXNAMLEN); + namelen = strlen( (char *) dir->data+dir->dirpos); + /* skip over file name */ + dir->dirpos += namelen +1; + + /* set entry namelen field */ + if (namelen > 255) + entry->namlen = 255; + else + entry->namlen = namelen; + /* set record length */ + entry->reclen = 10+namelen; + + /* pad to 4 byte boundary */ + while( dir->dirpos & 0x3 ) + { + dir->dirpos++; + entry->reclen++; + } + + /* and return it */ + *result=entry; + return 0; + } +} + +struct dirent * fsp_readdir(FSP_DIR *dirp) +{ + static struct dirent entry; + struct dirent *result; + + + if (dirp == NULL) return NULL; + if ( fsp_readdir_r(dirp,&entry,&result) ) + return NULL; + else + return result; +} + +long fsp_telldir(FSP_DIR *dirp) +{ + return dirp->dirpos; +} + +void fsp_seekdir(FSP_DIR *dirp, long loc) +{ + dirp->dirpos=loc; +} + +void fsp_rewinddir(FSP_DIR *dirp) +{ + dirp->dirpos=0; +} + +int fsp_closedir(FSP_DIR *dirp) +{ + if (dirp == NULL) + return -1; + if(dirp->dirname) free(dirp->dirname); + free(dirp->data); + free(dirp); + return 0; +} + +/* ***************** File input/output functions ********* */ +FSP_FILE * fsp_fopen(FSP_SESSION *session, const char *path,const char *modeflags) +{ + FSP_FILE *f; + + if(session == NULL || path == NULL || modeflags == NULL) + { + errno = EINVAL; + return NULL; + } + + f=calloc(1,sizeof(FSP_FILE)); + if (f == NULL) + { + return NULL; + } + + /* check and parse flags */ + switch (*modeflags++) + { + case 'r': + break; + case 'w': + f->writing=1; + break; + case 'a': + /* not supported */ + free(f); + errno = ENOTSUP; + return NULL; + default: + free(f); + errno = EINVAL; + return NULL; + } + + if (*modeflags == '+' || ( *modeflags=='b' && modeflags[1]=='+')) + { + free(f); + errno = ENOTSUP; + return NULL; + } + + /* build request packet */ + if(f->writing) + { + f->out.cmd=FSP_CC_UP_LOAD; + } + else + { + if(buildfilename(session,&f->out,path)) + { + free(f); + return NULL; + } + f->bufpos=FSP_SPACE; + f->out.cmd=FSP_CC_GET_FILE; + } + f->out.xlen=0; + + /* setup control variables */ + f->s=session; + f->name=strdup(path); + if(f->name == NULL) + { + free(f); + errno = ENOMEM; + return NULL; + } + + return f; +} + +size_t fsp_fread(void *dest,size_t size,size_t count,FSP_FILE *file) +{ + size_t total,done,havebytes; + char *ptr; + + total=count*size; + done=0; + ptr=dest; + + if(file->eof) return 0; + + while(1) + { + /* need more data? */ + if(file->bufpos>=FSP_SPACE) + { + /* fill the buffer */ + file->out.pos=file->pos; + if(fsp_transaction(file->s,&file->out,&file->in)) + { + file->err=1; + return done/size; + } + if(file->in.cmd != FSP_CC_GET_FILE) + { + errno = EIO; + file->err=1; + return done/size; + } + file->bufpos=FSP_SPACE-file->in.len; + if(file->bufpos > 0) + { + memmove(file->in.buf+file->bufpos,file->in.buf,file->in.len); + } + file->pos+=file->in.len; + } + havebytes=FSP_SPACE - file->bufpos; + if (havebytes == 0 ) + { + /* end of file! */ + file->eof=1; + errno = 0; + return done/size; + } + /* copy ready data to output buffer */ + if(havebytes <= total ) + { + /* copy all we have */ + memcpy(ptr,file->in.buf+file->bufpos,havebytes); + ptr+=havebytes; + file->bufpos=FSP_SPACE; + done+=havebytes; + total-=havebytes; + } else + { + /* copy bytes left */ + memcpy(ptr,file->in.buf+file->bufpos,total); + file->bufpos+=total; + errno = 0; + return count; + } + } +} + +size_t fsp_fwrite(const void * source, size_t size, size_t count, FSP_FILE * file) +{ + size_t total,done,freebytes; + const char *ptr; + + if(file->eof || file->err) + return 0; + + file->out.len=FSP_SPACE; + total=count*size; + done=0; + ptr=source; + + while(1) + { + /* need to write some data? */ + if(file->bufpos>=FSP_SPACE) + { + /* fill the buffer */ + file->out.pos=file->pos; + if(fsp_transaction(file->s,&file->out,&file->in)) + { + file->err=1; + return done/size; + } + if(file->in.cmd != FSP_CC_UP_LOAD) + { + errno = EIO; + file->err=1; + return done/size; + } + file->bufpos=0; + file->pos+=file->out.len; + done+=file->out.len; + } + freebytes=FSP_SPACE - file->bufpos; + /* copy input data to output buffer */ + if(freebytes <= total ) + { + /* copy all we have */ + memcpy(file->out.buf+file->bufpos,ptr,freebytes); + ptr+=freebytes; + file->bufpos=FSP_SPACE; + total-=freebytes; + } else + { + /* copy bytes left */ + memcpy(file->out.buf+file->bufpos,ptr,total); + file->bufpos+=total; + errno = 0; + return count; + } + } +} + +int fsp_fpurge(FSP_FILE *file) +{ + if(file->writing) + { + file->bufpos=0; + } + else + { + file->bufpos=FSP_SPACE; + } + errno = 0; + return 0; +} + +int fsp_fflush(FSP_FILE *file) +{ + if(file == NULL) + { + errno = ENOTSUP; + return -1; + } + if(!file->writing) + { + errno = EBADF; + return -1; + } + if(file->eof || file->bufpos==0) + { + errno = 0; + return 0; + } + + file->out.pos=file->pos; + file->out.len=file->bufpos; + if(fsp_transaction(file->s,&file->out,&file->in)) + { + file->err=1; + return -1; + } + if(file->in.cmd != FSP_CC_UP_LOAD) + { + errno = EIO; + file->err=1; + return -1; + } + file->bufpos=0; + file->pos+=file->out.len; + + errno = 0; + return 0; +} + + + +int fsp_fclose(FSP_FILE *file) +{ + int rc; + + rc=0; + errno = 0; + if(file->writing) + { + if(fsp_fflush(file)) + { + rc=-1; + } + else if(fsp_install(file->s,file->name,0)) + { + rc=-1; + } + } + free(file->name); + free(file); + return rc; +} + +int fsp_fseek(FSP_FILE *stream, long offset, int whence) +{ + long newoffset; + + switch(whence) + { + case SEEK_SET: + newoffset = offset; + break; + case SEEK_CUR: + newoffset = stream->pos + offset; + break; + case SEEK_END: + errno = ENOTSUP; + return -1; + default: + errno = EINVAL; + return -1; + } + if(stream->writing) + { + if(fsp_fflush(stream)) + { + return -1; + } + } + stream->pos=newoffset; + stream->eof=0; + fsp_fpurge(stream); + return 0; +} + +long fsp_ftell(FSP_FILE *f) +{ + return f->pos + f->bufpos; +} + +void fsp_rewind(FSP_FILE *f) +{ + if(f->writing) + fsp_fflush(f); + f->pos=0; + f->err=0; + f->eof=0; + fsp_fpurge(f); +} + +/* **************** Utility functions ****************** */ + +/* return 0 if user has enough privs for uploading the file */ +int fsp_canupload(FSP_SESSION *s,const char *fname) +{ + char *dir; + unsigned char dirpro; + int rc; + struct stat sb; + + dir=directoryfromfilename(fname); + if(dir == NULL) + { + errno = ENOMEM; + return -1; + } + + rc=fsp_getpro(s,dir,&dirpro); + free(dir); + + if(rc) + { + return -1; + } + + if(dirpro & FSP_DIR_OWNER) + return 0; + + if( ! (dirpro & FSP_DIR_ADD)) + return -1; + + if (dirpro & FSP_DIR_DEL) + return 0; + + /* we need to check file existence, because we can not overwrite files */ + + rc = fsp_stat(s,fname,&sb); + + if (rc == 0) + return -1; + else + return 0; +} + +/* install file opened for writing */ +int fsp_install(FSP_SESSION *s,const char *fname,time_t timestamp) +{ + int rc; + FSP_PKT in,out; + + /* and install a new file */ + out.cmd=FSP_CC_INSTALL; + out.xlen=0; + out.pos=0; + rc=0; + if( buildfilename(s,&out,fname) ) + rc=-1; + else + { + if (timestamp != 0) + { + /* add timestamp extra data */ + *(uint32_t *)(out.buf+out.len)=htonl(timestamp); + out.xlen=4; + out.pos=4; + } + if(fsp_transaction(s,&out,&in)) + { + rc=-1; + } else + { + if(in.cmd != FSP_CC_INSTALL) + { + rc=-1; + errno = EPERM; + } + } + } + + return rc; +} +/* Get protection byte from the directory */ +int fsp_getpro(FSP_SESSION *s,const char *directory,unsigned char *result) +{ + FSP_PKT in,out; + + if(buildfilename(s,&out,directory)) + return -1; + out.cmd=FSP_CC_GET_PRO; + out.xlen=0; + out.pos=0; + + if(fsp_transaction(s,&out,&in)) + return -1; + + if(in.cmd != FSP_CC_GET_PRO || in.pos != FSP_PRO_BYTES) + { + errno = ENOMSG; + return -1; + } + + if(result) + *result=in.buf[in.len]; + errno = 0; + return 0; +} + +int fsp_stat(FSP_SESSION *s,const char *path,struct stat *sb) +{ + FSP_PKT in,out; + unsigned char ftype; + + if(buildfilename(s,&out,path)) + return -1; + out.cmd=FSP_CC_STAT; + out.xlen=0; + out.pos=0; + + if(fsp_transaction(s,&out,&in)) + return -1; + + if(in.cmd != FSP_CC_STAT) + { + errno = ENOTSUP; + return -1; + } + /* parse results */ + ftype=in.buf[8]; + if(ftype == 0) + { + errno = ENOENT; + return -1; + } + sb->st_uid=sb->st_gid=0; + sb->st_mtime=sb->st_ctime=sb->st_atime=ntohl( *(const uint32_t *)( in.buf )); + sb->st_size=ntohl( *(const uint32_t *)(in.buf + 4 )); + sb->st_blocks=(sb->st_size+511)/512; + if (ftype==FSP_RDTYPE_DIR) + { + sb->st_mode=S_IFDIR | 0755; + sb->st_nlink=2; + } + else + { + sb->st_mode=S_IFREG | 0644; + sb->st_nlink=1; + } + + errno = 0; + return 0; +} + +int fsp_mkdir(FSP_SESSION *s,const char *directory) +{ + return simplecommand(s,directory,FSP_CC_MAKE_DIR); +} + +int fsp_rmdir(FSP_SESSION *s,const char *directory) +{ + return simplecommand(s,directory,FSP_CC_DEL_DIR); +} + +int fsp_unlink(FSP_SESSION *s,const char *directory) +{ + return simplecommand(s,directory,FSP_CC_DEL_FILE); +} + +int fsp_rename(FSP_SESSION *s,const char *from, const char *to) +{ + FSP_PKT in,out; + int l; + + if(buildfilename(s,&out,from)) + return -1; + /* append target name */ + l=strlen(to)+1; + if( l + out.len > FSP_SPACE ) + { + errno = ENAMETOOLONG; + return -1; + } + memcpy(out.buf+out.len,to,l); + out.xlen = l; + + if(s->password) + { + l=strlen(s->password)+1; + if(out.len + out.xlen + l > FSP_SPACE) + { + errno = ENAMETOOLONG; + return -1; + } + out.buf[out.len+out.xlen-1] = '\n'; + memcpy(out.buf+out.len+out.xlen,s->password,l); + out.xlen += l; + } + + out.cmd=FSP_CC_RENAME; + out.pos=out.xlen; + + if(fsp_transaction(s,&out,&in)) + return -1; + + if(in.cmd != FSP_CC_RENAME) + { + errno = EPERM; + return -1; + } + + errno = 0; + return 0; +} + +int fsp_access(FSP_SESSION *s,const char *path, int mode) +{ + struct stat sb; + int rc; + unsigned char dirpro; + char *dir; + + rc=fsp_stat(s,path,&sb); + if(rc == -1) + { + /* not found */ + /* errno is set by fsp_stat */ + return -1; + } + + /* just test file existence */ + if(mode == F_OK) + { + errno = 0; + return 0; + } + + /* deny execute access to file */ + if (mode & X_OK) + { + if(S_ISREG(sb.st_mode)) + { + errno = EACCES; + return -1; + } + } + + /* Need to get ACL of directory */ + if(S_ISDIR(sb.st_mode)) + dir=NULL; + else + dir=directoryfromfilename(path); + + rc=fsp_getpro(s,dir==NULL?path:dir,&dirpro); + /* get pro failure */ + if(rc) + { + if(dir) free(dir); + errno = EACCES; + return -1; + } + /* owner shortcut */ + if(dirpro & FSP_DIR_OWNER) + { + if(dir) free(dir); + errno = 0; + return 0; + } + /* check read access */ + if(mode & R_OK) + { + if(dir) + { + if(! (dirpro & FSP_DIR_GET)) + { + free(dir); + errno = EACCES; + return -1; + } + } else + { + if(! (dirpro & FSP_DIR_LIST)) + { + errno = EACCES; + return -1; + } + } + } + /* check write access */ + if(mode & W_OK) + { + if(dir) + { + if( !(dirpro & FSP_DIR_DEL) || !(dirpro & FSP_DIR_ADD)) + { + free(dir); + errno = EACCES; + return -1; + } + } else + { + /* when checking directory for write access we are cheating + by allowing ADD or DEL right */ + if( !(dirpro & FSP_DIR_DEL) && !(dirpro & FSP_DIR_ADD)) + { + errno = EACCES; + return -1; + } + } + } + + if(dir) free(dir); + errno = 0; + return 0; +} diff -r 2e718fba351e -r be9663e0be00 lib/fsplib/fsplib.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fsplib/fsplib.h Sun Jan 16 16:12:13 2005 +0000 @@ -0,0 +1,184 @@ +#ifndef _FSPLIB_H +#define _FSPLIB_H 1 +#include +/* The FSP v2 protocol support library - public interface */ + +/* +This file is part of fsplib - FSP protocol stack implemented in C +language. See http://fsp.sourceforge.net for more information. + +Copyright (c) 2003-2004 by Radim HSN Kolar (hsn@netmag.cz) + +You may copy or modify this file in any manner you wish, provided +that this notice is always included, and that you hold the author +harmless for any loss or damage resulting from the installation or +use of this software. + + This is a free software. Be creative. + Let me know of any bugs and suggestions. +*/ + +/* definition of FSP protocol v2 commands */ + +#define FSP_CC_VERSION 0x10 /* return server's version string. */ +#define FSP_CC_INFO 0x11 /* return server's extended info block */ +#define FSP_CC_ERR 0x40 /* error response from server. */ +#define FSP_CC_GET_DIR 0x41 /* get a directory listing. */ +#define FSP_CC_GET_FILE 0x42 /* get a file. */ +#define FSP_CC_UP_LOAD 0x43 /* open a file for writing. */ +#define FSP_CC_INSTALL 0x44 /* close a file opened for writing. */ +#define FSP_CC_DEL_FILE 0x45 /* delete a file. */ +#define FSP_CC_DEL_DIR 0x46 /* delete a directory. */ +#define FSP_CC_GET_PRO 0x47 /* get directory protection. */ +#define FSP_CC_SET_PRO 0x48 /* set directory protection. */ +#define FSP_CC_MAKE_DIR 0x49 /* create a directory. */ +#define FSP_CC_BYE 0x4A /* finish a session. */ +#define FSP_CC_GRAB_FILE 0x4B /* atomic get+delete a file. */ +#define FSP_CC_GRAB_DONE 0x4C /* atomic get+delete a file done. */ +#define FSP_CC_STAT 0x4D /* get information about file. */ +#define FSP_CC_RENAME 0x4E /* rename file or directory. */ +#define FSP_CC_CH_PASSWD 0x4F /* change password */ +#define FSP_CC_LIMIT 0x80 /* # > 0x7f for future cntrl blk ext. */ +#define FSP_CC_TEST 0x81 /* reserved for testing */ + +/* FSP v2 packet size */ +#define FSP_HSIZE 12 /* 12 bytes for v2 header */ +#define FSP_SPACE 1024 /* maximum payload. */ +#define FSP_MAXPACKET FSP_HSIZE+FSP_SPACE /* maximum packet size. */ + +/* byte offsets of fields in the FSP v2 header */ +#define FSP_OFFSET_CMD 0 +#define FSP_OFFSET_SUM 1 +#define FSP_OFFSET_KEY 2 +#define FSP_OFFSET_SEQ 4 +#define FSP_OFFSET_LEN 6 +#define FSP_OFFSET_POS 8 + +/* types of directory entry */ +#define FSP_RDTYPE_END 0x00 +#define FSP_RDTYPE_FILE 0x01 +#define FSP_RDTYPE_DIR 0x02 +#define FSP_RDTYPE_LINK 0x03 +#define FSP_RDTYPE_SKIP 0x2A + +/* definition of directory bitfield for directory information */ +/* directory information is just going to be a bitfield encoding + * of which protection bits are set/unset + */ + +#define FSP_PRO_BYTES 1 /* currently only 8 bits or less of info */ +#define FSP_DIR_OWNER 0x01 /* does caller own directory */ +#define FSP_DIR_DEL 0x02 /* can files be deleted from this dir */ +#define FSP_DIR_ADD 0x04 /* can files be added to this dir */ +#define FSP_DIR_MKDIR 0x08 /* can new subdirectories be created */ +#define FSP_DIR_GET 0x10 /* are files readable by non-owners? */ +#define FSP_DIR_README 0x20 /* does this dir contain an readme file? */ +#define FSP_DIR_LIST 0x40 /* public can list directory */ +#define FSP_DIR_RENAME 0x80 /* can files be renamed in this dir */ + +/* decoded FSP packet */ +typedef struct FSP_PKT { + unsigned char cmd; /* message code. */ + unsigned char sum; /* message checksum. */ + unsigned short key; /* message key. */ + unsigned short seq; /* message sequence number. */ + unsigned short len; /* number of bytes in buf 1. */ + unsigned int pos; /* location in the file. */ unsigned short xlen; /* number of bytes in buf 2 */ + + unsigned char buf[FSP_SPACE]; /* packet payload */ + } FSP_PKT; + +/* FSP host:port */ +typedef struct FSP_SESSION { + void * lock; /* key locking */ + unsigned int timeout; /* send timeout 1/1000s*/ + unsigned int maxdelay; /* maximum recv. delay */ + unsigned short seq; /* sequence number */ + unsigned int dupes; /* total pkt. dupes */ + unsigned int resends; /* total pkt. sends */ + unsigned int trips; /* total pkt trips */ + unsigned long rtts; /* cumul. rtt */ + unsigned int last_rtt; /* last rtt */ + unsigned int last_delay; /* last delay time */ + unsigned int last_dupes; /* last dupes */ + unsigned int last_resends;/* last resends */ + int fd; /* i/o descriptor */ + char *password; /* host acccess password */ + } FSP_SESSION; + +/* fsp directory handle */ +typedef struct FSP_DIR { + char *dirname; /* directory name */ + short inuse; /* in use counter */ + int dirpos; /* current directory pos. */ + unsigned short blocksize; /* size of directory block */ + unsigned char *data; /* raw directory data */ + unsigned int datasize; /* size of raw dir. data */ +} FSP_DIR; + +/* fsp directory entry */ +typedef struct FSP_RDENTRY { + char name[255 + 1]; /* entry name */ + unsigned short namlen; /* length */ + unsigned char type; /* field type */ + unsigned short reclen; /* directory record length */ + unsigned int size; + unsigned int lastmod; +} FSP_RDENTRY; + +/* fsp file handle */ +typedef struct FSP_FILE { + FSP_PKT in,out; /* io packets */ + FSP_SESSION *s; /* master session */ + char *name; /* filename for upload */ + unsigned char writing; /* opened for writing */ + unsigned char eof; /* EOF reached? */ + unsigned char err; /* i/o error? */ + int bufpos; /* position in buffer */ + unsigned int pos; /* position of next packet */ +} FSP_FILE; + +/* function prototypes */ + +/* session management */ +FSP_SESSION * fsp_open_session(const char *host,unsigned short port, const char *password); +void fsp_close_session(FSP_SESSION *s); + +/* packet encoding/decoding */ +size_t fsp_pkt_write(const FSP_PKT *p,void *space); +int fsp_pkt_read(FSP_PKT *p,const void *space,size_t recv_len); + +/* send/receive round-trip */ +int fsp_transaction(FSP_SESSION *s,FSP_PKT *p,FSP_PKT *rpkt); + +/* directory listing commands */ +FSP_DIR * fsp_opendir(FSP_SESSION *s,const char *dirname); +int fsp_readdir_r(FSP_DIR *dir,struct dirent *entry, struct dirent **result); +long fsp_telldir(FSP_DIR *dirp); +void fsp_seekdir(FSP_DIR *dirp, long loc); +void fsp_rewinddir(FSP_DIR *dirp); +struct dirent * fsp_readdir(FSP_DIR *dirp); +int fsp_readdir_native(FSP_DIR *dir,FSP_RDENTRY *entry, FSP_RDENTRY **result); +int fsp_closedir(FSP_DIR *dirp); +/* high level file i/o */ +FSP_FILE * fsp_fopen(FSP_SESSION *session, const char *path,const char *modeflags); +size_t fsp_fread(void *ptr,size_t size,size_t nmemb,FSP_FILE *file); +size_t fsp_fwrite(const void * source, size_t size, size_t count, FSP_FILE * file); +int fsp_fclose(FSP_FILE *file); +int fsp_fpurge(FSP_FILE *file); +int fsp_fflush(FSP_FILE *file); +int fsp_fseek(FSP_FILE *stream, long offset, int whence); +long fsp_ftell(FSP_FILE *f); +void fsp_rewind(FSP_FILE *f); +/* misc. functions */ +int fsp_stat(FSP_SESSION *s,const char *path,struct stat *sb); +int fsp_mkdir(FSP_SESSION *s,const char *directory); +int fsp_rmdir(FSP_SESSION *s,const char *directory); +int fsp_unlink(FSP_SESSION *s,const char *directory); +int fsp_rename(FSP_SESSION *s,const char *from, const char *to); +int fsp_access(FSP_SESSION *s,const char *path, int mode); +/* fsp protocol specific functions */ +int fsp_getpro(FSP_SESSION *s,const char *directory,unsigned char *result); +int fsp_install(FSP_SESSION *s,const char *fname,time_t timestamp); +int fsp_canupload(FSP_SESSION *s,const char *fname); +#endif diff -r 2e718fba351e -r be9663e0be00 lib/fsplib/lock.c --- /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 +#include +#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 +#include +#include +#include +#include +#include +#include + +#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 +#include +#include + +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 diff -r 2e718fba351e -r be9663e0be00 lib/fsplib/lock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fsplib/lock.h Sun Jan 16 16:12:13 2005 +0000 @@ -0,0 +1,45 @@ +#ifndef _FSPLIB_H_LOCK +#define _FSPLIB_H_LOCK 1 + +#ifndef FSP_NOLOCKING +/* define locking prefix if needed */ +# ifndef FSP_KEY_PREFIX +# define FSP_KEY_PREFIX "/tmp/.FSPL" +# endif +#endif + +#ifdef FSP_USE_SHAREMEM_AND_SEMOP + +typedef struct FSP_LOCK { + unsigned int *share_key; + int lock_shm; + int lock_sem; + char key_string[sizeof(FSP_KEY_PREFIX)+32]; +} FSP_LOCK; + +#elif defined(FSP_NOLOCKING) + +typedef struct FSP_LOCK { + unsigned short share_key; +} FSP_LOCK; + +#elif defined(FSP_USE_LOCKF) + +typedef struct FSP_LOCK { + int lock_fd; + char key_string[sizeof(FSP_KEY_PREFIX)+32]; +} FSP_LOCK; + +#else +#error "No locking type specified" +#endif + +/* prototypes */ + +unsigned short client_get_key (FSP_LOCK *lock); +void client_set_key (FSP_LOCK *lock,unsigned short key); +int client_init_key (FSP_LOCK *lock, + unsigned long server_addr, + unsigned short server_port); +void client_destroy_key(FSP_LOCK *lock); +#endif