OSDN Git Service

Update to 25262d6da000ac0d10f84c5aa75e33166f9fa05b (1.98c).
[ffftp/ffftp.git] / cache.c
1 /*=============================================================================\r
2 *\r
3 *                                                               ファイル一覧キャッシュ\r
4 *\r
5 ===============================================================================\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.\r
7 /\r
8 / Redistribution and use in source and binary forms, with or without \r
9 / modification, are permitted provided that the following conditions \r
10 / are met:\r
11 /\r
12 /  1. Redistributions of source code must retain the above copyright \r
13 /     notice, this list of conditions and the following disclaimer.\r
14 /  2. Redistributions in binary form must reproduce the above copyright \r
15 /     notice, this list of conditions and the following disclaimer in the \r
16 /     documentation and/or other materials provided with the distribution.\r
17 /\r
18 / THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR \r
19 / IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES \r
20 / OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
21 / IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
22 / INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
23 / BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
24 / USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
25 / ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
26 / (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \r
27 / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 /============================================================================*/\r
29 \r
30 #define STRICT\r
31 #include <windows.h>\r
32 #include <stdio.h>\r
33 #include <stdlib.h>\r
34 #include <string.h>\r
35 #include <time.h>\r
36 #include <mbstring.h>\r
37 #include <malloc.h>\r
38 #include <windowsx.h>\r
39 #include <commctrl.h>\r
40 \r
41 #include <stdarg.h>\r
42 \r
43 #include "common.h"\r
44 #include "resource.h"\r
45 \r
46 \r
47 \r
48 \r
49 static BOOL CALLBACK CountPrevFfftpWindowsProc(HWND hWnd, LPARAM lParam);\r
50 \r
51 \r
52 \r
53 /*===== キャッシュデータのストラクチャ =====*/\r
54 \r
55 typedef struct {\r
56         time_t Time;                                            /* リストに登録した時間 */\r
57         char HostAdrs[HOST_ADRS_LEN+1];         /* ホストのアドレス */\r
58         char UserName[USER_NAME_LEN+1];         /* ユーザ名 */\r
59         char Path[FMAX_PATH+1];                         /* パス名 */\r
60 } CACHELIST;\r
61 \r
62 /*===== ローカルなワーク =====*/\r
63 \r
64 static CACHELIST *RemoteCache = NULL;   /* キャッシュデータ */\r
65 static int TmpCacheEntry = 0;                   /* キャッシュされているデータの数 */\r
66 static int LastNum;                                             /* 現在表示しているデータの番号 */\r
67 static int ProgNum;                                             /* FFFTPの起動番号 */\r
68 \r
69 \r
70 /*----- ファイル一覧キャッシュを作成する --------------------------------------\r
71 *\r
72 *       Parameter\r
73 *               int Num : キャッシュ可能個数\r
74 *\r
75 *       Return Value\r
76 *               int ステータス\r
77 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
78 *----------------------------------------------------------------------------*/\r
79 \r
80 int MakeCacheBuf(int Num)\r
81 {\r
82         int Sts;\r
83         int i;\r
84 \r
85         Sts = FFFTP_SUCCESS;\r
86         if(Num > 0)\r
87         {\r
88                 Sts = FFFTP_FAIL;\r
89                 if((RemoteCache = malloc(sizeof(CACHELIST) * Num)) != NULL)\r
90                 {\r
91                         TmpCacheEntry = Num;\r
92                         for(i = 0; i < TmpCacheEntry; i++)\r
93                                 ClearCache(i);\r
94                         Sts = FFFTP_SUCCESS;\r
95                 }\r
96         }\r
97         return(Sts);\r
98 }\r
99 \r
100 \r
101 /*----- ファイル一覧キャッシュを削除する --------------------------------------\r
102 *\r
103 *       Parameter\r
104 *               なし\r
105 *\r
106 *       Return Value\r
107 *               なし\r
108 *----------------------------------------------------------------------------*/\r
109 \r
110 void DeleteCacheBuf(void)\r
111 {\r
112         if(RemoteCache != NULL)\r
113                 free(RemoteCache);\r
114         RemoteCache = NULL;\r
115         TmpCacheEntry = 0;\r
116         return;\r
117 }\r
118 \r
119 \r
120 /*----- パスがキャッシュされているかどうかを返す ------------------------------\r
121 *\r
122 *       Parameter\r
123 *               char *Path : パス名\r
124 *\r
125 *       Return Value\r
126 *               int キャッシュデータの番号\r
127 *                       -1 = キャッシュされていない\r
128 *----------------------------------------------------------------------------*/\r
129 \r
130 int AskCached(char *Path)\r
131 {\r
132         int Ret;\r
133         int i;\r
134         CACHELIST *Pos;\r
135 \r
136         Ret = -1;\r
137         if(TmpCacheEntry > 0)\r
138         {\r
139                 Pos = RemoteCache;\r
140                 for(i = 0; i < TmpCacheEntry; i++)\r
141                 {\r
142                         if((_stricmp(AskHostAdrs(), Pos->HostAdrs) == 0) &&\r
143                            (strcmp(AskHostUserName(), Pos->UserName) == 0) &&\r
144                            (strcmp(Path, Pos->Path) == 0))\r
145                         {\r
146                                 time(&(Pos->Time));             /* Refresh */\r
147                                 Ret = i;\r
148 //                              DoPrintf("Filelist cache found. (%d)", Ret);\r
149                                 break;\r
150                         }\r
151                         Pos++;\r
152                 }\r
153         }\r
154         return(Ret);\r
155 }\r
156 \r
157 \r
158 /*----- 未使用のキャッシュデータ番号を返す ------------------------------------\r
159 *\r
160 *       Parameter\r
161 *               なし\r
162 *\r
163 *       Return Value\r
164 *               int 未使用のキャッシュデータ番号\r
165 *\r
166 *       Note\r
167 *               未使用の物が無い時は、一番古いものに上書きする\r
168 *----------------------------------------------------------------------------*/\r
169 \r
170 int AskFreeCache(void)\r
171 {\r
172         int Ret;\r
173         int i;\r
174         time_t Oldest;\r
175         CACHELIST *Pos;\r
176 \r
177         Ret = 0;\r
178         if(TmpCacheEntry > 0)\r
179         {\r
180                 Oldest = 0;\r
181                 Ret = -1;\r
182                 Pos = RemoteCache;\r
183                 for(i = 0; i < TmpCacheEntry; i++)\r
184                 {\r
185                         if(strlen(Pos->Path) == 0)\r
186                         {\r
187                                 Ret = i;\r
188                                 break;\r
189                         }\r
190                         else\r
191                         {\r
192                                 if((Ret == -1) || (Pos->Time < Oldest))\r
193                                 {\r
194                                         Oldest = Pos->Time;\r
195                                         Ret = i;\r
196                                 }\r
197                         }\r
198                         Pos++;\r
199                 }\r
200         }\r
201 //      DoPrintf("Set filelist cache. (%d)", Ret);\r
202         return(Ret);\r
203 }\r
204 \r
205 \r
206 /*----- キャッシュデータをセットする ------------------------------------------\r
207 *\r
208 *       Parameter\r
209 *               int Num : キャッシュデータ番号\r
210 *               char *Path : パス名\r
211 *\r
212 *       Return Value\r
213 *               なし\r
214 *\r
215 *       Note\r
216 *               現在接続中のホスト名を使用する\r
217 *----------------------------------------------------------------------------*/\r
218 \r
219 void SetCache(int Num, char *Path)\r
220 {\r
221         if(TmpCacheEntry > 0)\r
222         {\r
223                 strcpy((RemoteCache + Num)->HostAdrs, AskHostAdrs());\r
224                 strcpy((RemoteCache + Num)->UserName, AskHostUserName());\r
225                 strcpy((RemoteCache + Num)->Path, Path);\r
226                 time(&((RemoteCache + Num)->Time));\r
227         }\r
228         return;\r
229 }\r
230 \r
231 \r
232 /*----- キャッシュデータをクリアする ------------------------------------------\r
233 *\r
234 *       Parameter\r
235 *               int Num : キャッシュデータ番号\r
236 *\r
237 *       Return Value\r
238 *               なし\r
239 *----------------------------------------------------------------------------*/\r
240 \r
241 void ClearCache(int Num)\r
242 {\r
243         if(TmpCacheEntry > 0)\r
244         {\r
245                 strcpy((RemoteCache + Num)->HostAdrs, "");\r
246                 strcpy((RemoteCache + Num)->UserName, "");\r
247                 strcpy((RemoteCache + Num)->Path, "");\r
248                 (RemoteCache + Num)->Time = 0;\r
249         }\r
250         return;\r
251 }\r
252 \r
253 \r
254 /*----- 現在表示中のキャッシュデータ番号を返す --------------------------------\r
255 *\r
256 *       Parameter\r
257 *               なし\r
258 *\r
259 *       Return Value\r
260 *               int キャッシュデータ番号\r
261 *----------------------------------------------------------------------------*/\r
262 \r
263 int AskCurrentFileListNum(void)\r
264 {\r
265         return(LastNum);\r
266 }\r
267 \r
268 \r
269 /*----- 現在表示中のキャッシュデータ番号をセットする --------------------------\r
270 *\r
271 *       Parameter\r
272 *               int Num : キャッシュデータ番号\r
273 *\r
274 *       Return Value\r
275 *               なし\r
276 *----------------------------------------------------------------------------*/\r
277 \r
278 void SetCurrentFileListNum(int Num)\r
279 {\r
280         LastNum = Num;\r
281 }\r
282 \r
283 \r
284 /*----- キャッシュデータを保存する --------------------------------------------\r
285 *\r
286 *       Parameter\r
287 *               なし\r
288 *\r
289 *       Return Value\r
290 *               なし\r
291 *\r
292 *       Note\r
293 *               キャッシュデータそのものはファイルになっているので、ここではインデック\r
294 *               スファイルを作成する。\r
295 *               また、不要なファイルは削除する。\r
296 *----------------------------------------------------------------------------*/\r
297 \r
298 void SaveCache(void)\r
299 {\r
300         char Buf[FMAX_PATH+1];\r
301         FILE *fd;\r
302         CACHELIST *Pos;\r
303         int i;\r
304 \r
305         if(ProgNum == 0)        /* 最初のインスタンスだけがキャッシュを保存できる */\r
306         {\r
307                 if(TmpCacheEntry > 0)\r
308                 {\r
309                         strcpy(Buf, AskTmpFilePath());\r
310                         SetYenTail(Buf);\r
311                         strcat(Buf, "_ffftp.idx");\r
312                         if((fd = fopen(Buf, "wt"))!=NULL)\r
313                         {\r
314                                 Pos = RemoteCache;\r
315                                 for(i = 0; i < TmpCacheEntry; i++)\r
316                                 {\r
317                                         if(strlen(Pos->Path) != 0)\r
318                                                 fprintf(fd, "%s %s %s %ld\n", Pos->HostAdrs, Pos->UserName, Pos->Path, Pos->Time);\r
319                                         Pos++;\r
320                                 }\r
321                                 fclose(fd);\r
322                         }\r
323                 }\r
324         }\r
325         else\r
326                 DeleteCache();\r
327 \r
328         MakeCacheFileName(998, Buf);\r
329         _unlink(Buf);\r
330 \r
331         MakeCacheFileName(999, Buf);\r
332         _unlink(Buf);\r
333 \r
334         return;\r
335 }\r
336 \r
337 \r
338 /*----- キャッシュデータを読み込む --------------------------------------------\r
339 *\r
340 *       Parameter\r
341 *               なし\r
342 *\r
343 *       Return Value\r
344 *               なし\r
345 *----------------------------------------------------------------------------*/\r
346 \r
347 void LoadCache(void)\r
348 {\r
349         char Buf[FMAX_PATH+1];\r
350         FILE *fd;\r
351         CACHELIST *Pos;\r
352         int Num;\r
353 \r
354         if(ProgNum == 0)        /* 最初のインスタンスだけがキャッシュを保存できる */\r
355         {\r
356                 if(TmpCacheEntry > 0)\r
357                 {\r
358                         strcpy(Buf, AskTmpFilePath());\r
359                         SetYenTail(Buf);\r
360                         strcat(Buf, "_ffftp.idx");\r
361                         if((fd = fopen(Buf, "rt"))!=NULL)\r
362                         {\r
363                                 Pos = RemoteCache;\r
364                                 Num = 0;\r
365                                 while(Num < TmpCacheEntry)\r
366                                 {\r
367                                         if(fgets(Buf, FMAX_PATH, fd) == NULL)\r
368                                                 break;\r
369 \r
370                                         if(sscanf(Buf, "%s %s %s %ld\n", Pos->HostAdrs, Pos->UserName, Pos->Path, &(Pos->Time)) == 4)\r
371                                         {\r
372                                                 Pos++;\r
373                                                 Num++;\r
374                                         }\r
375                                         else\r
376                                                 ClearCache(Num);\r
377                                 }\r
378                                 fclose(fd);\r
379                         }\r
380                 }\r
381         }\r
382         return;\r
383 }\r
384 \r
385 \r
386 /*----- キャッシュデータを全て削除する ----------------------------------------\r
387 *\r
388 *       Parameter\r
389 *               なし\r
390 *\r
391 *       Return Value\r
392 *               なし\r
393 *----------------------------------------------------------------------------*/\r
394 \r
395 void DeleteCache(void)\r
396 {\r
397         char Buf[FMAX_PATH+1];\r
398         int i;\r
399 \r
400         if(ProgNum == 0)\r
401         {\r
402                 strcpy(Buf, AskTmpFilePath());\r
403                 SetYenTail(Buf);\r
404                 strcat(Buf, "_ffftp.idx");\r
405                 _unlink(Buf);\r
406         }\r
407 \r
408         for(i = 0; i <= TmpCacheEntry; i++)\r
409         {\r
410                 MakeCacheFileName(i, Buf);\r
411                 _unlink(Buf);\r
412         }\r
413 \r
414         MakeCacheFileName(998, Buf);\r
415         _unlink(Buf);\r
416 \r
417         MakeCacheFileName(999, Buf);\r
418         _unlink(Buf);\r
419 \r
420         return;\r
421 }\r
422 \r
423 \r
424 /*----- キャッシュのファイル名を作成する --------------------------------------\r
425 *\r
426 *       Parameter\r
427 *               int Num : キャッシュデータ番号\r
428 *               char *Buf : ファイル名を格納するバッファ\r
429 *\r
430 *       Return Value\r
431 *               なし\r
432 *----------------------------------------------------------------------------*/\r
433 \r
434 void MakeCacheFileName(int Num, char *Buf)\r
435 {\r
436         char Prog[10];\r
437         char *Pos;\r
438 \r
439         strcpy(Buf, AskTmpFilePath());\r
440         SetYenTail(Buf);\r
441         Pos = strchr(Buf, NUL);\r
442 \r
443         strcpy(Prog, "");\r
444         if(ProgNum > 0)\r
445                 sprintf(Prog, ".%d", ProgNum);\r
446 \r
447         sprintf(Pos, "_ffftp.%03d%s", Num, Prog);\r
448         return;\r
449 }\r
450 \r
451 \r
452 /*----- 起動しているFFFTPの数を数える ------------------------------------------\r
453 *\r
454 *       Parameter\r
455 *               なし\r
456 *\r
457 *       Return Value\r
458 *               なし\r
459 *\r
460 *       Note\r
461 *               個数はProgNumに格納する\r
462 *----------------------------------------------------------------------------*/\r
463 \r
464 void CountPrevFfftpWindows(void)\r
465 {\r
466         ProgNum = 0;\r
467         EnumWindows(CountPrevFfftpWindowsProc, 0);\r
468         return;\r
469 }\r
470 \r
471 \r
472 /*----- 起動しているFFFTPの数を数えるコールバック-------------------------------\r
473 *\r
474 *       Parameter\r
475 *               HWND hWnd : ウインドウハンドル\r
476 *               LPARAM lParam : パラメータ\r
477 *\r
478 *       Return Value\r
479 *               BOOL TRUE/FALSE\r
480 *----------------------------------------------------------------------------*/\r
481 \r
482 static BOOL CALLBACK CountPrevFfftpWindowsProc(HWND hWnd, LPARAM lParam)\r
483 {\r
484         char Buf[FMAX_PATH+1];\r
485 \r
486         if(GetClassName(hWnd, Buf, FMAX_PATH) > 0)\r
487         {\r
488                 if(strcmp(Buf, "FFFTPWin") == 0)\r
489                         ProgNum++;\r
490         }\r
491         return(TRUE);\r
492 }\r
493 \r
494 \r
495 \r