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: /* 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: } 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 ){ 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: }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 "/" dbda8d6ce9 2007-07-21 drh: ** * Does not contain any path element that begins with "." 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; dbda8d6ce9 2007-07-21 drh: if( *z=='.' || *z=='/' || *z==0 ) return 0; 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]=='/' ){ dbda8d6ce9 2007-07-21 drh: if( z[i+1]=='/' || z[i+1]=='.' ){ 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: 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 /./ dbda8d6ce9 2007-07-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--; } dbda8d6ce9 2007-07-21 drh: i += 3; 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]=='/' af3a751841 2007-09-25 jnc: || (strlen(zOrigName)>3 && zOrigName[1]==':' && zOrigName[2]=='\\') ){ 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 b3ec774ab7 2008-02-08 drh: ** message and quit. 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: */ dbda8d6ce9 2007-07-21 drh: int file_tree_name(const char *zOrigName, Blob *pOut){ 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); b3ec774ab7 2008-02-08 drh: fossil_fatal("file outside of checkout tree: %s", zOrigName); 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++){ dbda8d6ce9 2007-07-21 drh: if( file_tree_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: /* 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: }