Source

blake / blake_fs.c

Full commit
/*
Copyright (C) 2001-2006 Daybo Logic.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/*
  *---------------------------------------------------------------------*
  * OverChat Blake - A communications protocol and helper library       *
  * by David Duncan Ross Palmer <http://www.daybologic.co.uk/mailddrp>  *
  *---------------------------------------------------------------------*
  * this source deals with the Blake file system related functions.     *
  * It deals with generally non-portable things such as file locking    *
  * file truncation, walking directories and the like.                  *
  *---------------------------------------------------------------------*
*/

#define BLAKE_SOURCE

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /*HAVE_CONFIG_H*/

#include <time.h>
#include <stdio.h>

#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif /*HAVE_LIMITS_H*/

#ifdef __UNIX__
# include <sys/file.h>
# ifdef HAVE_UNISTD_H
#  include <unistd.h>
# endif /*HAVE_UNISTD_H*/
#else /* Win32 or DOS */
# if ( defined (__BORLANDC__) || defined(__MSC__) )
#  include <io.h>
#  ifdef HAVE_FCNTL_H
#   include <fcntl.h>
#  endif /*HAVE_FCNTL_H*/
#  include <share.h>
#  ifdef HAVE_SYS_STAT_H
#   include <sys/stat.h>
#  endif /*HAVE_SYS_STAT_H*/
# else
#  error
# endif /*__BORLANDC__*/
#endif /*__UNIX__*/

#ifdef BLAKE_HDRSTOP
# pragma hdrstop
#endif /*BLAKE_HDRSTOP*/

#ifdef HAVE_DLSTDINC_H
# include "dlstdinc.h"
#endif /*HAVE_DLSTDINC_H*/

#include "blake_threads.h"
#include "blake.h" /* Public lib header */
#include "blake_main.h" /* Internal functions for Blake */
#include "blake_fs.h"
/*-------------------------------------------------------------------------*/
static const char *rcsid =
  "$Id: blake_fs.c,v 0.9 2006/03/29 12:00:00 ddrp Exp $";
/*-------------------------------------------------------------------------*/
void blake_int_fs_NCI()
{
    blake_Unused(rcsid);
}
/*-------------------------------------------------------------------------*/
BLAKEAPI(enum blakeError) blake_ExclusiveFileOpen(
  const char *FileName,
  blake_bool_t NeedWrite,
  FILE **PHandle
)
{
  int fd;
  FILE* fsp = NULL;

# ifdef __UNIX__
    struct flock fl;
#endif

  if ( !blake_int_IsInited() ) return blakeNotStarted;
  if ( !FileName || !PHandle ) return blakeInvalidParam;
  if ( (*PHandle) ) return blakeInvalidParam;

# ifdef __UNIX__
    fl.l_type = ( (NeedWrite) ? (F_WRLCK) : (F_RDLCK) );
    fl.l_whence = SEEK_SET; /* Lock region is absolute */
    fl.l_start = 0; /* From the top of the file */
    fl.l_len = 0; /* Throughout it's entirety */
    fl.l_pid = getpid(); /* Identify process which owns the file (us) */

    fd = open(
      FileName,
      O_CREAT | ( (NeedWrite) ? (O_RDWR) : (O_RDONLY) ),
      0600
    );

    if ( fd != -1 ) { /* If no error */
      if ( fcntl(fd, F_SETLKW, &fl) == -1 ) {
        close(fd);
        fd = -1;
      }
    }
# else /*__WIN32__*/
#   if ( defined(__BORLANDC__) || defined(__MSC__) )
      fd = sopen(FileName, O_RDONLY, SH_DENYNO, S_IREAD); /* FIXME */
      if ( fd != -1 ) {
        if ( lock(fd, 0L, filelength(fd)) ) {
          /* Locking the file has failed */
          close(fd);
          fd = -1;
        }
      }
#   else
#     error ("No code for this compiler")
#   endif /*__BORLANDC__*/
# endif /*__UNIX__*/

  if ( fd != -1 ) { /* If no error */
    fsp = fdopen(fd, ( (NeedWrite) ? ("r+b") : ("rb") ));
    if ( !fsp )
      close(fd);
  }

  *PHandle = fsp;
  if ( fd == -1 )
    return blakeExclusiveFileFailure;
  return blakeSuccess;
}
/*-------------------------------------------------------------------------*/
BLAKEAPI(void) blake_ExclusiveFileClose(FILE* Handle)
{
  if ( Handle ) {
#ifdef __UNIX__ /* Not UNIX */
    struct flock fl;

    fl.l_type = F_UNLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start = 0;
    fl.l_len = 0;
    fl.l_pid = getpid();

    fcntl(fileno(Handle), F_SETLK, &fl);
#else /* Not UNIX */
# ifdef __BORLANDC__
    int fd = fileno(Handle);
    unlock(fd, 0L, filelength(fd));
# else
#   error "Can't handle compiler"
# endif
#endif
    close(fileno(Handle));
    fclose(Handle);
  }
}
/*-------------------------------------------------------------------------*/