📄 fsplib.c
字号:
/* 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -