File Annotation
Not logged in
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Copyright (c) 2006 D. Richard Hipp
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is free software; you can redistribute it and/or
dbda8d6ce9 2007-07-21       drh: ** modify it under the terms of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License version 2 as published by the Free Software Foundation.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is distributed in the hope that it will be useful,
dbda8d6ce9 2007-07-21       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
dbda8d6ce9 2007-07-21       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dbda8d6ce9 2007-07-21       drh: ** General Public License for more details.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** You should have received a copy of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License along with this library; if not, write to the
dbda8d6ce9 2007-07-21       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dbda8d6ce9 2007-07-21       drh: ** Boston, MA  02111-1307, USA.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Author contact information:
dbda8d6ce9 2007-07-21       drh: **   drh@hwaci.com
dbda8d6ce9 2007-07-21       drh: **   http://www.hwaci.com/drh/
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: *******************************************************************************
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** File utilities
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include <sys/types.h>
dbda8d6ce9 2007-07-21       drh: #include <sys/stat.h>
dbda8d6ce9 2007-07-21       drh: #include <unistd.h>
dbda8d6ce9 2007-07-21       drh: #include "file.h"
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Return the size of a file in bytes.  Return -1 if the file does not
dbda8d6ce9 2007-07-21       drh: ** exist.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: i64 file_size(const char *zFilename){
dbda8d6ce9 2007-07-21       drh:   struct stat buf;
dbda8d6ce9 2007-07-21       drh:   if( stat(zFilename, &buf)!=0 ){
dbda8d6ce9 2007-07-21       drh:     return -1;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   return buf.st_size;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Return the modification time for a file.  Return -1 if the file
dbda8d6ce9 2007-07-21       drh: ** does not exist.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: i64 file_mtime(const char *zFilename){
dbda8d6ce9 2007-07-21       drh:   struct stat buf;
dbda8d6ce9 2007-07-21       drh:   if( stat(zFilename, &buf)!=0 ){
dbda8d6ce9 2007-07-21       drh:     return -1;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   return buf.st_mtime;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
e146d800ac 2008-11-09       drh: ** Return the tail of a file pathname.  The tail is the last component
e146d800ac 2008-11-09       drh: ** of the path.  For example, the tail of "/a/b/c.d" is "c.d".
e146d800ac 2008-11-09       drh: */
e146d800ac 2008-11-09       drh: const char *file_tail(const char *z){
e146d800ac 2008-11-09       drh:   const char *zTail = z;
e146d800ac 2008-11-09       drh:   while( z[0] ){
e146d800ac 2008-11-09       drh:     if( z[0]=='/' ) zTail = &z[1];
e146d800ac 2008-11-09       drh:     z++;
e146d800ac 2008-11-09       drh:   }
e146d800ac 2008-11-09       drh:   return zTail;
e146d800ac 2008-11-09       drh: }
e146d800ac 2008-11-09       drh: 
e146d800ac 2008-11-09       drh: /*
9236f0c086 2008-10-05       drh: ** Copy the content of a file from one place to another.
9236f0c086 2008-10-05       drh: */
9236f0c086 2008-10-05       drh: void file_copy(const char *zFrom, const char *zTo){
9236f0c086 2008-10-05       drh:   FILE *in, *out;
9236f0c086 2008-10-05       drh:   int got;
9236f0c086 2008-10-05       drh:   char zBuf[8192];
9236f0c086 2008-10-05       drh:   in = fopen(zFrom, "rb");
9236f0c086 2008-10-05       drh:   if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
9236f0c086 2008-10-05       drh:   out = fopen(zTo, "wb");
9236f0c086 2008-10-05       drh:   if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
9236f0c086 2008-10-05       drh:   while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
9236f0c086 2008-10-05       drh:     fwrite(zBuf, 1, got, out);
9236f0c086 2008-10-05       drh:   }
9236f0c086 2008-10-05       drh:   fclose(in);
9236f0c086 2008-10-05       drh:   fclose(out);
9236f0c086 2008-10-05       drh: }
9236f0c086 2008-10-05       drh: 
9236f0c086 2008-10-05       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Return TRUE if the named file is an ordinary file.  Return false
dbda8d6ce9 2007-07-21       drh: ** for directories, devices, fifos, symlinks, etc.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int file_isfile(const char *zFilename){
dbda8d6ce9 2007-07-21       drh:   struct stat buf;
dbda8d6ce9 2007-07-21       drh:   if( stat(zFilename, &buf)!=0 ){
dbda8d6ce9 2007-07-21       drh:     return 0;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   return S_ISREG(buf.st_mode);
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
33c31f73cd 2008-02-21       drh: ** Return TRUE if the named file is an executable.  Return false
33c31f73cd 2008-02-21       drh: ** for directories, devices, fifos, symlinks, etc.
33c31f73cd 2008-02-21       drh: */
33c31f73cd 2008-02-21       drh: int file_isexe(const char *zFilename){
33c31f73cd 2008-02-21       drh:   struct stat buf;
33c31f73cd 2008-02-21       drh:   if( stat(zFilename, &buf)!=0 ){
33c31f73cd 2008-02-21       drh:     return 0;
33c31f73cd 2008-02-21       drh:   }
525cc35bf3 2008-05-17       drh:   if( !S_ISREG(buf.st_mode) ) return 0;
dbb2cee113 2008-03-11  mjanssen: #ifdef __MINGW32__
dbb2cee113 2008-03-11  mjanssen:   return ((S_IXUSR)&buf.st_mode)!=0;
dbb2cee113 2008-03-11  mjanssen: #else
33c31f73cd 2008-02-21       drh:   return ((S_IXUSR|S_IXGRP|S_IXOTH)&buf.st_mode)!=0;
dbb2cee113 2008-03-11  mjanssen: #endif
33c31f73cd 2008-02-21       drh: }
33c31f73cd 2008-02-21       drh: 
33c31f73cd 2008-02-21       drh: /*
33c31f73cd 2008-02-21       drh: ** Set or clear the execute bit on a file.
33c31f73cd 2008-02-21       drh: */
33c31f73cd 2008-02-21       drh: void file_setexe(const char *zFilename, int onoff){
33c31f73cd 2008-02-21       drh: #ifndef __MINGW32__
33c31f73cd 2008-02-21       drh:   struct stat buf;
33c31f73cd 2008-02-21       drh:   if( stat(zFilename, &buf)!=0 ) return;
33c31f73cd 2008-02-21       drh:   if( onoff ){
525cc35bf3 2008-05-17       drh:     if( (buf.st_mode & 0111)!=0111 ){
33c31f73cd 2008-02-21       drh:       chmod(zFilename, buf.st_mode | 0111);
33c31f73cd 2008-02-21       drh:     }
33c31f73cd 2008-02-21       drh:   }else{
33c31f73cd 2008-02-21       drh:     if( (buf.st_mode & 0111)!=0 ){
33c31f73cd 2008-02-21       drh:       chmod(zFilename, buf.st_mode & ~0111);
33c31f73cd 2008-02-21       drh:     }
33c31f73cd 2008-02-21       drh:   }
33c31f73cd 2008-02-21       drh: #endif
33c31f73cd 2008-02-21       drh: }
33c31f73cd 2008-02-21       drh: 
33c31f73cd 2008-02-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Return 1 if zFilename is a directory.  Return 0 if zFilename
dbda8d6ce9 2007-07-21       drh: ** does not exist.  Return 2 if zFilename exists but is something
dbda8d6ce9 2007-07-21       drh: ** other than a directory.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int file_isdir(const char *zFilename){
dbda8d6ce9 2007-07-21       drh:   struct stat buf;
dbda8d6ce9 2007-07-21       drh:   if( stat(zFilename, &buf)!=0 ){
dbda8d6ce9 2007-07-21       drh:     return 0;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   return S_ISDIR(buf.st_mode) ? 1 : 2;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Create the directory named in the argument, if it does not already
dbda8d6ce9 2007-07-21       drh: ** exist.  If forceFlag is 1, delete any prior non-directory object
dbda8d6ce9 2007-07-21       drh: ** with the same name.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Return the number of errors.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int file_mkdir(const char *zName, int forceFlag){
dbda8d6ce9 2007-07-21       drh:   int rc = file_isdir(zName);
dbda8d6ce9 2007-07-21       drh:   if( rc==2 ){
dbda8d6ce9 2007-07-21       drh:     if( !forceFlag ) return 1;
dbda8d6ce9 2007-07-21       drh:     unlink(zName);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( rc!=1 ){
83c876b447 2007-09-21 anonymous: #ifdef __MINGW32__
83c876b447 2007-09-21 anonymous:     return mkdir(zName);
83c876b447 2007-09-21 anonymous: #else
dbda8d6ce9 2007-07-21       drh:     return mkdir(zName, 0755);
83c876b447 2007-09-21 anonymous: #endif
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   return 0;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Return true if the filename given is a valid filename for
dbda8d6ce9 2007-07-21       drh: ** a file in a repository.  Valid filenames follow all of the
dbda8d6ce9 2007-07-21       drh: ** following rules:
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: **     *  Does not begin with "/"
525cc35bf3 2008-05-17       drh: **     *  Does not contain any path element named "." or ".."
dbda8d6ce9 2007-07-21       drh: **     *  Does not contain any of these characters in the path: "\*[]?"
dbda8d6ce9 2007-07-21       drh: **     *  Does not end with "/".
dbda8d6ce9 2007-07-21       drh: **     *  Does not contain two or more "/" characters in a row.
dbda8d6ce9 2007-07-21       drh: **     *  Contains at least one character
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int file_is_simple_pathname(const char *z){
dbda8d6ce9 2007-07-21       drh:   int i;
525cc35bf3 2008-05-17       drh:   if( *z=='/' || *z==0 ) return 0;
525cc35bf3 2008-05-17       drh:   if( *z=='.' ){
525cc35bf3 2008-05-17       drh:     if( z[1]=='/' || z[1]==0 ) return 0;
525cc35bf3 2008-05-17       drh:     if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0;
525cc35bf3 2008-05-17       drh:   }
dbda8d6ce9 2007-07-21       drh:   for(i=0; z[i]; i++){
dbda8d6ce9 2007-07-21       drh:     if( z[i]=='\\' || z[i]=='*' || z[i]=='[' || z[i]==']' || z[i]=='?' ){
dbda8d6ce9 2007-07-21       drh:       return 0;
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     if( z[i]=='/' ){
525cc35bf3 2008-05-17       drh:       if( z[i+1]=='/' ) return 0;
525cc35bf3 2008-05-17       drh:       if( z[i+1]=='.' ){
525cc35bf3 2008-05-17       drh:         if( z[i+2]=='/' || z[i+2]==0 ) return 0;
525cc35bf3 2008-05-17       drh:         if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( z[i-1]=='/' ) return 0;
dbda8d6ce9 2007-07-21       drh:   return 1;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Simplify a filename by
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: **  * removing any trailing and duplicate /
dbda8d6ce9 2007-07-21       drh: **  * removing /./
d31c0f9c29 2008-11-21       drh: **  * removing /A/../
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Changes are made in-place.  Return the new name length.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int file_simplify_name(char *z, int n){
dbda8d6ce9 2007-07-21       drh:   int i, j;
dbda8d6ce9 2007-07-21       drh:   while( n>1 && z[n-1]=='/' ){ n--; }
dbda8d6ce9 2007-07-21       drh:   for(i=j=0; i<n; i++){
dbda8d6ce9 2007-07-21       drh:     if( z[i]=='/' ){
dbda8d6ce9 2007-07-21       drh:       if( z[i+1]=='/' ) continue;
dbda8d6ce9 2007-07-21       drh:       if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
dbda8d6ce9 2007-07-21       drh:         i += 1;
dbda8d6ce9 2007-07-21       drh:         continue;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:       if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
dbda8d6ce9 2007-07-21       drh:         while( j>0 && z[j-1]!='/' ){ j--; }
d31c0f9c29 2008-11-21       drh:         if( j>0 ){ j--; }
d31c0f9c29 2008-11-21       drh:         i += 2;
dbda8d6ce9 2007-07-21       drh:         continue;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     z[j++] = z[i];
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   z[j] = 0;
dbda8d6ce9 2007-07-21       drh:   return j;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Compute a canonical pathname for a file or directory.
dbda8d6ce9 2007-07-21       drh: ** Make the name absolute if it is relative.
dbda8d6ce9 2007-07-21       drh: ** Remove redundant / characters
dbda8d6ce9 2007-07-21       drh: ** Remove all /./ path elements.
dbda8d6ce9 2007-07-21       drh: ** Convert /A/../ to just /
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void file_canonical_name(const char *zOrigName, Blob *pOut){
af3a751841 2007-09-25       jnc:   if( zOrigName[0]=='/'
becc24e4e9 2008-05-01       drh: #ifdef __MINGW32__
becc24e4e9 2008-05-01       drh:       || (strlen(zOrigName)>3 && zOrigName[1]==':'
becc24e4e9 2008-05-01       drh:            && (zOrigName[2]=='\\' || zOrigName[2]=='/'))
becc24e4e9 2008-05-01       drh: #endif
becc24e4e9 2008-05-01       drh:   ){
dbda8d6ce9 2007-07-21       drh:     blob_set(pOut, zOrigName);
dbda8d6ce9 2007-07-21       drh:     blob_materialize(pOut);
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:     char zPwd[2000];
dbda8d6ce9 2007-07-21       drh:     if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
e63a9fd9d0 2007-09-25       jnc:       fprintf(stderr, "pwd too big: max %d\n", (int)sizeof(zPwd)-20);
dbda8d6ce9 2007-07-21       drh:       exit(1);
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     blob_zero(pOut);
c7278fd013 2007-09-22       jnc:     blob_appendf(pOut, "%//%/", zPwd, zOrigName);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND:  test-canonical-name
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Test the operation of the canonical name generator.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void cmd_test_canonical_name(void){
dbda8d6ce9 2007-07-21       drh:   int i;
dbda8d6ce9 2007-07-21       drh:   Blob x;
dbda8d6ce9 2007-07-21       drh:   blob_zero(&x);
dbda8d6ce9 2007-07-21       drh:   for(i=2; i<g.argc; i++){
dbda8d6ce9 2007-07-21       drh:     file_canonical_name(g.argv[i], &x);
dbda8d6ce9 2007-07-21       drh:     printf("%s\n", blob_buffer(&x));
dbda8d6ce9 2007-07-21       drh:     blob_reset(&x);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Compute a pathname for a file or directory that is relative
dbda8d6ce9 2007-07-21       drh: ** to the current directory.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void file_relative_name(const char *zOrigName, Blob *pOut){
dbda8d6ce9 2007-07-21       drh:   char *zPath;
dbda8d6ce9 2007-07-21       drh:   blob_set(pOut, zOrigName);
dbda8d6ce9 2007-07-21       drh:   blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
dbda8d6ce9 2007-07-21       drh:   zPath = blob_buffer(pOut);
dbda8d6ce9 2007-07-21       drh:   if( zPath[0]=='/' ){
dbda8d6ce9 2007-07-21       drh:     int i, j;
dbda8d6ce9 2007-07-21       drh:     Blob tmp;
dbda8d6ce9 2007-07-21       drh:     char zPwd[2000];
dbda8d6ce9 2007-07-21       drh:     if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
e63a9fd9d0 2007-09-25       jnc:       fprintf(stderr, "pwd too big: max %d\n", (int)sizeof(zPwd)-20);
dbda8d6ce9 2007-07-21       drh:       exit(1);
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     for(i=1; zPath[i] && zPwd[i]==zPath[i]; i++){}
dbda8d6ce9 2007-07-21       drh:     if( zPath[i]==0 ){
dbda8d6ce9 2007-07-21       drh:       blob_reset(pOut);
dbda8d6ce9 2007-07-21       drh:       if( zPwd[i]==0 ){
dbda8d6ce9 2007-07-21       drh:         blob_append(pOut, ".", 1);
dbda8d6ce9 2007-07-21       drh:       }else{
dbda8d6ce9 2007-07-21       drh:         blob_append(pOut, "..", 2);
dbda8d6ce9 2007-07-21       drh:         for(j=i+1; zPwd[j]; j++){
dbda8d6ce9 2007-07-21       drh:           if( zPwd[j]=='/' ) {
dbda8d6ce9 2007-07-21       drh:             blob_append(pOut, "/..", 3);
dbda8d6ce9 2007-07-21       drh:           }
dbda8d6ce9 2007-07-21       drh:         }
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:       return;
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     if( zPwd[i]==0 && zPath[i]=='/' ){
dbda8d6ce9 2007-07-21       drh:       memcpy(&tmp, pOut, sizeof(tmp));
dbda8d6ce9 2007-07-21       drh:       blob_set(pOut, "./");
dbda8d6ce9 2007-07-21       drh:       blob_append(pOut, &zPath[i+1], -1);
dbda8d6ce9 2007-07-21       drh:       blob_reset(&tmp);
dbda8d6ce9 2007-07-21       drh:       return;
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     while( zPath[i-1]!='/' ){ i--; }
dbda8d6ce9 2007-07-21       drh:     blob_set(&tmp, "../");
dbda8d6ce9 2007-07-21       drh:     for(j=i; zPwd[j]; j++){
dbda8d6ce9 2007-07-21       drh:       if( zPwd[j]=='/' ) {
dbda8d6ce9 2007-07-21       drh:         blob_append(&tmp, "../", 3);
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     blob_append(&tmp, &zPath[i], -1);
dbda8d6ce9 2007-07-21       drh:     blob_reset(pOut);
dbda8d6ce9 2007-07-21       drh:     memcpy(pOut, &tmp, sizeof(tmp));
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND:  test-relative-name
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Test the operation of the relative name generator.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void cmd_test_relative_name(void){
dbda8d6ce9 2007-07-21       drh:   int i;
dbda8d6ce9 2007-07-21       drh:   Blob x;
dbda8d6ce9 2007-07-21       drh:   blob_zero(&x);
dbda8d6ce9 2007-07-21       drh:   for(i=2; i<g.argc; i++){
dbda8d6ce9 2007-07-21       drh:     file_relative_name(g.argv[i], &x);
dbda8d6ce9 2007-07-21       drh:     printf("%s\n", blob_buffer(&x));
dbda8d6ce9 2007-07-21       drh:     blob_reset(&x);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Compute a pathname for a file relative to the root of the local
b3ec774ab7 2008-02-08       drh: ** tree.  Return TRUE on success.  On failure, print and error
2ecc407d9b 2008-07-23       drh: ** message and quit if the errFatal flag is true.  If errFatal is
2ecc407d9b 2008-07-23       drh: ** false, then simply return 0.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** The root of the tree is defined by the g.zLocalRoot variable.
dbda8d6ce9 2007-07-21       drh: */
2ecc407d9b 2008-07-23       drh: int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){
dbda8d6ce9 2007-07-21       drh:   int n;
dbda8d6ce9 2007-07-21       drh:   Blob full;
dbda8d6ce9 2007-07-21       drh:   db_must_be_within_tree();
dbda8d6ce9 2007-07-21       drh:   file_canonical_name(zOrigName, &full);
dbda8d6ce9 2007-07-21       drh:   n = strlen(g.zLocalRoot);
dbda8d6ce9 2007-07-21       drh:   if( blob_size(&full)<=n || memcmp(g.zLocalRoot, blob_buffer(&full), n) ){
dbda8d6ce9 2007-07-21       drh:     blob_reset(&full);
2ecc407d9b 2008-07-23       drh:     if( errFatal ){
2ecc407d9b 2008-07-23       drh:       fossil_fatal("file outside of checkout tree: %s", zOrigName);
2ecc407d9b 2008-07-23       drh:     }
dbda8d6ce9 2007-07-21       drh:     return 0;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_zero(pOut);
dbda8d6ce9 2007-07-21       drh:   blob_append(pOut, blob_buffer(&full)+n, blob_size(&full)-n);
dbda8d6ce9 2007-07-21       drh:   return 1;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND:  test-tree-name
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Test the operation of the tree name generator.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void cmd_test_tree_name(void){
dbda8d6ce9 2007-07-21       drh:   int i;
dbda8d6ce9 2007-07-21       drh:   Blob x;
dbda8d6ce9 2007-07-21       drh:   blob_zero(&x);
dbda8d6ce9 2007-07-21       drh:   for(i=2; i<g.argc; i++){
2ecc407d9b 2008-07-23       drh:     if( file_tree_name(g.argv[i], &x, 1) ){
dbda8d6ce9 2007-07-21       drh:       printf("%s\n", blob_buffer(&x));
dbda8d6ce9 2007-07-21       drh:       blob_reset(&x);
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Parse a URI into scheme, host, port, and path.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void file_parse_uri(
dbda8d6ce9 2007-07-21       drh:   const char *zUri,
dbda8d6ce9 2007-07-21       drh:   Blob *pScheme,
dbda8d6ce9 2007-07-21       drh:   Blob *pHost,
dbda8d6ce9 2007-07-21       drh:   int *pPort,
dbda8d6ce9 2007-07-21       drh:   Blob *pPath
dbda8d6ce9 2007-07-21       drh: ){
dbda8d6ce9 2007-07-21       drh:   int i, j;
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh:   for(i=0; zUri[i] && zUri[i]>='a' && zUri[i]<='z'; i++){}
dbda8d6ce9 2007-07-21       drh:   if( zUri[i]!=':' ){
dbda8d6ce9 2007-07-21       drh:     blob_zero(pScheme);
dbda8d6ce9 2007-07-21       drh:     blob_zero(pHost);
dbda8d6ce9 2007-07-21       drh:     blob_set(pPath, zUri);
dbda8d6ce9 2007-07-21       drh:     return;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_init(pScheme, zUri, i);
dbda8d6ce9 2007-07-21       drh:   i++;
dbda8d6ce9 2007-07-21       drh:   if( zUri[i]=='/' && zUri[i+1]=='/' ){
dbda8d6ce9 2007-07-21       drh:     i += 2;
dbda8d6ce9 2007-07-21       drh:     j = i;
dbda8d6ce9 2007-07-21       drh:     while( zUri[i] && zUri[i]!='/' && zUri[i]!=':' ){ i++; }
dbda8d6ce9 2007-07-21       drh:     blob_init(pHost, &zUri[j], i-j);
dbda8d6ce9 2007-07-21       drh:     if( zUri[i]==':' ){
dbda8d6ce9 2007-07-21       drh:       i++;
dbda8d6ce9 2007-07-21       drh:       *pPort = atoi(&zUri[i]);
dbda8d6ce9 2007-07-21       drh:       while( zUri[i] && zUri[i]!='/' ){ i++; }
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:     blob_zero(pHost);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   if( zUri[i]=='/' ){
dbda8d6ce9 2007-07-21       drh:     blob_set(pPath, &zUri[i]);
dbda8d6ce9 2007-07-21       drh:   }else{
dbda8d6ce9 2007-07-21       drh:     blob_set(pPath, "/");
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }