/*
 *  This file is part of DVS, a simple distributed versioning system
 *  See http://www.cs.colorado.edu/~carzanig/dvs/
 *
 *  Author: Antonio Carzaniga <carzanig@cs.colorado.edu>
 *
 *  Copyright (C) 1998-2002 University of Colorado
 *
 *  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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
 *  USA, or send email to carzanig@cs.colorado.edu.
 *
 *
 *  $Id: paths.c,v 1.9 2002/05/01 17:38:31 carzanig Exp $
 */
#include <stdio.h>

#include <nc.h>

#include "paths.h"
/*
 *  this function copies in filename the filename referred by pathname
 *  e.g., pathname = "//host:1234/ciao/miao:2" --> filename == "miao" 
 */
const char *pathfilename(const char *pathname)
{
    static char filename[MAXPATHLEN];
    return pathfilename_r(pathname,filename);
}

char *pathfilename_x(char *pathname)
{
    pathfilename_r(pathname, pathname);
    return pathname;
}

char *pathfilename_r(const char *pathname, char *filename)
{
    const char *curs;
    char *aux;

    for(curs = pathname; *curs != '\0'; curs++);
    while(*curs != FS_SEPARATOR && curs != pathname) curs--; 
    if (*curs == FS_SEPARATOR) curs++;

    aux = filename;
    while(*curs != '\0' && *curs != VERSION_SEPARATOR)
	*filename++ = *curs++; 
    *filename = '\0';

    return aux;
}

const char *version_position(const char *pathname)
{
    /*
     *  returns a pointer to the first char of the version id
     *  if pathname doesn't have a version id, it returns the pointer
     *  to the end of pathname (thus, *version_position == '\0')
     */
    const char *curs;
    const char *aux;

    for(curs = pathname; *curs != '\0'; curs++);
    for(aux = curs; *curs != FS_SEPARATOR && curs != pathname; --curs)
	if (*curs == VERSION_SEPARATOR) 
	    return ++curs;
    
    return aux;
}

char *version_position_x(char *pathname)
{
    char *curs;
    char *aux;

    for(curs = pathname; *curs != '\0'; curs++);
    for(aux = curs; *curs != FS_SEPARATOR && curs != pathname; --curs)
	if (*curs == VERSION_SEPARATOR) 
	    return ++curs;
    
    return aux;
}


/*
 *  this function copies pathname into filename stripping off the version
 *  e.g., pathname = "//host:1234/ciao/miao:2"
 *        --> filename == "//host:1234/ciao/miao" 
 */
const char *strip_version(const char *pathname)
{
    static char filename[MAXPATHLEN];
    return strip_version_r(pathname,filename);
}

char *strip_version_x(char *pathname)
{
    char *curs;

    if (*(curs = version_position_x(pathname)) != '\0') 
	*--curs = '\0';

    return pathname;
}

char *strip_version_r(const char *pathname, char *filename)
{
    char *curs;
  
    for(curs = filename; *pathname != '\0'; *curs++ = *pathname++);
    *curs = '\0';
  
    return strip_version_x(filename);
}

/*
 *  splits a (local) pathname into a directory and a filename
 *  pathname: pippo/pluto/paperino
 *  --> *directory = pippo/pluto
 *  --> *filename = paperino
 */
/*
char *split_directory_file_x(const char *pathname, 
			     char *directory,
			     char *filename)
{
    const char *f_start = pathname;
    const char *curs = pathname;
    char **target;

    while(*curs != '\0';)
	if (*curs == FS_SEPARATOR) 
	    f_start = curs;

    target = &directory;
    for(curs = pathname; *curs != '\0'; ++curs) {
	if (curs == f_start) target = &filename;
	**target = *curs;

    } 
}
*/

/*
 *  this function copies pathname into filename stripping off the version
 *  e.g., pathname = "//host:1234/ciao/miao:2"
 *        --> filename == "//host:1234/ciao/miao" 
 */
