Skip to content
Snippets Groups Projects
smbwrap.c 7.22 KiB
/* smbwrap.c */

/* Synchronet SMBLIB system-call wrappers */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

/* OS-specific */
#if defined(__unix__)

#include <glob.h>       /* glob() wildcard matching */
#include <string.h>     /* strlen() */
#include <unistd.h>     /* getpid() */
#include <fcntl.h>      /* fcntl() file/record locking */

#endif

/* ANSI */
#include <sys/types.h>	/* _dev_t */
#include <sys/stat.h>	/* struct stat */

/* SMB-specific */
#include "smblib.h"		/* SMBCALL */
#include "smbwrap.h"	/* Verify prototypes */

/****************************************************************************/
/* Convert ASCIIZ string to upper case										*/
/****************************************************************************/
#ifdef __unix__
char* SMBCALL strupr(char* str)
{
	char*	p=str;

	while(*p) {
		*p=toupper(*p);
		p++;
	}
	return(str);
}
/****************************************************************************/
/* Convert ASCIIZ string to lower case										*/
/****************************************************************************/
char* SMBCALL strlwr(char* str)
{
	char*	p=str;

	while(*p) {
		*p=tolower(*p);
		p++;
	}
	return(str);
}
#endif

/****************************************************************************/
/* Returns the length of the file in 'filename'                             */
/****************************************************************************/
long SMBCALL flength(char *filename)
{
#ifdef __BORLANDC__	/* stat() doesn't work right */

	long	handle;
	struct _finddata_t f;

	if(access(filename,0)==-1)
		return(-1L);

	if((handle=_findfirst(filename,&f))==-1)
		return(-1);

 	_findclose(handle);

	return(f.size);

#else 

	struct stat st;

	if(access(filename,0)==-1)
		return(-1L);

	if(stat(filename, &st)!=0)
		return(-1L);

	return(st.st_size);

#endif
}

/****************************************************************************/
/* Checks the file system for the existence of one or more files.			*/
/* Returns TRUE if it exists, FALSE if it doesn't.                          */
/* 'filespec' may contain wildcards!										*/
/****************************************************************************/
BOOL SMBCALL fexist(char *filespec)
{
#ifdef _WIN32

	long	handle;
	struct _finddata_t f;

	if(access(filespec,0)==-1 && !strchr(filespec,'*') && !strchr(filespec,'?'))
		return(FALSE);

	if((handle=_findfirst(filespec,&f))==-1)
		return(FALSE);

 	_findclose(handle);

 	if(f.attrib&_A_SUBDIR)
		return(FALSE);

	return(TRUE);

#elif defined(__unix__)	/* portion by cmartin */

	glob_t g;
    int c;
    int l;

	if(access(filespec,0)==-1 && !strchr(filespec,'*') && !strchr(filespec,'?'))
		return(FALSE);

    // start the search
    glob(filespec, GLOB_MARK | GLOB_NOSORT, NULL, &g);

    if (!g.gl_pathc) {
	    // no results
    	globfree(&g);
    	return FALSE;
    }

    // make sure it's not a directory
	c = g.gl_pathc;
    while (c--) {
    	l = strlen(g.gl_pathv[c]);
    	if (l && g.gl_pathv[c][l-1] != '/') {
        	globfree(&g);
            return TRUE;
        }
    }
        
    globfree(&g);
    return FALSE;

#else

#warning "fexist() port needs to support wildcards!"

	return(FALSE);

#endif
}

#if defined(__unix__)

/****************************************************************************/
/* Returns the length of the file in 'fd'									*/
/****************************************************************************/
long SMBCALL filelength(int fd)
{
	struct stat st;

	if(fstat(fd, &st)!=0)
		return(-1L);

	return(st.st_size);
}

/* Sets a lock on a portion of a file */
int SMBCALL lock(int fd, long pos, int len)
{
	int	flags;
 	struct flock alock;

	if((flags=fcntl(fd,F_GETFL))<0)
		return -1;

	if(flags==O_RDONLY)
		alock.l_type = F_RDLCK; // set read lock to prevent writes
	else
		alock.l_type = F_WRLCK; // set write lock to prevent all access
	alock.l_whence = L_SET;	  // SEEK_SET
	alock.l_start = pos;
	alock.l_len = len;

	return fcntl(fd, F_SETLK, &alock);
}

/* Removes a lock from a file record */
int SMBCALL unlock(int fd, long pos, int len)
{
	struct flock alock;

	alock.l_type = F_UNLCK;   // remove the lock
	alock.l_whence = L_SET;
	alock.l_start = pos;
	alock.l_len = len;
	return fcntl(fd, F_SETLK, &alock);
}

/* Opens a file in specified sharing (file-locking) mode */
int SMBCALL sopen(char *fn, int access, int share)
{
	int fd;
	struct flock alock;

	if ((fd = open(fn, access, S_IREAD|S_IWRITE)) < 0)
		return -1;

	if (share == SH_DENYNO)
		// no lock needed
		return fd;

	alock.l_type = share;
	alock.l_whence = L_SET;
	alock.l_start = 0;
	alock.l_len = 0;       // lock to EOF

#if 0
	/* The l_pid field is only used with F_GETLK to return the process 
		ID of the process holding a blocking lock.  */
	alock.l_pid = getpid();
#endif

	if (fcntl(fd, F_SETLK, &alock) < 0) {
		close(fd);
		return -1;
	}

	return fd;
}

#elif defined _MSC_VER || defined __MINGW32__

#include <io.h>				/* tell */
#include <stdio.h>			/* SEEK_SET */
#include <sys/locking.h>	/* _locking */

/* Fix MinGW locking.h typo */
#if defined LK_UNLOCK && !defined LK_UNLCK
	#define LK_UNLCK LK_UNLOCK
#endif

int SMBCALL lock(int file, long offset, int size) 
{
	int	i;
	long	pos;
   
	pos=tell(file);
	if(offset!=pos)
		lseek(file, offset, SEEK_SET);
	i=_locking(file,LK_NBLCK,size);
	if(offset!=pos)
		lseek(file, pos, SEEK_SET);
	return(i);
}

int SMBCALL unlock(int file, long offset, int size)
{
	int	i;
	long	pos;
   
	pos=tell(file);
	if(offset!=pos)
		lseek(file, offset, SEEK_SET);
	i=_locking(file,LK_UNLCK,size);
	if(offset!=pos)
		lseek(file, pos, SEEK_SET);
	return(i);
}

#endif	/* !Unix && (MSVC || MinGW) */