/*
 * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/fle.c,v 1.18 2004/05/11 20:39:12 aleigh Exp $ 
 */

/*
 * Copyright (c) 1994, 2004 Alex Leigh, All Rights Reserved
 * 
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright
 * notice above does not evidence any actual or intended publication of such
 * source code.
 * 
 * Disclosure, copying, distribution, or transmission of this code without
 * express permission is prohibited.
 */

#include "mecha.h"


#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>

#define MAX_LINKS 32            /* Maximum number of links we are willing to
                                 * recurse */

int fleFset_close_exec(int fd)
{
    int fd_flags;

    /* Set the socket to nonblocking */
    if ((fd_flags = fcntl(fd, F_GETFD)) == -1) {
        perror("fcntl");
        return -1;
    }
    fd_flags |= FD_CLOEXEC;

    if (fcntl(fd, F_SETFD, fd_flags) == -1) {
        perror("fcntl");
        return -1;
    }
    return (0);
}

int fleFpath_combine(const char *path, int path_len, const char *relative,
                     char *output, int output_len)
{
    int second_length = 0;

    if (output_len < path_len) {
        path_len = output_len;
    }
    memcpy(output, path, path_len);

    /* make sure we even have room to do anything else */
    if (path_len == output_len) {
        /*
         * should we return what we could do or return -1 because we couldn't
         * combine them?
         * 
         * -eric@5stops.com - 1.29.2004
         * 
         */
        return (path_len);
    }
    if (output[path_len - 1] == '/') {
        output[--path_len] = 0;
    }
    second_length =
        fleFpath_simplify(relative, output + path_len,
                          output_len - path_len);

    if (output[path_len] != '/') {
        if (output_len <= (path_len + second_length + 1)) {
            second_length = output_len - path_len - 2;
        }
        memmove(output + path_len + 1, output + path_len, second_length);

        output[path_len++] = '/';

        output[path_len + second_length] = 0;
    }
    return (path_len + second_length);
}

int fleFpath_simplify(const char *path, char *outpath, int len)
{
    const char *cur_path;
    char *cur_outpath;

    assert(path != NULL);
    assert(outpath != NULL);

    cur_path = path;
    cur_outpath = outpath;

    while (*cur_path != 0 && (cur_outpath - outpath) < (len - 1)) {
        if (*cur_path == '/') {
            if (cur_path[1] == '.'
                && (cur_path[2] == 0 || cur_path[2] == '/')) {
                cur_path += 2;

                continue;
            } else if (cur_path[1] == '/') {
                cur_path++;

                continue;
            } else if (cur_path[1] == '.' && cur_path[2] == '.' &&
                       (cur_path[3] == 0 || cur_path[3] == '/')) {
                while (cur_outpath > outpath && *(--cur_outpath) != '/');

                if (cur_outpath == outpath) {
                    *cur_outpath = '/';
                }
                cur_path += 3;

                continue;
            }
        }
        *cur_outpath++ = *cur_path++;
    }

    *cur_outpath = 0;

    return ((int) (cur_outpath - outpath));
}

void fleFpath_clean(char *pathname)
{
    char *cleanpath, c;

    assert(pathname != NULL);

    cleanpath = pathname;
    while ((c = *pathname++)) {
        if (c == '/') {
            while (1) {
                if (*pathname == '/')
                    pathname++;
                else if (*pathname == '.' && *(pathname + 1) == '/')
                    pathname += 2;
                else if (*pathname == '.' && *(pathname + 1) == '.' &&
                         *(pathname + 2) == '/') {
                    pathname += 3;
                } else
                    break;
            }
            c = '/';
        }
        *cleanpath++ = c;
    }
    *cleanpath = '\0';
}

int fleFlock(const char *filename)
{
    char lockpath[1024];
    int fd;

    assert(filename != NULL);

    snprintf(lockpath, sizeof(lockpath), "%s.lock", filename);

    fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0644);

    if (fd < 0)
        return 0;

    close(fd);

    return 1;
}

int fleFunlock(const char *filename)
{
    char lockpath[1024];

    assert(filename != NULL);

    snprintf(lockpath, sizeof(lockpath), "%s.lock", filename);

    if (unlink(lockpath) < 0)
        return 0;
    return 1;
}

int fleFsync_mem_to_file(char *filename, const char *memory, size_t len)
{
    int fd;
    char *map;

    assert(filename != NULL);
    assert(memory != NULL);

    fd = open(filename, O_RDWR, 0644);
    if (fd < 0)
        return -1;

    map = mmap((void *) 0, len, (PROT_READ | PROT_WRITE), 0, fd, 0);
    assert(map != NULL);

    close(fd);

    if (map == MAP_FAILED)
        return -1;

    memFcopy(memory, map, len);

    munmap(map, len);

    return len;
}

int fleFexist(const char *filename) {
    struct stat sb;

  assert(filename!=NULL);

  if(stat(filename,&sb)==0) {
    return 1;
  }

  return 0;
}

/* How can this return -1 if it's not a ssize_t? -aleigh */
size_t fleFget_size(const char *filename)
{
    struct stat sb;

    assert(filename != NULL);

    if (stat(filename, &sb) < 0)
        return -1;

    return sb.st_size;
}

char *fleFload_file(const char *filename, size_t * len)
{
    int fd;
    size_t size;
    char *map;
    char *target;

    assert(filename != NULL);
    assert(len != NULL);

    fd = open(filename, O_RDONLY, 0644);
    if (fd < 0)
        return NULL;

    size = fleFget_size(filename);

    map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);

    close(fd);

    assert(map != NULL);

    if (map == MAP_FAILED) {
        return NULL;
    }
    target = (char *) malloc(size);
    memFcopy(map, target, size);

    *len = size;

    munmap(map, size);

    return target;
}

void fleFrotate(int count, const char *fn) {
  int i;
  char buf1[1024];
  char buf2[1024];
      
  assert(fn!=NULL);   
  assert(count>0);
     
  for(i=count;i>0;i--) {
    snprintf(buf1,1024,"%s.%d", fn, i);
    
    /* The last file we just delete. */
    if(i==count) {
      unlink(buf1);
      continue;
    }

    /* The first file we get from *fn */
    if(i==1) {
      snprintf(buf1,1024,"%s.%d",fn,1);
      rename(fn,buf1);
      break;
    }

    snprintf(buf2,1024,"%s.%d",fn,i-1);
    rename(buf2,buf1);
  }
}