const char *set_version(const char *pathname, const char *version)
{
    static char filename[MAXPATHLEN];
    return set_version_r(pathname,filename, version);
}

char *set_version_x(char *pathname, const char *version)
{
    char *curs;
    char *vers;

    for(curs = pathname; *curs != '\0'; curs++);

    vers = curs;
    while(*curs != FS_SEPARATOR && curs != pathname)
	if (*curs == VERSION_SEPARATOR) {
	    vers = curs;
	    break;
	}
	else
	    curs--;

    *vers++ = VERSION_SEPARATOR;
    while(*version != '\0')
	*vers++ = *version++;
    *vers = '\0';

    return pathname;
}

char *set_version_r(const char *pathname, char *filename, const char *version)
{
    char *curs;
    char *vers;

    for(curs = filename; *pathname != '\0'; *curs++ = *pathname++);
    vers = curs;
    while(*curs != FS_SEPARATOR && curs != filename) {
	if (*curs == VERSION_SEPARATOR) {
	    vers = curs;
	    break;
	}
	else curs--;
    }
    *vers++ = VERSION_SEPARATOR;
    while(*version != '\0')
	*vers++ = *version++;
    *vers = '\0';

    return filename;
}

/*
 *  this determines whether pathname refers to a local path or it refers
 *  to a remote path (on a server). This version is very primitive. It
 *  simply checks whether pathname begins with "//"
 */
int local_path(const char *pathname) 
{
    return (*pathname != '/' || *(++pathname) != '/');
}

/*
 *  this attach the server information to a path, if the server is already
 *  specified then these function overwrite it
 */
const char *attach_server(const char *pathname, const t_server *myserver)
{
    static char completepath[MAXPATHLEN];

    return attach_server_r(pathname, completepath, myserver);
}

char *attach_server_x(char *pathname, const t_server *myserver)
{
    strcpy(pathname, attach_server(pathname,myserver));
    return pathname;
}

char *attach_server_r(const char *pathname, char *completepath, 
		      const t_server *myserver)
{
    if (*pathname == FS_SEPARATOR) pathname++;
    if (*pathname == FS_SEPARATOR)
	for(pathname++; *pathname != '\0';pathname++)
	    if (*pathname == FS_SEPARATOR) {
		pathname++;
		break;
	    }
    
    sprintf(completepath, "%c%c%s%c%s%c%s", FS_SEPARATOR, FS_SEPARATOR,
	    myserver->host, VERSION_SEPARATOR, myserver->port, 
	    FS_SEPARATOR, pathname);
    return completepath;
}

static char *copy_local_part(char *path, const char *s) {
    char *start = path;
  
    while ((*path = *s++) != '\0') 
	++path;

    if (path != start) {
	--path;
	if (*path == FS_SEPARATOR || *path == VERSION_SEPARATOR) {
	    *path = '\0';
	} else {
	    ++path;
	}
    }
    return path;
}

/*
 *  copies s into path making sure that path has a correct syntax
 */
char *copy_normalize_path(char *path, const char *s)
{
    if ((*path = *s++) == FS_SEPARATOR) {
	++path;
	if ((*path = *s++) == FS_SEPARATOR) {
	    ++path;
	    while (*s != FS_SEPARATOR && *s != '\0') {
		*path++ = *s++;
	    }
	    *path = '\0';
	    return copy_local_part(path, s);
	}
    }
    if (*path != '\0')
	return copy_local_part(++path, s);
    else 
	return path;
}

char *copy_dirname_filename(char *dirname, char *filename, const char *path)
{
    const char *curs;
    char *dir_c = dirname;
    char *file_c = filename;

    for(curs = path; *curs != '\0'; ++curs) {
        *dirname++ = *curs;
	if(*curs == FS_SEPARATOR) {
	    if (curs[1] == '\0') break;
	    file_c = filename;
	    dir_c = dirname;
	} else {
	  *file_c++ = *curs;
	} 
    }
    *dir_c = '\0';
    *file_c = '\0';

    return filename;
}

