Fossil SCM

Merge in the w32 changes.

drh 2007-09-22 19:43 trunk merge
Commit 3c5482959c058d62b032ad5819a738dd418a73cf
+46
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -0,0 +1,46 @@
1
+#!/usr/bin/make
2
+#
3
+#### The toplevel directory of the source tree. Fossil can be built
4
+# in a directory that is separate from the source tree. Just change
5
+# the following to point from the build direcSRCDIR = ./srcf the source trere. Fossil can be builsil can be built
6
+# in a directory that is separate from the source tree. Just change
7
+# the following to point from the build directory to the src/ folder.
8
+#
9
+DIRSEP = \\
10
+OPERATING_SYSTEM = windows
11
+SRCDIR = .$(DIRSEP)src
12
+OBJDIR = .$(DIRSEP)wobj
13
+
14
+#### C Compiler and options for use in building executables that
15
+# will## The toplevel directory of the source tree. Fossil can be built
16
+# in a directory that is separate from the source tree. Just change
17
+# the following to point from the build directory to the src/ folder.
18
+#
19
+DIRSEP = \\
20
+OPERATING_SYSTEM = windows
21
+SRCDIR = .$(DIRSEP)src
22
+OBJDIR = .$(DIRSEP)wobj
23
+
24
+#### C Compiler and options for use in building executables that
25
+# will run on the platTCC = = gcc -g -Oslocal/lib -I/usr/local to link against the Z-Lib compression library. T
26
+# other dependencies. We sometimes add the -static option here
27
+# so that we can build a static executable that will run in a
28
+# chroot jail.
29
+#
30
+#LIB = -lz
31
+#LIB = -lz -lws2_32
32
+LIB = -lmingwex -lz -lws2_32
33
+# OpenSSL:
34
+ifdef FOSSIL_ENABLE_SSL
35
+LIB += -lcrypto -lssl
36
+endif
37
+
38
+#### Tcl shell for use in running the fossil testsuite.
39
+#
40
+TCLSH = tclsh
41
+
42
+#### Include a configuration file that can override any one of these settings.
43
+#
44
+-include config.w32
45
+
46
+# You should not need t
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -0,0 +1,46 @@
1 #!/usr/bin/make
2 #
3 #### The toplevel directory of the source tree. Fossil can be built
4 # in a directory that is separate from the source tree. Just change
5 # the following to point from the build direcSRCDIR = ./srcf the source trere. Fossil can be builsil can be built
6 # in a directory that is separate from the source tree. Just change
7 # the following to point from the build directory to the src/ folder.
8 #
9 DIRSEP = \\
10 OPERATING_SYSTEM = windows
11 SRCDIR = .$(DIRSEP)src
12 OBJDIR = .$(DIRSEP)wobj
13
14 #### C Compiler and options for use in building executables that
15 # will## The toplevel directory of the source tree. Fossil can be built
16 # in a directory that is separate from the source tree. Just change
17 # the following to point from the build directory to the src/ folder.
18 #
19 DIRSEP = \\
20 OPERATING_SYSTEM = windows
21 SRCDIR = .$(DIRSEP)src
22 OBJDIR = .$(DIRSEP)wobj
23
24 #### C Compiler and options for use in building executables that
25 # will run on the platTCC = = gcc -g -Oslocal/lib -I/usr/local to link against the Z-Lib compression library. T
26 # other dependencies. We sometimes add the -static option here
27 # so that we can build a static executable that will run in a
28 # chroot jail.
29 #
30 #LIB = -lz
31 #LIB = -lz -lws2_32
32 LIB = -lmingwex -lz -lws2_32
33 # OpenSSL:
34 ifdef FOSSIL_ENABLE_SSL
35 LIB += -lcrypto -lssl
36 endif
37
38 #### Tcl shell for use in running the fossil testsuite.
39 #
40 TCLSH = tclsh
41
42 #### Include a configuration file that can override any one of these settings.
43 #
44 -include config.w32
45
46 # You should not need t
+46
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -0,0 +1,46 @@
1
+#!/usr/bin/make
2
+#
3
+#### The toplevel directory of the source tree. Fossil can be built
4
+# in a directory that is separate from the source tree. Just change
5
+# the following to point from the build direcSRCDIR = ./srcf the source trere. Fossil can be builsil can be built
6
+# in a directory that is separate from the source tree. Just change
7
+# the following to point from the build directory to the src/ folder.
8
+#
9
+DIRSEP = \\
10
+OPERATING_SYSTEM = windows
11
+SRCDIR = .$(DIRSEP)src
12
+OBJDIR = .$(DIRSEP)wobj
13
+
14
+#### C Compiler and options for use in building executables that
15
+# will## The toplevel directory of the source tree. Fossil can be built
16
+# in a directory that is separate from the source tree. Just change
17
+# the following to point from the build directory to the src/ folder.
18
+#
19
+DIRSEP = \\
20
+OPERATING_SYSTEM = windows
21
+SRCDIR = .$(DIRSEP)src
22
+OBJDIR = .$(DIRSEP)wobj
23
+
24
+#### C Compiler and options for use in building executables that
25
+# will run on the platTCC = = gcc -g -Oslocal/lib -I/usr/local to link against the Z-Lib compression library. T
26
+# other dependencies. We sometimes add the -static option here
27
+# so that we can build a static executable that will run in a
28
+# chroot jail.
29
+#
30
+#LIB = -lz
31
+#LIB = -lz -lws2_32
32
+LIB = -lmingwex -lz -lws2_32
33
+# OpenSSL:
34
+ifdef FOSSIL_ENABLE_SSL
35
+LIB += -lcrypto -lssl
36
+endif
37
+
38
+#### Tcl shell for use in running the fossil testsuite.
39
+#
40
+TCLSH = tclsh
41
+
42
+#### Include a configuration file that can override any one of these settings.
43
+#
44
+-include config.w32
45
+
46
+# You should not need t
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -0,0 +1,46 @@
1 #!/usr/bin/make
2 #
3 #### The toplevel directory of the source tree. Fossil can be built
4 # in a directory that is separate from the source tree. Just change
5 # the following to point from the build direcSRCDIR = ./srcf the source trere. Fossil can be builsil can be built
6 # in a directory that is separate from the source tree. Just change
7 # the following to point from the build directory to the src/ folder.
8 #
9 DIRSEP = \\
10 OPERATING_SYSTEM = windows
11 SRCDIR = .$(DIRSEP)src
12 OBJDIR = .$(DIRSEP)wobj
13
14 #### C Compiler and options for use in building executables that
15 # will## The toplevel directory of the source tree. Fossil can be built
16 # in a directory that is separate from the source tree. Just change
17 # the following to point from the build directory to the src/ folder.
18 #
19 DIRSEP = \\
20 OPERATING_SYSTEM = windows
21 SRCDIR = .$(DIRSEP)src
22 OBJDIR = .$(DIRSEP)wobj
23
24 #### C Compiler and options for use in building executables that
25 # will run on the platTCC = = gcc -g -Oslocal/lib -I/usr/local to link against the Z-Lib compression library. T
26 # other dependencies. We sometimes add the -static option here
27 # so that we can build a static executable that will run in a
28 # chroot jail.
29 #
30 #LIB = -lz
31 #LIB = -lz -lws2_32
32 LIB = -lmingwex -lz -lws2_32
33 # OpenSSL:
34 ifdef FOSSIL_ENABLE_SSL
35 LIB += -lcrypto -lssl
36 endif
37
38 #### Tcl shell for use in running the fossil testsuite.
39 #
40 TCLSH = tclsh
41
42 #### Include a configuration file that can override any one of these settings.
43 #
44 -include config.w32
45
46 # You should not need t
+2 -2
--- src/add.c
+++ src/add.c
@@ -50,11 +50,11 @@
5050
char *zName;
5151
char *zPath;
5252
Blob pathname;
5353
int isDir;
5454
55
- zName = mprintf("%s", g.argv[i]);
55
+ zName = mprintf("%/", g.argv[i]);
5656
isDir = file_isdir(zName);
5757
if( isDir==1 ) continue;
5858
if( isDir==0 ){
5959
fossil_fatal("not found: %s", zName);
6060
}
@@ -100,11 +100,11 @@
100100
for(i=2; i<g.argc; i++){
101101
char *zName;
102102
char *zPath;
103103
Blob pathname;
104104
105
- zName = mprintf("%s", g.argv[i]);
105
+ zName = mprintf("%/", g.argv[i]);
106106
file_tree_name(zName, &pathname);
107107
zPath = blob_str(&pathname);
108108
if( !db_exists(
109109
"SELECT 1 FROM vfile WHERE pathname=%Q AND NOT deleted", zPath) ){
110110
fossil_fatal("not in the repository: %s", zName);
111111
--- src/add.c
+++ src/add.c
@@ -50,11 +50,11 @@
50 char *zName;
51 char *zPath;
52 Blob pathname;
53 int isDir;
54
55 zName = mprintf("%s", g.argv[i]);
56 isDir = file_isdir(zName);
57 if( isDir==1 ) continue;
58 if( isDir==0 ){
59 fossil_fatal("not found: %s", zName);
60 }
@@ -100,11 +100,11 @@
100 for(i=2; i<g.argc; i++){
101 char *zName;
102 char *zPath;
103 Blob pathname;
104
105 zName = mprintf("%s", g.argv[i]);
106 file_tree_name(zName, &pathname);
107 zPath = blob_str(&pathname);
108 if( !db_exists(
109 "SELECT 1 FROM vfile WHERE pathname=%Q AND NOT deleted", zPath) ){
110 fossil_fatal("not in the repository: %s", zName);
111
--- src/add.c
+++ src/add.c
@@ -50,11 +50,11 @@
50 char *zName;
51 char *zPath;
52 Blob pathname;
53 int isDir;
54
55 zName = mprintf("%/", g.argv[i]);
56 isDir = file_isdir(zName);
57 if( isDir==1 ) continue;
58 if( isDir==0 ){
59 fossil_fatal("not found: %s", zName);
60 }
@@ -100,11 +100,11 @@
100 for(i=2; i<g.argc; i++){
101 char *zName;
102 char *zPath;
103 Blob pathname;
104
105 zName = mprintf("%/", g.argv[i]);
106 file_tree_name(zName, &pathname);
107 zPath = blob_str(&pathname);
108 if( !db_exists(
109 "SELECT 1 FROM vfile WHERE pathname=%Q AND NOT deleted", zPath) ){
110 fossil_fatal("not in the repository: %s", zName);
111
+13 -2
--- src/blob.c
+++ src/blob.c
@@ -571,13 +571,24 @@
571571
}
572572
nName = file_simplify_name(zName, nName);
573573
for(i=1; i<nName; i++){
574574
if( zName[i]=='/' ){
575575
zName[i] = 0;
576
- if( file_mkdir(zName, 1) ){
577
- fossil_panic("unable to create directory %s", zName);
576
+#ifdef __MINGW32__
577
+ /*
578
+ ** On Windows, local path looks like: C:/develop/project/file.txt
579
+ ** The if stops us from trying to create a directory of a drive letter
580
+ ** C: in this example.
581
+ */
582
+ if( !(i==2 && zName[1]==':') ){
583
+#endif
584
+ if( file_mkdir(zName, 1) ){
585
+ fossil_panic("unable to create directory %s", zName);
586
+ }
587
+#ifdef __MINGW32__
578588
}
589
+#endif
579590
zName[i] = '/';
580591
}
581592
}
582593
out = fopen(zName, "wb");
583594
if( out==0 ){
584595
--- src/blob.c
+++ src/blob.c
@@ -571,13 +571,24 @@
571 }
572 nName = file_simplify_name(zName, nName);
573 for(i=1; i<nName; i++){
574 if( zName[i]=='/' ){
575 zName[i] = 0;
576 if( file_mkdir(zName, 1) ){
577 fossil_panic("unable to create directory %s", zName);
 
 
 
 
 
 
 
 
 
 
578 }
 
579 zName[i] = '/';
580 }
581 }
582 out = fopen(zName, "wb");
583 if( out==0 ){
584
--- src/blob.c
+++ src/blob.c
@@ -571,13 +571,24 @@
571 }
572 nName = file_simplify_name(zName, nName);
573 for(i=1; i<nName; i++){
574 if( zName[i]=='/' ){
575 zName[i] = 0;
576 #ifdef __MINGW32__
577 /*
578 ** On Windows, local path looks like: C:/develop/project/file.txt
579 ** The if stops us from trying to create a directory of a drive letter
580 ** C: in this example.
581 */
582 if( !(i==2 && zName[1]==':') ){
583 #endif
584 if( file_mkdir(zName, 1) ){
585 fossil_panic("unable to create directory %s", zName);
586 }
587 #ifdef __MINGW32__
588 }
589 #endif
590 zName[i] = '/';
591 }
592 }
593 out = fopen(zName, "wb");
594 if( out==0 ){
595
+18 -7
--- src/cgi.c
+++ src/cgi.c
@@ -26,20 +26,26 @@
2626
** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
2727
** formatting function and its cousins, and routines to encode and
2828
** decode strings in HTML or HTTP.
2929
*/
3030
#include "config.h"
31
-#include <sys/socket.h>
32
-#include <netinet/in.h>
33
-#include <arpa/inet.h>
31
+#ifdef __MINGW32__
32
+# include <windows.h> /* for Sleep once server works again */
33
+# include <winsock2.h> /* socket operations */
34
+# define sleep Sleep /* windows does not have sleep, but Sleep */
35
+#else
36
+# include <sys/socket.h>
37
+# include <netinet/in.h>
38
+# include <arpa/inet.h>
39
+# include <sys/times.h>
40
+# include <sys/time.h>
41
+# include <sys/wait.h>
42
+# include <sys/select.h>
43
+#endif
3444
#include <time.h>
35
-#include <sys/times.h>
36
-#include <sys/time.h>
37
-#include <sys/wait.h>
3845
#include <stdio.h>
3946
#include <stdlib.h>
40
-#include <sys/select.h>
4147
#include <unistd.h>
4248
#include "cgi.h"
4349
4450
#if INTERFACE
4551
/*
@@ -1076,10 +1082,14 @@
10761082
** As new connections arrive, fork a child and let child return
10771083
** out of this procedure call. The child will handle the request.
10781084
** The parent never returns from this procedure.
10791085
*/
10801086
void cgi_http_server(int iPort){
1087
+#ifdef __MINGW32__
1088
+ fprintf(stderr,"server not yet available in windows version of fossil\n");
1089
+ exit(1);
1090
+#else
10811091
int listener; /* The server socket */
10821092
int connection; /* A socket for each individual connection */
10831093
fd_set readfds; /* Set of file descriptors for select() */
10841094
size_t lenaddr; /* Length of the inaddr structure */
10851095
int child; /* PID of the child process */
@@ -1142,10 +1152,11 @@
11421152
nchildren--;
11431153
}
11441154
}
11451155
/* NOT REACHED */
11461156
exit(1);
1157
+#endif
11471158
}
11481159
11491160
/*
11501161
** Name of days and months.
11511162
*/
11521163
--- src/cgi.c
+++ src/cgi.c
@@ -26,20 +26,26 @@
26 ** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
27 ** formatting function and its cousins, and routines to encode and
28 ** decode strings in HTML or HTTP.
29 */
30 #include "config.h"
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
 
 
 
 
 
 
 
 
 
 
34 #include <time.h>
35 #include <sys/times.h>
36 #include <sys/time.h>
37 #include <sys/wait.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <sys/select.h>
41 #include <unistd.h>
42 #include "cgi.h"
43
44 #if INTERFACE
45 /*
@@ -1076,10 +1082,14 @@
1076 ** As new connections arrive, fork a child and let child return
1077 ** out of this procedure call. The child will handle the request.
1078 ** The parent never returns from this procedure.
1079 */
1080 void cgi_http_server(int iPort){
 
 
 
 
1081 int listener; /* The server socket */
1082 int connection; /* A socket for each individual connection */
1083 fd_set readfds; /* Set of file descriptors for select() */
1084 size_t lenaddr; /* Length of the inaddr structure */
1085 int child; /* PID of the child process */
@@ -1142,10 +1152,11 @@
1142 nchildren--;
1143 }
1144 }
1145 /* NOT REACHED */
1146 exit(1);
 
1147 }
1148
1149 /*
1150 ** Name of days and months.
1151 */
1152
--- src/cgi.c
+++ src/cgi.c
@@ -26,20 +26,26 @@
26 ** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
27 ** formatting function and its cousins, and routines to encode and
28 ** decode strings in HTML or HTTP.
29 */
30 #include "config.h"
31 #ifdef __MINGW32__
32 # include <windows.h> /* for Sleep once server works again */
33 # include <winsock2.h> /* socket operations */
34 # define sleep Sleep /* windows does not have sleep, but Sleep */
35 #else
36 # include <sys/socket.h>
37 # include <netinet/in.h>
38 # include <arpa/inet.h>
39 # include <sys/times.h>
40 # include <sys/time.h>
41 # include <sys/wait.h>
42 # include <sys/select.h>
43 #endif
44 #include <time.h>
 
 
 
45 #include <stdio.h>
46 #include <stdlib.h>
 
47 #include <unistd.h>
48 #include "cgi.h"
49
50 #if INTERFACE
51 /*
@@ -1076,10 +1082,14 @@
1082 ** As new connections arrive, fork a child and let child return
1083 ** out of this procedure call. The child will handle the request.
1084 ** The parent never returns from this procedure.
1085 */
1086 void cgi_http_server(int iPort){
1087 #ifdef __MINGW32__
1088 fprintf(stderr,"server not yet available in windows version of fossil\n");
1089 exit(1);
1090 #else
1091 int listener; /* The server socket */
1092 int connection; /* A socket for each individual connection */
1093 fd_set readfds; /* Set of file descriptors for select() */
1094 size_t lenaddr; /* Length of the inaddr structure */
1095 int child; /* PID of the child process */
@@ -1142,10 +1152,11 @@
1152 nchildren--;
1153 }
1154 }
1155 /* NOT REACHED */
1156 exit(1);
1157 #endif
1158 }
1159
1160 /*
1161 ** Name of days and months.
1162 */
1163
+22 -4
--- src/checkin.c
+++ src/checkin.c
@@ -162,18 +162,24 @@
162162
db_finalize(&q);
163163
}
164164
165165
/*
166166
** COMMAND: clean
167
-** Usage: %fossil clean
167
+** Usage: %fossil clean ?-all
168168
** Delete all "extra" files in the source tree. "Extra" files are
169169
** files that are not officially part of the checkout. See also
170
-** the "extra" command.
170
+** the "extra" command. This operation cannot be undone.
171
+**
172
+** You will be prompted before removing each file. If you are
173
+** sure you wish to remove all "extra" files you can specify the
174
+** optional -all flag.
171175
*/
172176
void clean_cmd(void){
177
+ int allFlag;
173178
Blob path;
174179
Stmt q;
180
+ allFlag = find_option("all","a",0)!=0;
175181
db_must_be_within_tree();
176182
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
177183
chdir(g.zLocalRoot);
178184
blob_zero(&path);
179185
vfile_scan(0, &path);
@@ -180,11 +186,23 @@
180186
db_prepare(&q,
181187
"SELECT %Q || x FROM sfile"
182188
" WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_')"
183189
" ORDER BY 1", g.zLocalRoot);
184190
while( db_step(&q)==SQLITE_ROW ){
185
- unlink(db_column_text(&q, 0));
191
+ if( allFlag ){
192
+ unlink(db_column_text(&q, 0));
193
+ continue;
194
+ }
195
+
196
+ Blob ans;
197
+ char *prompt = mprintf("remove unmanaged file \"%s\" [y/N]? ",
198
+ db_column_text(&q, 0));
199
+ blob_zero(&ans);
200
+ prompt_user(prompt, &ans);
201
+ if( blob_str(&ans)[0]=='y' ){
202
+ unlink(db_column_text(&q, 0));
203
+ }
186204
}
187205
db_finalize(&q);
188206
}
189207
190208
/*
@@ -218,11 +236,11 @@
218236
zEditor = "ed";
219237
}
220238
zFile = db_text(0, "SELECT '%qci-comment-' || hex(randomblob(6)) || '.txt'",
221239
g.zLocalRoot);
222240
blob_write_to_file(&text, zFile);
223
- zCmd = mprintf("%s %s", zEditor, zFile);
241
+ zCmd = mprintf("%s \"%s\"", zEditor, zFile);
224242
printf("%s\n", zCmd);
225243
if( system(zCmd) ){
226244
fossil_panic("editor aborted");
227245
}
228246
blob_reset(&text);
229247
--- src/checkin.c
+++ src/checkin.c
@@ -162,18 +162,24 @@
162 db_finalize(&q);
163 }
164
165 /*
166 ** COMMAND: clean
167 ** Usage: %fossil clean
168 ** Delete all "extra" files in the source tree. "Extra" files are
169 ** files that are not officially part of the checkout. See also
170 ** the "extra" command.
 
 
 
 
171 */
172 void clean_cmd(void){
 
173 Blob path;
174 Stmt q;
 
175 db_must_be_within_tree();
176 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
177 chdir(g.zLocalRoot);
178 blob_zero(&path);
179 vfile_scan(0, &path);
@@ -180,11 +186,23 @@
180 db_prepare(&q,
181 "SELECT %Q || x FROM sfile"
182 " WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_')"
183 " ORDER BY 1", g.zLocalRoot);
184 while( db_step(&q)==SQLITE_ROW ){
185 unlink(db_column_text(&q, 0));
 
 
 
 
 
 
 
 
 
 
 
 
186 }
187 db_finalize(&q);
188 }
189
190 /*
@@ -218,11 +236,11 @@
218 zEditor = "ed";
219 }
220 zFile = db_text(0, "SELECT '%qci-comment-' || hex(randomblob(6)) || '.txt'",
221 g.zLocalRoot);
222 blob_write_to_file(&text, zFile);
223 zCmd = mprintf("%s %s", zEditor, zFile);
224 printf("%s\n", zCmd);
225 if( system(zCmd) ){
226 fossil_panic("editor aborted");
227 }
228 blob_reset(&text);
229
--- src/checkin.c
+++ src/checkin.c
@@ -162,18 +162,24 @@
162 db_finalize(&q);
163 }
164
165 /*
166 ** COMMAND: clean
167 ** Usage: %fossil clean ?-all
168 ** Delete all "extra" files in the source tree. "Extra" files are
169 ** files that are not officially part of the checkout. See also
170 ** the "extra" command. This operation cannot be undone.
171 **
172 ** You will be prompted before removing each file. If you are
173 ** sure you wish to remove all "extra" files you can specify the
174 ** optional -all flag.
175 */
176 void clean_cmd(void){
177 int allFlag;
178 Blob path;
179 Stmt q;
180 allFlag = find_option("all","a",0)!=0;
181 db_must_be_within_tree();
182 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
183 chdir(g.zLocalRoot);
184 blob_zero(&path);
185 vfile_scan(0, &path);
@@ -180,11 +186,23 @@
186 db_prepare(&q,
187 "SELECT %Q || x FROM sfile"
188 " WHERE x NOT IN ('manifest','manifest.uuid','_FOSSIL_')"
189 " ORDER BY 1", g.zLocalRoot);
190 while( db_step(&q)==SQLITE_ROW ){
191 if( allFlag ){
192 unlink(db_column_text(&q, 0));
193 continue;
194 }
195
196 Blob ans;
197 char *prompt = mprintf("remove unmanaged file \"%s\" [y/N]? ",
198 db_column_text(&q, 0));
199 blob_zero(&ans);
200 prompt_user(prompt, &ans);
201 if( blob_str(&ans)[0]=='y' ){
202 unlink(db_column_text(&q, 0));
203 }
204 }
205 db_finalize(&q);
206 }
207
208 /*
@@ -218,11 +236,11 @@
236 zEditor = "ed";
237 }
238 zFile = db_text(0, "SELECT '%qci-comment-' || hex(randomblob(6)) || '.txt'",
239 g.zLocalRoot);
240 blob_write_to_file(&text, zFile);
241 zCmd = mprintf("%s \"%s\"", zEditor, zFile);
242 printf("%s\n", zCmd);
243 if( system(zCmd) ){
244 fossil_panic("editor aborted");
245 }
246 blob_reset(&text);
247
+24 -2
--- src/db.c
+++ src/db.c
@@ -33,14 +33,16 @@
3333
** (3) A local checkout database named "FOSSIL" and located at the
3434
** root of the local copy of the source tree.
3535
**
3636
*/
3737
#include "config.h"
38
+#ifndef __MINGW32__
39
+# include <pwd.h>
40
+#endif
3841
#include <sqlite3.h>
3942
#include <sys/types.h>
4043
#include <sys/stat.h>
41
-#include <pwd.h>
4244
#include <unistd.h>
4345
#include "db.h"
4446
4547
#if INTERFACE
4648
/*
@@ -488,15 +490,31 @@
488490
** Open the user database in "~/.fossil". Create the database anew if
489491
** it does not already exist.
490492
*/
491493
void db_open_config(void){
492494
char *zDbName;
493
- const char *zHome = getenv("HOME");
495
+ const char *zHome;
496
+#ifdef __MINGW32__
497
+ zHome = getenv("LOCALAPPDATA");
498
+ if( zHome==0 ){
499
+ zHome = getenv("APPDATA");
500
+ if( zHome==0 ){
501
+ zHome = getenv("HOMEPATH");
502
+ }
503
+ }
504
+#else
505
+ zHome = getenv("HOME");
506
+#endif
494507
if( zHome==0 ){
495508
db_err("cannot local home directory");
496509
}
510
+#ifdef __MINGW32__
511
+ /* . filenames give some window systems problems and many apps problems */
512
+ zDbName = mprintf("%s/_fossil", zHome);
513
+#else
497514
zDbName = mprintf("%s/.fossil", zHome);
515
+#endif
498516
if( g.configOpen ) return;
499517
if( file_size(zDbName)<1024*3 ){
500518
db_init_database(zDbName, zConfigSchema, (char*)0);
501519
}
502520
db_open_or_attach(zDbName, "configdb");
@@ -534,15 +552,19 @@
534552
** it is attached to the open database connection too.
535553
*/
536554
int db_open_local(void){
537555
int n;
538556
char zPwd[2000];
557
+ char *zPwdConv;
539558
if( g.localOpen) return 1;
540559
if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
541560
db_err("pwd too big: max %d", sizeof(zPwd)-20);
542561
}
543562
n = strlen(zPwd);
563
+ zPwdConv = mprintf("%/", zPwd);
564
+ strncpy(zPwd, zPwdConv, 2000-20);
565
+ free(zPwdConv);
544566
while( n>0 ){
545567
if( access(zPwd, W_OK) ) break;
546568
strcpy(&zPwd[n], "/_FOSSIL_");
547569
if( isValidLocalDb(zPwd) ){
548570
/* Found a valid _FOSSIL_ file */
549571
--- src/db.c
+++ src/db.c
@@ -33,14 +33,16 @@
33 ** (3) A local checkout database named "FOSSIL" and located at the
34 ** root of the local copy of the source tree.
35 **
36 */
37 #include "config.h"
 
 
 
38 #include <sqlite3.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <pwd.h>
42 #include <unistd.h>
43 #include "db.h"
44
45 #if INTERFACE
46 /*
@@ -488,15 +490,31 @@
488 ** Open the user database in "~/.fossil". Create the database anew if
489 ** it does not already exist.
490 */
491 void db_open_config(void){
492 char *zDbName;
493 const char *zHome = getenv("HOME");
 
 
 
 
 
 
 
 
 
 
 
494 if( zHome==0 ){
495 db_err("cannot local home directory");
496 }
 
 
 
 
497 zDbName = mprintf("%s/.fossil", zHome);
 
498 if( g.configOpen ) return;
499 if( file_size(zDbName)<1024*3 ){
500 db_init_database(zDbName, zConfigSchema, (char*)0);
501 }
502 db_open_or_attach(zDbName, "configdb");
@@ -534,15 +552,19 @@
534 ** it is attached to the open database connection too.
535 */
536 int db_open_local(void){
537 int n;
538 char zPwd[2000];
 
539 if( g.localOpen) return 1;
540 if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
541 db_err("pwd too big: max %d", sizeof(zPwd)-20);
542 }
543 n = strlen(zPwd);
 
 
 
544 while( n>0 ){
545 if( access(zPwd, W_OK) ) break;
546 strcpy(&zPwd[n], "/_FOSSIL_");
547 if( isValidLocalDb(zPwd) ){
548 /* Found a valid _FOSSIL_ file */
549
--- src/db.c
+++ src/db.c
@@ -33,14 +33,16 @@
33 ** (3) A local checkout database named "FOSSIL" and located at the
34 ** root of the local copy of the source tree.
35 **
36 */
37 #include "config.h"
38 #ifndef __MINGW32__
39 # include <pwd.h>
40 #endif
41 #include <sqlite3.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
 
44 #include <unistd.h>
45 #include "db.h"
46
47 #if INTERFACE
48 /*
@@ -488,15 +490,31 @@
490 ** Open the user database in "~/.fossil". Create the database anew if
491 ** it does not already exist.
492 */
493 void db_open_config(void){
494 char *zDbName;
495 const char *zHome;
496 #ifdef __MINGW32__
497 zHome = getenv("LOCALAPPDATA");
498 if( zHome==0 ){
499 zHome = getenv("APPDATA");
500 if( zHome==0 ){
501 zHome = getenv("HOMEPATH");
502 }
503 }
504 #else
505 zHome = getenv("HOME");
506 #endif
507 if( zHome==0 ){
508 db_err("cannot local home directory");
509 }
510 #ifdef __MINGW32__
511 /* . filenames give some window systems problems and many apps problems */
512 zDbName = mprintf("%s/_fossil", zHome);
513 #else
514 zDbName = mprintf("%s/.fossil", zHome);
515 #endif
516 if( g.configOpen ) return;
517 if( file_size(zDbName)<1024*3 ){
518 db_init_database(zDbName, zConfigSchema, (char*)0);
519 }
520 db_open_or_attach(zDbName, "configdb");
@@ -534,15 +552,19 @@
552 ** it is attached to the open database connection too.
553 */
554 int db_open_local(void){
555 int n;
556 char zPwd[2000];
557 char *zPwdConv;
558 if( g.localOpen) return 1;
559 if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
560 db_err("pwd too big: max %d", sizeof(zPwd)-20);
561 }
562 n = strlen(zPwd);
563 zPwdConv = mprintf("%/", zPwd);
564 strncpy(zPwd, zPwdConv, 2000-20);
565 free(zPwdConv);
566 while( n>0 ){
567 if( access(zPwd, W_OK) ) break;
568 strcpy(&zPwd[n], "/_FOSSIL_");
569 if( isValidLocalDb(zPwd) ){
570 /* Found a valid _FOSSIL_ file */
571
+5 -1
--- src/file.c
+++ src/file.c
@@ -105,11 +105,15 @@
105105
if( rc==2 ){
106106
if( !forceFlag ) return 1;
107107
unlink(zName);
108108
}
109109
if( rc!=1 ){
110
+#ifdef __MINGW32__
111
+ return mkdir(zName);
112
+#else
110113
return mkdir(zName, 0755);
114
+#endif
111115
}
112116
return 0;
113117
}
114118
115119
/*
@@ -188,11 +192,11 @@
188192
if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
189193
fprintf(stderr, "pwd too big: max %d\n", sizeof(zPwd)-20);
190194
exit(1);
191195
}
192196
blob_zero(pOut);
193
- blob_appendf(pOut, "%s/%s", zPwd, zOrigName);
197
+ blob_appendf(pOut, "%//%/", zPwd, zOrigName);
194198
}
195199
blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
196200
}
197201
198202
/*
199203
--- src/file.c
+++ src/file.c
@@ -105,11 +105,15 @@
105 if( rc==2 ){
106 if( !forceFlag ) return 1;
107 unlink(zName);
108 }
109 if( rc!=1 ){
 
 
 
110 return mkdir(zName, 0755);
 
111 }
112 return 0;
113 }
114
115 /*
@@ -188,11 +192,11 @@
188 if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
189 fprintf(stderr, "pwd too big: max %d\n", sizeof(zPwd)-20);
190 exit(1);
191 }
192 blob_zero(pOut);
193 blob_appendf(pOut, "%s/%s", zPwd, zOrigName);
194 }
195 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
196 }
197
198 /*
199
--- src/file.c
+++ src/file.c
@@ -105,11 +105,15 @@
105 if( rc==2 ){
106 if( !forceFlag ) return 1;
107 unlink(zName);
108 }
109 if( rc!=1 ){
110 #ifdef __MINGW32__
111 return mkdir(zName);
112 #else
113 return mkdir(zName, 0755);
114 #endif
115 }
116 return 0;
117 }
118
119 /*
@@ -188,11 +192,11 @@
192 if( getcwd(zPwd, sizeof(zPwd)-20)==0 ){
193 fprintf(stderr, "pwd too big: max %d\n", sizeof(zPwd)-20);
194 exit(1);
195 }
196 blob_zero(pOut);
197 blob_appendf(pOut, "%//%/", zPwd, zOrigName);
198 }
199 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut)));
200 }
201
202 /*
203
+148 -10
--- src/http.c
+++ src/http.c
@@ -23,22 +23,55 @@
2323
**
2424
** This file contains code that implements the client-side HTTP protocol
2525
*/
2626
#include "config.h"
2727
#include "http.h"
28
+#ifdef __MINGW32__
29
+# include <windows.h>
30
+# include <winsock2.h>
31
+#else
32
+# include <arpa/inet.h>
33
+# include <sys/socket.h>
34
+# include <netdb.h>
35
+# include <netinet/in.h>
36
+#endif
2837
#include <assert.h>
29
-#include <arpa/inet.h>
3038
#include <sys/types.h>
31
-#include <sys/socket.h>
32
-#include <netdb.h>
33
-#include <netinet/in.h>
3439
#include <signal.h>
3540
3641
/*
3742
** Persistent information about the HTTP connection.
3843
*/
39
-static FILE *pSocket = 0; /* The socket on which we talk to the server */
44
+
45
+#ifdef __MINGW32__
46
+static WSADATA ws_info;
47
+static int pSocket = 0; /* The socket on which we talk to the server on */
48
+#else
49
+static FILE *pSocket = 0; /* The socket filehandle on which we talk to the server */
50
+#endif
51
+
52
+/*
53
+** Winsock must be initialize before use. This helper method allows us to
54
+** always call ws_init in our code regardless of platform but only actually
55
+** initialize winsock on the windows platform.
56
+*/
57
+static void ws_init(){
58
+#ifdef __MINGW32__
59
+ if (WSAStartup(MAKEWORD(2,0), &ws_info) != 0){
60
+ fossil_panic("can't initialize winsock");
61
+ }
62
+#endif
63
+}
64
+
65
+/*
66
+** Like ws_init, winsock must also be cleaned up after.
67
+*/
68
+static void ws_cleanup(){
69
+#ifdef __MINGW32__
70
+ WSACleanup();
71
+#endif
72
+}
4073
4174
/*
4275
** Open a socket connection to the server. Return 0 on success and
4376
** non-zero if an error occurs.
4477
*/
@@ -45,11 +78,14 @@
4578
static int http_open_socket(void){
4679
static struct sockaddr_in addr; /* The server address */
4780
static int addrIsInit = 0; /* True once addr is initialized */
4881
int s;
4982
83
+ ws_init();
84
+
5085
if( !addrIsInit ){
86
+
5187
addr.sin_family = AF_INET;
5288
addr.sin_port = htons(g.urlPort);
5389
*(int*)&addr.sin_addr = inet_addr(g.urlName);
5490
if( -1 == *(int*)&addr.sin_addr ){
5591
#ifndef FOSSIL_STATIC_LINK
@@ -76,14 +112,65 @@
76112
fossil_panic("cannot create a socket");
77113
}
78114
if( connect(s,(struct sockaddr*)&addr,sizeof(addr))<0 ){
79115
fossil_panic("cannot connect to host %s:%d", g.urlName, g.urlPort);
80116
}
117
+#ifdef __MINGW32__
118
+ pSocket = s;
119
+#else
81120
pSocket = fdopen(s,"r+");
82121
signal(SIGPIPE, SIG_IGN);
122
+#endif
83123
return 0;
84124
}
125
+
126
+/*
127
+** Read the socket until a newline '\n' is found. Return the number
128
+** of characters read. pSockId contains the socket handel. pOut
129
+** contains a pointer to the buffer to write to. pOutSize contains
130
+** the maximum size of the line that pOut can handle.
131
+*/
132
+static int socket_recv_line(int pSockId, char* pOut, int pOutSize){
133
+ int received=0;
134
+ char letter;
135
+ memset(pOut,0,pOutSize);
136
+ for(; received<pOutSize-1;received++){
137
+ if( recv(pSockId,(char*)&letter,1,0)>0 ){
138
+ pOut[received]=letter;
139
+ if( letter=='\n' ){
140
+ break;
141
+ }
142
+ }else{
143
+ break;
144
+ }
145
+ }
146
+ return received;
147
+}
148
+
149
+/*
150
+** Initialize a blob to the data on an input socket. return
151
+** the number of bytes read into the blob. Any prior content
152
+** of the blob is discarded, not freed.
153
+**
154
+** The function was placed here in http.c due to it's socket
155
+** nature and we did not want to introduce socket headers into
156
+** the socket netural blob.c file.
157
+*/
158
+int socket_read_blob(Blob *pBlob, int pSockId, int nToRead){
159
+ int i=0,read=0;
160
+ char rbuf[50];
161
+ blob_zero(pBlob);
162
+ while ( i<nToRead ){
163
+ read = recv(pSockId, rbuf, 50, 0);
164
+ i += read;
165
+ if( read<0 ){
166
+ return 0;
167
+ }
168
+ blob_append(pBlob, rbuf, read);
169
+ }
170
+ return blob_size(pBlob);
171
+}
85172
86173
/*
87174
** Make a single attempt to talk to the server. Return TRUE on success
88175
** and FALSE on a failure.
89176
**
@@ -93,40 +180,78 @@
93180
**
94181
** If an error occurs, this routine return false, resets pReply and
95182
** closes the persistent connection, if any.
96183
*/
97184
static int http_send_recv(Blob *pHeader, Blob *pPayload, Blob *pReply){
185
+ int closeConnection=1; /* default to closing the connection */
98186
int rc;
99
- int closeConnection;
100187
int iLength;
101188
int iHttpVersion;
102189
int i;
103190
int nRead;
104191
char zLine[2000];
105192
106193
if( pSocket==0 && http_open_socket() ){
107194
return 0;
108195
}
196
+ iLength = -1;
197
+#ifdef __MINGW32__
198
+ /*
199
+ ** Use recv/send on the windows platform as winsock does not allow
200
+ ** sockets to be used as FILE handles, thus fdopen, fwrite, fgets
201
+ ** does not function on windows for sockets.
202
+ */
203
+ rc = send(pSocket, blob_buffer(pHeader), blob_size(pHeader), 0);
204
+ if( rc!=blob_size(pHeader) ) goto write_err;
205
+ rc = send(pSocket, blob_buffer(pPayload), blob_size(pPayload), 0);
206
+ if( rc!=blob_size(pPayload) ) goto write_err;
207
+
208
+ /* Read the response */
209
+ while( socket_recv_line(pSocket, zLine, 2000) ){
210
+ for( i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++ ){}
211
+ if( i==0 ) break;
212
+ zLine[i] = 0;
213
+ if( strncasecmp(zLine, "http/1.", 7)==0 ){
214
+ if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
215
+ if( rc!=200 ) goto write_err;
216
+ if( iHttpVersion==0 ){
217
+ closeConnection = 1;
218
+ }else{
219
+ closeConnection = 0;
220
+ }
221
+ } else if( strncasecmp(zLine, "content-length:", 15)==0 ){
222
+ iLength = atoi(&zLine[16]);
223
+ }else if( strncasecmp(zLine, "connection:", 11)==0 ){
224
+ for(i=12; isspace(zLine[i]); i++){}
225
+ if( zLine[i]=='c' || zLine[i]=='C' ){
226
+ closeConnection = 1;
227
+ }else if( zLine[i]=='k' || zLine[i]=='K' ){
228
+ closeConnection = 0;
229
+ }
230
+ }
231
+ }
232
+ if( iLength<0 ) goto write_err;
233
+ nRead = socket_read_blob(pReply, pSocket, iLength);
234
+#else
109235
rc = fwrite(blob_buffer(pHeader), 1, blob_size(pHeader), pSocket);
110236
if( rc!=blob_size(pHeader) ) goto write_err;
111237
rc = fwrite(blob_buffer(pPayload), 1, blob_size(pPayload), pSocket);
112238
if( rc!=blob_size(pPayload) ) goto write_err;
113239
if( fflush(pSocket) ) goto write_err;
114240
if( fgets(zLine, sizeof(zLine), pSocket)==0 ) goto write_err;
115241
if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
116242
if( rc!=200 ) goto write_err;
117243
if( iHttpVersion==0 ){
118
- closeConnection = 1;
244
+ closeConnection = 1; /* Connection: close */
119245
}else{
120
- closeConnection = 0;
246
+ closeConnection = 0; /* Connection: keep-alive */
121247
}
122
- iLength = -1;
123248
while( fgets(zLine, sizeof(zLine), pSocket) ){
124249
for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
125250
if( i==0 ) break;
126251
zLine[i] = 0;
127
- if( strncasecmp(zLine, "content-length:",15)==0 ){
252
+ if( strncasecmp(zLine,"content-length:",15)==0 ){
128253
iLength = atoi(&zLine[16]);
129254
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
130255
for(i=12; isspace(zLine[i]); i++){}
131256
if( zLine[i]=='c' || zLine[i]=='C' ){
132257
closeConnection = 1; /* Connection: close */
@@ -135,10 +260,11 @@
135260
}
136261
}
137262
}
138263
if( iLength<0 ) goto write_err;
139264
nRead = blob_read_from_channel(pReply, pSocket, iLength);
265
+#endif
140266
if( nRead!=iLength ){
141267
blob_reset(pReply);
142268
goto write_err;
143269
}
144270
if( closeConnection ){
@@ -260,9 +386,21 @@
260386
/*
261387
** Make sure the socket to the HTTP server is closed
262388
*/
263389
void http_close(void){
264390
if( pSocket ){
391
+#ifdef __MINGW32__
392
+ closesocket(pSocket);
393
+#else
265394
fclose(pSocket);
395
+#endif
266396
pSocket = 0;
267397
}
398
+ /*
399
+ ** This is counter productive. Each time we open a connection we initialize
400
+ ** winsock and then when closing we cleanup. It would be better to
401
+ ** initialize winsock once at application start when we know we are going to
402
+ ** use the socket interface and then cleanup once at application exit when
403
+ ** we are all done with all socket operations.
404
+ */
405
+ ws_cleanup();
268406
}
269407
--- src/http.c
+++ src/http.c
@@ -23,22 +23,55 @@
23 **
24 ** This file contains code that implements the client-side HTTP protocol
25 */
26 #include "config.h"
27 #include "http.h"
 
 
 
 
 
 
 
 
 
28 #include <assert.h>
29 #include <arpa/inet.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netdb.h>
33 #include <netinet/in.h>
34 #include <signal.h>
35
36 /*
37 ** Persistent information about the HTTP connection.
38 */
39 static FILE *pSocket = 0; /* The socket on which we talk to the server */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
41 /*
42 ** Open a socket connection to the server. Return 0 on success and
43 ** non-zero if an error occurs.
44 */
@@ -45,11 +78,14 @@
45 static int http_open_socket(void){
46 static struct sockaddr_in addr; /* The server address */
47 static int addrIsInit = 0; /* True once addr is initialized */
48 int s;
49
 
 
50 if( !addrIsInit ){
 
51 addr.sin_family = AF_INET;
52 addr.sin_port = htons(g.urlPort);
53 *(int*)&addr.sin_addr = inet_addr(g.urlName);
54 if( -1 == *(int*)&addr.sin_addr ){
55 #ifndef FOSSIL_STATIC_LINK
@@ -76,14 +112,65 @@
76 fossil_panic("cannot create a socket");
77 }
78 if( connect(s,(struct sockaddr*)&addr,sizeof(addr))<0 ){
79 fossil_panic("cannot connect to host %s:%d", g.urlName, g.urlPort);
80 }
 
 
 
81 pSocket = fdopen(s,"r+");
82 signal(SIGPIPE, SIG_IGN);
 
83 return 0;
84 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
86 /*
87 ** Make a single attempt to talk to the server. Return TRUE on success
88 ** and FALSE on a failure.
89 **
@@ -93,40 +180,78 @@
93 **
94 ** If an error occurs, this routine return false, resets pReply and
95 ** closes the persistent connection, if any.
96 */
97 static int http_send_recv(Blob *pHeader, Blob *pPayload, Blob *pReply){
 
98 int rc;
99 int closeConnection;
100 int iLength;
101 int iHttpVersion;
102 int i;
103 int nRead;
104 char zLine[2000];
105
106 if( pSocket==0 && http_open_socket() ){
107 return 0;
108 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109 rc = fwrite(blob_buffer(pHeader), 1, blob_size(pHeader), pSocket);
110 if( rc!=blob_size(pHeader) ) goto write_err;
111 rc = fwrite(blob_buffer(pPayload), 1, blob_size(pPayload), pSocket);
112 if( rc!=blob_size(pPayload) ) goto write_err;
113 if( fflush(pSocket) ) goto write_err;
114 if( fgets(zLine, sizeof(zLine), pSocket)==0 ) goto write_err;
115 if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
116 if( rc!=200 ) goto write_err;
117 if( iHttpVersion==0 ){
118 closeConnection = 1;
119 }else{
120 closeConnection = 0;
121 }
122 iLength = -1;
123 while( fgets(zLine, sizeof(zLine), pSocket) ){
124 for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
125 if( i==0 ) break;
126 zLine[i] = 0;
127 if( strncasecmp(zLine, "content-length:",15)==0 ){
128 iLength = atoi(&zLine[16]);
129 }else if( strncasecmp(zLine, "connection:", 11)==0 ){
130 for(i=12; isspace(zLine[i]); i++){}
131 if( zLine[i]=='c' || zLine[i]=='C' ){
132 closeConnection = 1; /* Connection: close */
@@ -135,10 +260,11 @@
135 }
136 }
137 }
138 if( iLength<0 ) goto write_err;
139 nRead = blob_read_from_channel(pReply, pSocket, iLength);
 
140 if( nRead!=iLength ){
141 blob_reset(pReply);
142 goto write_err;
143 }
144 if( closeConnection ){
@@ -260,9 +386,21 @@
260 /*
261 ** Make sure the socket to the HTTP server is closed
262 */
263 void http_close(void){
264 if( pSocket ){
 
 
 
265 fclose(pSocket);
 
266 pSocket = 0;
267 }
 
 
 
 
 
 
 
 
268 }
269
--- src/http.c
+++ src/http.c
@@ -23,22 +23,55 @@
23 **
24 ** This file contains code that implements the client-side HTTP protocol
25 */
26 #include "config.h"
27 #include "http.h"
28 #ifdef __MINGW32__
29 # include <windows.h>
30 # include <winsock2.h>
31 #else
32 # include <arpa/inet.h>
33 # include <sys/socket.h>
34 # include <netdb.h>
35 # include <netinet/in.h>
36 #endif
37 #include <assert.h>
 
38 #include <sys/types.h>
 
 
 
39 #include <signal.h>
40
41 /*
42 ** Persistent information about the HTTP connection.
43 */
44
45 #ifdef __MINGW32__
46 static WSADATA ws_info;
47 static int pSocket = 0; /* The socket on which we talk to the server on */
48 #else
49 static FILE *pSocket = 0; /* The socket filehandle on which we talk to the server */
50 #endif
51
52 /*
53 ** Winsock must be initialize before use. This helper method allows us to
54 ** always call ws_init in our code regardless of platform but only actually
55 ** initialize winsock on the windows platform.
56 */
57 static void ws_init(){
58 #ifdef __MINGW32__
59 if (WSAStartup(MAKEWORD(2,0), &ws_info) != 0){
60 fossil_panic("can't initialize winsock");
61 }
62 #endif
63 }
64
65 /*
66 ** Like ws_init, winsock must also be cleaned up after.
67 */
68 static void ws_cleanup(){
69 #ifdef __MINGW32__
70 WSACleanup();
71 #endif
72 }
73
74 /*
75 ** Open a socket connection to the server. Return 0 on success and
76 ** non-zero if an error occurs.
77 */
@@ -45,11 +78,14 @@
78 static int http_open_socket(void){
79 static struct sockaddr_in addr; /* The server address */
80 static int addrIsInit = 0; /* True once addr is initialized */
81 int s;
82
83 ws_init();
84
85 if( !addrIsInit ){
86
87 addr.sin_family = AF_INET;
88 addr.sin_port = htons(g.urlPort);
89 *(int*)&addr.sin_addr = inet_addr(g.urlName);
90 if( -1 == *(int*)&addr.sin_addr ){
91 #ifndef FOSSIL_STATIC_LINK
@@ -76,14 +112,65 @@
112 fossil_panic("cannot create a socket");
113 }
114 if( connect(s,(struct sockaddr*)&addr,sizeof(addr))<0 ){
115 fossil_panic("cannot connect to host %s:%d", g.urlName, g.urlPort);
116 }
117 #ifdef __MINGW32__
118 pSocket = s;
119 #else
120 pSocket = fdopen(s,"r+");
121 signal(SIGPIPE, SIG_IGN);
122 #endif
123 return 0;
124 }
125
126 /*
127 ** Read the socket until a newline '\n' is found. Return the number
128 ** of characters read. pSockId contains the socket handel. pOut
129 ** contains a pointer to the buffer to write to. pOutSize contains
130 ** the maximum size of the line that pOut can handle.
131 */
132 static int socket_recv_line(int pSockId, char* pOut, int pOutSize){
133 int received=0;
134 char letter;
135 memset(pOut,0,pOutSize);
136 for(; received<pOutSize-1;received++){
137 if( recv(pSockId,(char*)&letter,1,0)>0 ){
138 pOut[received]=letter;
139 if( letter=='\n' ){
140 break;
141 }
142 }else{
143 break;
144 }
145 }
146 return received;
147 }
148
149 /*
150 ** Initialize a blob to the data on an input socket. return
151 ** the number of bytes read into the blob. Any prior content
152 ** of the blob is discarded, not freed.
153 **
154 ** The function was placed here in http.c due to it's socket
155 ** nature and we did not want to introduce socket headers into
156 ** the socket netural blob.c file.
157 */
158 int socket_read_blob(Blob *pBlob, int pSockId, int nToRead){
159 int i=0,read=0;
160 char rbuf[50];
161 blob_zero(pBlob);
162 while ( i<nToRead ){
163 read = recv(pSockId, rbuf, 50, 0);
164 i += read;
165 if( read<0 ){
166 return 0;
167 }
168 blob_append(pBlob, rbuf, read);
169 }
170 return blob_size(pBlob);
171 }
172
173 /*
174 ** Make a single attempt to talk to the server. Return TRUE on success
175 ** and FALSE on a failure.
176 **
@@ -93,40 +180,78 @@
180 **
181 ** If an error occurs, this routine return false, resets pReply and
182 ** closes the persistent connection, if any.
183 */
184 static int http_send_recv(Blob *pHeader, Blob *pPayload, Blob *pReply){
185 int closeConnection=1; /* default to closing the connection */
186 int rc;
 
187 int iLength;
188 int iHttpVersion;
189 int i;
190 int nRead;
191 char zLine[2000];
192
193 if( pSocket==0 && http_open_socket() ){
194 return 0;
195 }
196 iLength = -1;
197 #ifdef __MINGW32__
198 /*
199 ** Use recv/send on the windows platform as winsock does not allow
200 ** sockets to be used as FILE handles, thus fdopen, fwrite, fgets
201 ** does not function on windows for sockets.
202 */
203 rc = send(pSocket, blob_buffer(pHeader), blob_size(pHeader), 0);
204 if( rc!=blob_size(pHeader) ) goto write_err;
205 rc = send(pSocket, blob_buffer(pPayload), blob_size(pPayload), 0);
206 if( rc!=blob_size(pPayload) ) goto write_err;
207
208 /* Read the response */
209 while( socket_recv_line(pSocket, zLine, 2000) ){
210 for( i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++ ){}
211 if( i==0 ) break;
212 zLine[i] = 0;
213 if( strncasecmp(zLine, "http/1.", 7)==0 ){
214 if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
215 if( rc!=200 ) goto write_err;
216 if( iHttpVersion==0 ){
217 closeConnection = 1;
218 }else{
219 closeConnection = 0;
220 }
221 } else if( strncasecmp(zLine, "content-length:", 15)==0 ){
222 iLength = atoi(&zLine[16]);
223 }else if( strncasecmp(zLine, "connection:", 11)==0 ){
224 for(i=12; isspace(zLine[i]); i++){}
225 if( zLine[i]=='c' || zLine[i]=='C' ){
226 closeConnection = 1;
227 }else if( zLine[i]=='k' || zLine[i]=='K' ){
228 closeConnection = 0;
229 }
230 }
231 }
232 if( iLength<0 ) goto write_err;
233 nRead = socket_read_blob(pReply, pSocket, iLength);
234 #else
235 rc = fwrite(blob_buffer(pHeader), 1, blob_size(pHeader), pSocket);
236 if( rc!=blob_size(pHeader) ) goto write_err;
237 rc = fwrite(blob_buffer(pPayload), 1, blob_size(pPayload), pSocket);
238 if( rc!=blob_size(pPayload) ) goto write_err;
239 if( fflush(pSocket) ) goto write_err;
240 if( fgets(zLine, sizeof(zLine), pSocket)==0 ) goto write_err;
241 if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
242 if( rc!=200 ) goto write_err;
243 if( iHttpVersion==0 ){
244 closeConnection = 1; /* Connection: close */
245 }else{
246 closeConnection = 0; /* Connection: keep-alive */
247 }
 
248 while( fgets(zLine, sizeof(zLine), pSocket) ){
249 for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
250 if( i==0 ) break;
251 zLine[i] = 0;
252 if( strncasecmp(zLine,"content-length:",15)==0 ){
253 iLength = atoi(&zLine[16]);
254 }else if( strncasecmp(zLine, "connection:", 11)==0 ){
255 for(i=12; isspace(zLine[i]); i++){}
256 if( zLine[i]=='c' || zLine[i]=='C' ){
257 closeConnection = 1; /* Connection: close */
@@ -135,10 +260,11 @@
260 }
261 }
262 }
263 if( iLength<0 ) goto write_err;
264 nRead = blob_read_from_channel(pReply, pSocket, iLength);
265 #endif
266 if( nRead!=iLength ){
267 blob_reset(pReply);
268 goto write_err;
269 }
270 if( closeConnection ){
@@ -260,9 +386,21 @@
386 /*
387 ** Make sure the socket to the HTTP server is closed
388 */
389 void http_close(void){
390 if( pSocket ){
391 #ifdef __MINGW32__
392 closesocket(pSocket);
393 #else
394 fclose(pSocket);
395 #endif
396 pSocket = 0;
397 }
398 /*
399 ** This is counter productive. Each time we open a connection we initialize
400 ** winsock and then when closing we cleanup. It would be better to
401 ** initialize winsock once at application start when we know we are going to
402 ** use the socket interface and then cleanup once at application exit when
403 ** we are all done with all socket operations.
404 */
405 ws_cleanup();
406 }
407
--- src/login.c
+++ src/login.c
@@ -44,10 +44,14 @@
4444
** logs and downloading diffs of very version of the archive that
4545
** has ever existed, and things like that.
4646
*/
4747
#include "config.h"
4848
#include "login.h"
49
+#ifdef __MINGW32__
50
+# include <windows.h> /* for Sleep */
51
+# define sleep Sleep /* windows does not have sleep, but Sleep */
52
+#endif
4953
#include <time.h>
5054
5155
/*
5256
** Return the name of the login cookie
5357
*/
5458
--- src/login.c
+++ src/login.c
@@ -44,10 +44,14 @@
44 ** logs and downloading diffs of very version of the archive that
45 ** has ever existed, and things like that.
46 */
47 #include "config.h"
48 #include "login.h"
 
 
 
 
49 #include <time.h>
50
51 /*
52 ** Return the name of the login cookie
53 */
54
--- src/login.c
+++ src/login.c
@@ -44,10 +44,14 @@
44 ** logs and downloading diffs of very version of the archive that
45 ** has ever existed, and things like that.
46 */
47 #include "config.h"
48 #include "login.h"
49 #ifdef __MINGW32__
50 # include <windows.h> /* for Sleep */
51 # define sleep Sleep /* windows does not have sleep, but Sleep */
52 #endif
53 #include <time.h>
54
55 /*
56 ** Return the name of the login cookie
57 */
58
+18
--- src/printf.c
+++ src/printf.c
@@ -49,10 +49,11 @@
4949
#define etPOINTER 15 /* The %p conversion */
5050
#define etHTMLIZE 16 /* Make text safe for HTML */
5151
#define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
5252
#define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
5353
#define etFOSSILIZE 19 /* The fossil header encoding format. */
54
+#define etPATH 20 /* Path type */
5455
5556
5657
/*
5758
** An "etByte" is an 8-bit unsigned value.
5859
*/
@@ -109,10 +110,11 @@
109110
{ 'G', 0, 1, etGENERIC, 14, 0 },
110111
{ 'i', 10, 1, etRADIX, 0, 0 },
111112
{ 'n', 0, 0, etSIZE, 0, 0 },
112113
{ '%', 0, 0, etPERCENT, 0, 0 },
113114
{ 'p', 16, 0, etPOINTER, 0, 1 },
115
+ { '/', 0, 0, etPATH, 0, 0 },
114116
};
115117
#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
116118
117119
/*
118120
** "*val" is a double such that 0.1 <= *val < 10.0
@@ -541,10 +543,26 @@
541543
}else{
542544
length =1;
543545
}
544546
bufpt = buf;
545547
break;
548
+ case etPATH: {
549
+ int i;
550
+ char *e = va_arg(ap,char*);
551
+ if( e==0 ){e="";}
552
+ length = strlen(e);
553
+ zExtra = bufpt = malloc(length+1);
554
+ for( i=0; i<length; i++ ){
555
+ if( e[i]=='\\' ){
556
+ bufpt[i]='/';
557
+ }else{
558
+ bufpt[i]=e[i];
559
+ }
560
+ }
561
+ bufpt[length]='\0';
562
+ break;
563
+ }
546564
case etSTRING:
547565
case etDYNSTRING:
548566
bufpt = va_arg(ap,char*);
549567
if( bufpt==0 ){
550568
bufpt = "";
551569
--- src/printf.c
+++ src/printf.c
@@ -49,10 +49,11 @@
49 #define etPOINTER 15 /* The %p conversion */
50 #define etHTMLIZE 16 /* Make text safe for HTML */
51 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
52 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
53 #define etFOSSILIZE 19 /* The fossil header encoding format. */
 
54
55
56 /*
57 ** An "etByte" is an 8-bit unsigned value.
58 */
@@ -109,10 +110,11 @@
109 { 'G', 0, 1, etGENERIC, 14, 0 },
110 { 'i', 10, 1, etRADIX, 0, 0 },
111 { 'n', 0, 0, etSIZE, 0, 0 },
112 { '%', 0, 0, etPERCENT, 0, 0 },
113 { 'p', 16, 0, etPOINTER, 0, 1 },
 
114 };
115 #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
116
117 /*
118 ** "*val" is a double such that 0.1 <= *val < 10.0
@@ -541,10 +543,26 @@
541 }else{
542 length =1;
543 }
544 bufpt = buf;
545 break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
546 case etSTRING:
547 case etDYNSTRING:
548 bufpt = va_arg(ap,char*);
549 if( bufpt==0 ){
550 bufpt = "";
551
--- src/printf.c
+++ src/printf.c
@@ -49,10 +49,11 @@
49 #define etPOINTER 15 /* The %p conversion */
50 #define etHTMLIZE 16 /* Make text safe for HTML */
51 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
52 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
53 #define etFOSSILIZE 19 /* The fossil header encoding format. */
54 #define etPATH 20 /* Path type */
55
56
57 /*
58 ** An "etByte" is an 8-bit unsigned value.
59 */
@@ -109,10 +110,11 @@
110 { 'G', 0, 1, etGENERIC, 14, 0 },
111 { 'i', 10, 1, etRADIX, 0, 0 },
112 { 'n', 0, 0, etSIZE, 0, 0 },
113 { '%', 0, 0, etPERCENT, 0, 0 },
114 { 'p', 16, 0, etPOINTER, 0, 1 },
115 { '/', 0, 0, etPATH, 0, 0 },
116 };
117 #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
118
119 /*
120 ** "*val" is a double such that 0.1 <= *val < 10.0
@@ -541,10 +543,26 @@
543 }else{
544 length =1;
545 }
546 bufpt = buf;
547 break;
548 case etPATH: {
549 int i;
550 char *e = va_arg(ap,char*);
551 if( e==0 ){e="";}
552 length = strlen(e);
553 zExtra = bufpt = malloc(length+1);
554 for( i=0; i<length; i++ ){
555 if( e[i]=='\\' ){
556 bufpt[i]='/';
557 }else{
558 bufpt[i]=e[i];
559 }
560 }
561 bufpt[length]='\0';
562 break;
563 }
564 case etSTRING:
565 case etDYNSTRING:
566 bufpt = va_arg(ap,char*);
567 if( bufpt==0 ){
568 bufpt = "";
569
+40
--- src/user.c
+++ src/user.c
@@ -44,10 +44,50 @@
4444
}
4545
if( z[i]<' ' ) z[i] = ' ';
4646
}
4747
blob_append(pBlob, z, -1);
4848
}
49
+
50
+#ifdef __MINGW32__
51
+/*
52
+** getpass for Windows
53
+*/
54
+static char *getpass(const char *prompt){
55
+ static char pwd[64];
56
+ size_t i;
57
+
58
+ fputs(prompt,stderr);
59
+ fflush(stderr);
60
+ for(i=0; i<sizeof(pwd)-1; ++i){
61
+ pwd[i] = _getch();
62
+ if(pwd[i]=='\r' || pwd[i]=='\n'){
63
+ break;
64
+ }
65
+ /* BS or DEL */
66
+ else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
67
+ i -= 2;
68
+ continue;
69
+ }
70
+ /* CTRL-C */
71
+ else if(pwd[i]==3) {
72
+ i=0;
73
+ break;
74
+ }
75
+ /* ESC */
76
+ else if(pwd[i]==27){
77
+ i=0;
78
+ break;
79
+ }
80
+ else{
81
+ fputc('*',stderr);
82
+ }
83
+ }
84
+ pwd[i]='\0';
85
+ fputs("\n", stderr);
86
+ return pwd;
87
+}
88
+#endif
4989
5090
/*
5191
** Do a single prompt for a passphrase. Store the results in the blob.
5292
*/
5393
static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
5494
5595
ADDED win32.txt
--- src/user.c
+++ src/user.c
@@ -44,10 +44,50 @@
44 }
45 if( z[i]<' ' ) z[i] = ' ';
46 }
47 blob_append(pBlob, z, -1);
48 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
50 /*
51 ** Do a single prompt for a passphrase. Store the results in the blob.
52 */
53 static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
54
55 DDED win32.txt
--- src/user.c
+++ src/user.c
@@ -44,10 +44,50 @@
44 }
45 if( z[i]<' ' ) z[i] = ' ';
46 }
47 blob_append(pBlob, z, -1);
48 }
49
50 #ifdef __MINGW32__
51 /*
52 ** getpass for Windows
53 */
54 static char *getpass(const char *prompt){
55 static char pwd[64];
56 size_t i;
57
58 fputs(prompt,stderr);
59 fflush(stderr);
60 for(i=0; i<sizeof(pwd)-1; ++i){
61 pwd[i] = _getch();
62 if(pwd[i]=='\r' || pwd[i]=='\n'){
63 break;
64 }
65 /* BS or DEL */
66 else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
67 i -= 2;
68 continue;
69 }
70 /* CTRL-C */
71 else if(pwd[i]==3) {
72 i=0;
73 break;
74 }
75 /* ESC */
76 else if(pwd[i]==27){
77 i=0;
78 break;
79 }
80 else{
81 fputc('*',stderr);
82 }
83 }
84 pwd[i]='\0';
85 fputs("\n", stderr);
86 return pwd;
87 }
88 #endif
89
90 /*
91 ** Do a single prompt for a passphrase. Store the results in the blob.
92 */
93 static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
94
95 DDED win32.txt
+30
--- a/win32.txt
+++ b/win32.txt
@@ -0,0 +1,30 @@
1
+Notes: Porting fossil to win32
2
+======================================================================
3
+
4
+Setting up myu have read "Setti:
5
+----------------------------------------------------------------------
6
+
7
+ Install:
8
+ MinGW 5.1.3
9
+ MSYS 1.0.10
10
+
11
+ Download/compile/install zlib (configure --prefix=/mingw)
12
+ Download/compile/install tclsh (configure --All commands were issued in th
13
+
14
+Outstanding Issues:
15
+----------------------------------------------------------------------
16
+
17
+* server is totally non-functional - #if/#end'd out of the code
18
+
19
+
20
+Commands status:
21
+----------------------------------------------------------------------
22
+
23
+add OK
24
+cgi Not tested
25
+changes OK
26
+checkout BAD #1
27
+clean Commands status:
28
+----------------------------------------------------------------------
29
+
30
+add
--- a/win32.txt
+++ b/win32.txt
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/win32.txt
+++ b/win32.txt
@@ -0,0 +1,30 @@
1 Notes: Porting fossil to win32
2 ======================================================================
3
4 Setting up myu have read "Setti:
5 ----------------------------------------------------------------------
6
7 Install:
8 MinGW 5.1.3
9 MSYS 1.0.10
10
11 Download/compile/install zlib (configure --prefix=/mingw)
12 Download/compile/install tclsh (configure --All commands were issued in th
13
14 Outstanding Issues:
15 ----------------------------------------------------------------------
16
17 * server is totally non-functional - #if/#end'd out of the code
18
19
20 Commands status:
21 ----------------------------------------------------------------------
22
23 add OK
24 cgi Not tested
25 changes OK
26 checkout BAD #1
27 clean Commands status:
28 ----------------------------------------------------------------------
29
30 add

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button