Mercurial > gftp.yaz
annotate lib/local.c @ 992:9c583f570950 default tip
more character set conversion on remote file names.
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Wed, 15 Sep 2010 11:42:57 +0900 |
parents | c99b134c6185 |
children |
rev | line source |
---|---|
1 | 1 /*****************************************************************************/ |
2 /* local.c - functions that will use the local system */ | |
885 | 3 /* Copyright (C) 1998-2007 Brian Masney <masneyb@gftp.org> */ |
1 | 4 /* */ |
5 /* This program is free software; you can redistribute it and/or modify */ | |
6 /* it under the terms of the GNU General Public License as published by */ | |
7 /* the Free Software Foundation; either version 2 of the License, or */ | |
8 /* (at your option) any later version. */ | |
9 /* */ | |
10 /* This program is distributed in the hope that it will be useful, */ | |
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ | |
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ | |
13 /* GNU General Public License for more details. */ | |
14 /* */ | |
15 /* You should have received a copy of the GNU General Public License */ | |
16 /* along with this program; if not, write to the Free Software */ | |
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */ | |
18 /*****************************************************************************/ | |
19 | |
20 #include "gftp.h" | |
33 | 21 static const char cvsid[] = "$Id$"; |
1 | 22 |
23 typedef struct local_protocol_data_tag | |
24 { | |
25 DIR *dir; | |
26 GHashTable *userhash, *grouphash; | |
27 } local_protocol_data; | |
28 | |
29 | |
48 | 30 static void |
787 | 31 local_remove_key (gpointer key, gpointer value, gpointer user_data) |
1 | 32 { |
48 | 33 g_free (value); |
1 | 34 } |
35 | |
36 | |
37 static void | |
38 local_destroy (gftp_request * request) | |
39 { | |
40 local_protocol_data * lpd; | |
41 | |
42 g_return_if_fail (request != NULL); | |
43 g_return_if_fail (request->protonum == GFTP_LOCAL_NUM); | |
44 | |
45 lpd = request->protocol_data; | |
46 g_hash_table_foreach (lpd->userhash, local_remove_key, NULL); | |
47 g_hash_table_destroy (lpd->userhash); | |
48 g_hash_table_foreach (lpd->grouphash, local_remove_key, NULL); | |
49 g_hash_table_destroy (lpd->grouphash); | |
50 lpd->userhash = lpd->grouphash = NULL; | |
51 } | |
52 | |
53 | |
54 static int | |
831 | 55 local_getcwd (gftp_request * request) |
56 { | |
57 char tempstr[PATH_MAX], *utf8; | |
838 | 58 size_t destlen; |
831 | 59 |
60 if (request->directory != NULL) | |
61 g_free (request->directory); | |
62 | |
63 if (getcwd (tempstr, sizeof (tempstr)) == NULL) | |
64 { | |
65 request->logging_function (gftp_logging_error, request, | |
66 _("Could not get current working directory: %s\n"), | |
67 g_strerror (errno)); | |
68 request->directory = NULL; | |
69 return (GFTP_ERETRYABLE); | |
70 } | |
71 | |
845 | 72 utf8 = gftp_filename_to_utf8 (request, tempstr, &destlen); |
831 | 73 if (utf8 != NULL) |
74 request->directory = utf8; | |
75 else | |
76 request->directory = g_strdup (tempstr); | |
77 | |
78 return (0); | |
79 } | |
80 | |
81 | |
82 static int | |
83 local_chdir (gftp_request * request, const char *directory) | |
84 { | |
838 | 85 size_t destlen; |
831 | 86 char *utf8; |
87 int ret; | |
88 | |
89 g_return_val_if_fail (request != NULL, GFTP_EFATAL); | |
90 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
91 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
92 | |
845 | 93 utf8 = gftp_filename_from_utf8 (request, directory, &destlen); |
831 | 94 if (utf8 != NULL) |
95 { | |
96 ret = chdir (utf8); | |
97 g_free (utf8); | |
98 } | |
99 else | |
100 ret = chdir (directory); | |
101 | |
102 if (ret == 0) | |
103 { | |
104 request->logging_function (gftp_logging_misc, request, | |
105 _("Successfully changed local directory to %s\n"), | |
106 directory); | |
107 ret = local_getcwd (request); | |
108 } | |
109 else | |
110 { | |
111 request->logging_function (gftp_logging_error, request, | |
112 _("Could not change local directory to %s: %s\n"), | |
113 directory, g_strerror (errno)); | |
114 ret = GFTP_ERETRYABLE; | |
115 } | |
116 | |
117 return (ret); | |
118 } | |
119 | |
120 | |
121 static int | |
1 | 122 local_connect (gftp_request * request) |
123 { | |
84 | 124 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
125 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
1 | 126 |
510 | 127 if (request->directory != NULL) |
831 | 128 return (local_chdir (request, request->directory)); |
1 | 129 else |
831 | 130 return (local_getcwd (request)); |
1 | 131 } |
132 | |
133 | |
134 static void | |
135 local_disconnect (gftp_request * request) | |
136 { | |
137 g_return_if_fail (request != NULL); | |
138 g_return_if_fail (request->protonum == GFTP_LOCAL_NUM); | |
139 | |
58 | 140 if (request->datafd != -1) |
1 | 141 { |
87 | 142 if (close (request->datafd) == -1) |
186 | 143 request->logging_function (gftp_logging_error, request, |
1 | 144 _("Error closing file descriptor: %s\n"), |
145 g_strerror (errno)); | |
58 | 146 request->datafd = -1; |
1 | 147 } |
148 } | |
149 | |
150 | |
58 | 151 static off_t |
895 | 152 local_get_file (gftp_request * request, const char *filename, |
1 | 153 off_t startsize) |
154 { | |
838 | 155 size_t destlen; |
831 | 156 char *utf8; |
58 | 157 off_t size; |
158 int flags; | |
1 | 159 |
84 | 160 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
161 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
162 g_return_val_if_fail (filename != NULL, GFTP_EFATAL); | |
1 | 163 |
895 | 164 flags = O_RDONLY; |
434 | 165 #if defined (_LARGEFILE_SOURCE) && defined (O_LARGEFILE) |
895 | 166 flags |= O_LARGEFILE; |
7 | 167 #endif |
168 | |
895 | 169 utf8 = gftp_filename_from_utf8 (request, filename, &destlen); |
170 if (utf8 != NULL) | |
171 { | |
172 request->datafd = gftp_fd_open (request, utf8, flags, 0); | |
173 g_free (utf8); | |
1 | 174 } |
175 else | |
895 | 176 request->datafd = gftp_fd_open (request, filename, flags, 0); |
177 | |
178 if (request->datafd == -1) | |
179 return (GFTP_ERETRYABLE); | |
1 | 180 |
87 | 181 if ((size = lseek (request->datafd, 0, SEEK_END)) == -1) |
1 | 182 { |
186 | 183 request->logging_function (gftp_logging_error, request, |
1 | 184 _("Error: Cannot seek on file %s: %s\n"), |
185 filename, g_strerror (errno)); | |
58 | 186 gftp_disconnect (request); |
84 | 187 return (GFTP_ERETRYABLE); |
1 | 188 } |
189 | |
87 | 190 if (lseek (request->datafd, startsize, SEEK_SET) == -1) |
1 | 191 { |
186 | 192 request->logging_function (gftp_logging_error, request, |
1 | 193 _("Error: Cannot seek on file %s: %s\n"), |
194 filename, g_strerror (errno)); | |
58 | 195 gftp_disconnect (request); |
84 | 196 return (GFTP_ERETRYABLE); |
1 | 197 } |
198 | |
199 return (size); | |
200 } | |
201 | |
202 | |
203 static int | |
895 | 204 local_put_file (gftp_request * request, const char *filename, |
787 | 205 off_t startsize, off_t totalsize) |
1 | 206 { |
831 | 207 int flags, perms; |
838 | 208 size_t destlen; |
831 | 209 char *utf8; |
1 | 210 |
84 | 211 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
212 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
213 g_return_val_if_fail (filename != NULL, GFTP_EFATAL); | |
1 | 214 |
895 | 215 flags = O_WRONLY | O_CREAT; |
216 if (startsize > 0) | |
217 flags |= O_APPEND; | |
434 | 218 #if defined (_LARGEFILE_SOURCE) && defined (O_LARGEFILE) |
895 | 219 flags |= O_LARGEFILE; |
7 | 220 #endif |
221 | |
895 | 222 perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
223 utf8 = gftp_filename_from_utf8 (request, filename, &destlen); | |
224 if (utf8 != NULL) | |
225 { | |
226 request->datafd = gftp_fd_open (request, utf8, flags, perms); | |
227 g_free (utf8); | |
1 | 228 } |
229 else | |
895 | 230 request->datafd = gftp_fd_open (request, filename, flags, perms); |
231 | |
232 if (request->datafd == -1) | |
233 return (GFTP_ERETRYABLE); | |
1 | 234 |
87 | 235 if (ftruncate (request->datafd, startsize) == -1) |
1 | 236 { |
186 | 237 request->logging_function (gftp_logging_error, request, |
1 | 238 _("Error: Cannot truncate local file %s: %s\n"), |
239 filename, g_strerror (errno)); | |
58 | 240 gftp_disconnect (request); |
84 | 241 return (GFTP_ERETRYABLE); |
1 | 242 } |
243 | |
87 | 244 if (lseek (request->datafd, startsize, SEEK_SET) == -1) |
1 | 245 { |
186 | 246 request->logging_function (gftp_logging_error, request, |
1 | 247 _("Error: Cannot seek on file %s: %s\n"), |
248 filename, g_strerror (errno)); | |
58 | 249 gftp_disconnect (request); |
84 | 250 return (GFTP_ERETRYABLE); |
1 | 251 } |
252 return (0); | |
253 } | |
254 | |
255 | |
256 static int | |
257 local_end_transfer (gftp_request * request) | |
258 { | |
259 local_protocol_data * lpd; | |
260 | |
261 lpd = request->protocol_data; | |
262 if (lpd->dir) | |
263 { | |
264 closedir (lpd->dir); | |
265 lpd->dir = NULL; | |
266 } | |
267 | |
58 | 268 if (request->datafd > 0) |
1 | 269 { |
87 | 270 if (close (request->datafd) == -1) |
186 | 271 request->logging_function (gftp_logging_error, request, |
1 | 272 _("Error closing file descriptor: %s\n"), |
273 g_strerror (errno)); | |
274 | |
58 | 275 request->datafd = -1; |
1 | 276 } |
277 | |
278 return (0); | |
279 } | |
280 | |
281 | |
520 | 282 static int |
787 | 283 local_stat_filename (gftp_request * request, const char *filename, |
284 mode_t * mode, off_t * filesize) | |
500 | 285 { |
286 struct stat st; | |
838 | 287 size_t destlen; |
831 | 288 char *utf8; |
289 int ret; | |
500 | 290 |
845 | 291 utf8 = gftp_filename_from_utf8 (request, filename, &destlen); |
831 | 292 if (utf8 != NULL) |
293 { | |
294 ret = stat (utf8, &st); | |
295 g_free (utf8); | |
296 } | |
297 else | |
298 ret = stat (filename, &st); | |
299 | |
300 if (ret != 0) | |
500 | 301 return (GFTP_ERETRYABLE); |
302 | |
520 | 303 *mode = st.st_mode; |
787 | 304 *filesize = st.st_size; |
305 | |
520 | 306 return (0); |
500 | 307 } |
308 | |
309 | |
1 | 310 static int |
58 | 311 local_get_next_file (gftp_request * request, gftp_file * fle, int fd) |
1 | 312 { |
313 local_protocol_data * lpd; | |
255 | 314 struct stat st, fst; |
1 | 315 struct dirent *dirp; |
316 char *user, *group; | |
317 struct passwd *pw; | |
318 struct group *gr; | |
319 | |
320 /* the struct passwd and struct group are not thread safe. But, | |
321 we're ok here because I have threading turned off for the local | |
341 | 322 protocol (see use_threads in gftp_protocols in options.h) */ |
84 | 323 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
324 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
325 g_return_val_if_fail (fle != NULL, GFTP_EFATAL); | |
1 | 326 |
327 lpd = request->protocol_data; | |
87 | 328 |
329 g_return_val_if_fail (lpd != NULL, GFTP_EFATAL); | |
330 | |
1 | 331 memset (fle, 0, sizeof (*fle)); |
332 | |
333 if ((dirp = readdir (lpd->dir)) == NULL) | |
334 { | |
335 closedir (lpd->dir); | |
336 lpd->dir = NULL; | |
274 | 337 return (GFTP_EFATAL); |
1 | 338 } |
339 | |
87 | 340 fle->file = g_strdup (dirp->d_name); |
1 | 341 if (lstat (fle->file, &st) != 0) |
274 | 342 return (GFTP_ERETRYABLE); |
1 | 343 |
255 | 344 if (stat (fle->file, &fst) != 0) |
274 | 345 return (GFTP_ERETRYABLE); |
255 | 346 |
1 | 347 if ((user = g_hash_table_lookup (lpd->userhash, |
348 GUINT_TO_POINTER(st.st_uid))) != NULL) | |
87 | 349 fle->user = g_strdup (user); |
1 | 350 else |
351 { | |
352 if ((pw = getpwuid (st.st_uid)) == NULL) | |
353 fle->user = g_strdup_printf ("%u", st.st_uid); | |
354 else | |
87 | 355 fle->user = g_strdup (pw->pw_name); |
1 | 356 |
87 | 357 user = g_strdup (fle->user); |
1 | 358 g_hash_table_insert (lpd->userhash, GUINT_TO_POINTER (st.st_uid), user); |
359 } | |
360 | |
361 if ((group = g_hash_table_lookup (lpd->grouphash, | |
362 GUINT_TO_POINTER(st.st_gid))) != NULL) | |
87 | 363 fle->group = g_strdup (group); |
1 | 364 else |
365 { | |
366 if ((gr = getgrgid (st.st_gid)) == NULL) | |
367 fle->group = g_strdup_printf ("%u", st.st_gid); | |
368 else | |
87 | 369 fle->group = g_strdup (gr->gr_name); |
1 | 370 |
87 | 371 group = g_strdup (fle->group); |
1 | 372 g_hash_table_insert (lpd->grouphash, GUINT_TO_POINTER (st.st_gid), group); |
373 } | |
374 | |
852 | 375 fle->st_dev = fst.st_dev; |
376 fle->st_ino = fst.st_ino; | |
499 | 377 fle->st_mode = fst.st_mode; |
1 | 378 fle->datetime = st.st_mtime; |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
379 |
499 | 380 if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode)) |
48 | 381 fle->size = (off_t) st.st_rdev; |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
382 else |
294 | 383 fle->size = fst.st_size; |
1 | 384 |
385 return (1); | |
386 } | |
387 | |
388 | |
389 static int | |
390 local_list_files (gftp_request * request) | |
391 { | |
392 local_protocol_data *lpd; | |
843 | 393 char *dir, *utf8; |
838 | 394 size_t destlen; |
1 | 395 |
84 | 396 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
87 | 397 g_return_val_if_fail (request->directory != NULL, GFTP_EFATAL); |
84 | 398 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); |
87 | 399 |
1 | 400 lpd = request->protocol_data; |
401 | |
87 | 402 g_return_val_if_fail (lpd != NULL, GFTP_EFATAL); |
403 | |
843 | 404 if (request->directory[strlen (request->directory) - 1] != '/') |
405 dir = g_strconcat (request->directory, "/", NULL); | |
406 else | |
407 dir = request->directory; | |
831 | 408 |
845 | 409 utf8 = gftp_filename_from_utf8 (request, dir, &destlen); |
843 | 410 if (utf8 != NULL) |
87 | 411 { |
843 | 412 lpd->dir = opendir (utf8); |
413 g_free (utf8); | |
87 | 414 } |
415 else | |
843 | 416 lpd->dir = opendir (dir); |
1 | 417 |
843 | 418 if (dir != request->directory) |
419 g_free (dir); | |
420 | |
421 if (lpd->dir == NULL) | |
1 | 422 { |
186 | 423 request->logging_function (gftp_logging_error, request, |
1 | 424 _("Could not get local directory listing %s: %s\n"), |
843 | 425 request->directory, g_strerror (errno)); |
426 return (GFTP_ERETRYABLE); | |
1 | 427 } |
831 | 428 else |
843 | 429 return (0); |
1 | 430 } |
431 | |
432 | |
433 static off_t | |
787 | 434 local_get_file_size (gftp_request * request, const char *filename) |
1 | 435 { |
436 struct stat st; | |
838 | 437 size_t destlen; |
831 | 438 char *utf8; |
439 int ret; | |
1 | 440 |
845 | 441 utf8 = gftp_filename_from_utf8 (request, filename, &destlen); |
831 | 442 if (utf8 != NULL) |
1 | 443 { |
831 | 444 ret = stat (utf8, &st); |
445 g_free (utf8); | |
1 | 446 } |
87 | 447 else |
831 | 448 ret = stat (filename, &st); |
449 | |
450 if (ret == -1) | |
451 return (GFTP_ERETRYABLE); | |
452 | |
453 return (st.st_size); | |
1 | 454 } |
455 | |
456 | |
457 static int | |
458 local_rmdir (gftp_request * request, const char *directory) | |
459 { | |
838 | 460 size_t destlen; |
831 | 461 char *utf8; |
462 int ret; | |
463 | |
84 | 464 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
465 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
466 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
1 | 467 |
845 | 468 utf8 = gftp_filename_from_utf8 (request, directory, &destlen); |
831 | 469 if (utf8 != NULL) |
470 { | |
471 ret = rmdir (utf8); | |
472 g_free (utf8); | |
473 } | |
474 else | |
475 ret = rmdir (directory); | |
476 | |
477 if (ret == 0) | |
1 | 478 { |
186 | 479 request->logging_function (gftp_logging_misc, request, |
1 | 480 _("Successfully removed %s\n"), directory); |
481 return (0); | |
482 } | |
483 else | |
484 { | |
186 | 485 request->logging_function (gftp_logging_error, request, |
1 | 486 _("Error: Could not remove directory %s: %s\n"), |
487 directory, g_strerror (errno)); | |
84 | 488 return (GFTP_ERETRYABLE); |
1 | 489 } |
490 } | |
491 | |
492 | |
493 static int | |
494 local_rmfile (gftp_request * request, const char *file) | |
495 { | |
838 | 496 size_t destlen; |
831 | 497 char *utf8; |
498 int ret; | |
499 | |
84 | 500 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
501 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
502 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
1 | 503 |
845 | 504 utf8 = gftp_filename_from_utf8 (request, file, &destlen); |
831 | 505 if (utf8 != NULL) |
506 { | |
507 ret = unlink (utf8); | |
508 g_free (utf8); | |
509 } | |
510 else | |
511 ret = unlink (file); | |
512 | |
513 if (ret == 0) | |
1 | 514 { |
186 | 515 request->logging_function (gftp_logging_misc, request, |
1 | 516 _("Successfully removed %s\n"), file); |
517 return (0); | |
518 } | |
519 else | |
520 { | |
186 | 521 request->logging_function (gftp_logging_error, request, |
1 | 522 _("Error: Could not remove file %s: %s\n"), |
523 file, g_strerror (errno)); | |
84 | 524 return (GFTP_ERETRYABLE); |
1 | 525 } |
526 } | |
527 | |
528 | |
529 static int | |
530 local_mkdir (gftp_request * request, const char *directory) | |
531 { | |
831 | 532 int ret, perms; |
838 | 533 size_t destlen; |
831 | 534 char *utf8; |
535 | |
84 | 536 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
537 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
538 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
1 | 539 |
831 | 540 perms = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |
541 | |
845 | 542 utf8 = gftp_filename_from_utf8 (request, directory, &destlen); |
831 | 543 if (utf8 != NULL) |
544 { | |
545 ret = mkdir (utf8, perms); | |
546 g_free (utf8); | |
547 } | |
548 else | |
549 ret = mkdir (directory, perms); | |
550 | |
551 if (ret == 0) | |
1 | 552 { |
186 | 553 request->logging_function (gftp_logging_misc, request, |
1 | 554 _("Successfully made directory %s\n"), |
555 directory); | |
556 return (0); | |
557 } | |
558 else | |
559 { | |
186 | 560 request->logging_function (gftp_logging_error, request, |
1 | 561 _("Error: Could not make directory %s: %s\n"), |
562 directory, g_strerror (errno)); | |
84 | 563 return (GFTP_ERETRYABLE); |
1 | 564 } |
565 } | |
566 | |
567 | |
568 static int | |
569 local_rename (gftp_request * request, const char *oldname, | |
570 const char *newname) | |
571 { | |
831 | 572 const char *conv_oldname, *conv_newname; |
573 char *old_utf8, *new_utf8; | |
838 | 574 size_t destlen; |
831 | 575 int ret; |
576 | |
84 | 577 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
578 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
579 g_return_val_if_fail (oldname != NULL, GFTP_EFATAL); | |
580 g_return_val_if_fail (newname != NULL, GFTP_EFATAL); | |
1 | 581 |
845 | 582 old_utf8 = gftp_filename_from_utf8 (request, oldname, &destlen); |
831 | 583 conv_oldname = old_utf8 != NULL ? old_utf8 : oldname; |
845 | 584 new_utf8 = gftp_filename_from_utf8 (request, newname, &destlen); |
831 | 585 conv_newname = new_utf8 != NULL ? new_utf8 : newname; |
586 | |
587 if (rename (conv_oldname, conv_newname) == 0) | |
1 | 588 { |
186 | 589 request->logging_function (gftp_logging_misc, request, |
1 | 590 _("Successfully renamed %s to %s\n"), |
591 oldname, newname); | |
831 | 592 ret = 0; |
1 | 593 } |
594 else | |
595 { | |
186 | 596 request->logging_function (gftp_logging_error, request, |
1 | 597 _("Error: Could not rename %s to %s: %s\n"), |
598 oldname, newname, g_strerror (errno)); | |
831 | 599 ret = GFTP_ERETRYABLE; |
1 | 600 } |
831 | 601 |
602 if (old_utf8 != NULL) | |
603 g_free (old_utf8); | |
604 if (new_utf8 != NULL) | |
605 g_free (new_utf8); | |
606 | |
607 return (ret); | |
1 | 608 } |
609 | |
610 | |
611 static int | |
499 | 612 local_chmod (gftp_request * request, const char *file, mode_t mode) |
1 | 613 { |
838 | 614 size_t destlen; |
831 | 615 char *utf8; |
616 int ret; | |
617 | |
84 | 618 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
619 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
620 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
1 | 621 |
845 | 622 utf8 = gftp_filename_from_utf8 (request, file, &destlen); |
831 | 623 if (utf8 != NULL) |
624 { | |
625 ret = chmod (utf8, mode); | |
626 g_free (utf8); | |
627 } | |
628 else | |
629 ret = chmod (file, mode); | |
630 | |
631 if (ret == 0) | |
1 | 632 { |
186 | 633 request->logging_function (gftp_logging_misc, request, |
504 | 634 _("Successfully changed mode of %s to %o\n"), |
1 | 635 file, mode); |
636 return (0); | |
637 } | |
638 else | |
639 { | |
186 | 640 request->logging_function (gftp_logging_error, request, |
504 | 641 _("Error: Could not change mode of %s to %o: %s\n"), |
1 | 642 file, mode, g_strerror (errno)); |
84 | 643 return (GFTP_ERETRYABLE); |
1 | 644 } |
645 } | |
646 | |
647 | |
648 static int | |
649 local_set_file_time (gftp_request * request, const char *file, | |
650 time_t datetime) | |
651 { | |
652 struct utimbuf time_buf; | |
838 | 653 size_t destlen; |
831 | 654 char *utf8; |
655 int ret; | |
1 | 656 |
84 | 657 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
658 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
659 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
1 | 660 |
516 | 661 time_buf.modtime = datetime; |
662 time_buf.actime = datetime; | |
831 | 663 |
845 | 664 utf8 = gftp_filename_from_utf8 (request, file, &destlen); |
831 | 665 if (utf8 != NULL) |
666 { | |
667 ret = utime (utf8, &time_buf); | |
668 g_free (utf8); | |
669 } | |
670 else | |
671 ret = utime (file, &time_buf); | |
672 | |
673 if (ret == 0) | |
674 { | |
675 request->logging_function (gftp_logging_misc, request, | |
676 _("Successfully changed the time stamp of %s\n"), | |
677 file); | |
678 return (0); | |
679 } | |
680 else | |
681 { | |
682 request->logging_function (gftp_logging_error, request, | |
683 _("Error: Could not change the time stamp of %s: %s\n"), | |
684 file, g_strerror (errno)); | |
685 return (GFTP_ERETRYABLE); | |
686 } | |
1 | 687 } |
688 | |
689 | |
989 | 690 void |
122 | 691 local_register_module (void) |
692 { | |
693 } | |
694 | |
695 | |
173 | 696 int |
48 | 697 local_init (gftp_request * request) |
698 { | |
699 local_protocol_data *lpd; | |
700 | |
173 | 701 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
48 | 702 |
703 request->protonum = GFTP_LOCAL_NUM; | |
704 request->init = local_init; | |
309 | 705 request->copy_param_options = NULL; |
48 | 706 request->destroy = local_destroy; |
168 | 707 request->read_function = gftp_fd_read; |
708 request->write_function = gftp_fd_write; | |
48 | 709 request->connect = local_connect; |
168 | 710 request->post_connect = NULL; |
48 | 711 request->disconnect = local_disconnect; |
712 request->get_file = local_get_file; | |
713 request->put_file = local_put_file; | |
714 request->transfer_file = NULL; | |
715 request->get_next_file_chunk = NULL; | |
716 request->put_next_file_chunk = NULL; | |
717 request->end_transfer = local_end_transfer; | |
718 request->abort_transfer = local_end_transfer; /* NOTE: uses end_transfer */ | |
500 | 719 request->stat_filename = local_stat_filename; |
48 | 720 request->list_files = local_list_files; |
721 request->get_next_file = local_get_next_file; | |
485 | 722 request->get_next_dirlist_line = NULL; |
48 | 723 request->get_file_size = local_get_file_size; |
724 request->chdir = local_chdir; | |
725 request->rmdir = local_rmdir; | |
726 request->rmfile = local_rmfile; | |
727 request->mkdir = local_mkdir; | |
728 request->rename = local_rename; | |
729 request->chmod = local_chmod; | |
730 request->set_file_time = local_set_file_time; | |
731 request->site = NULL; | |
732 request->parse_url = NULL; | |
58 | 733 request->set_config_options = NULL; |
63 | 734 request->swap_socks = NULL; |
48 | 735 request->url_prefix = "file"; |
736 request->need_hostport = 0; | |
553 | 737 request->need_username = 0; |
738 request->need_password = 0; | |
48 | 739 request->use_cache = 0; |
740 request->always_connected = 1; | |
832 | 741 request->use_local_encoding = 1; |
48 | 742 |
743 lpd = g_malloc0 (sizeof (*lpd)); | |
744 request->protocol_data = lpd; | |
852 | 745 lpd->userhash = g_hash_table_new (uint_hash_function, uint_hash_compare); |
746 lpd->grouphash = g_hash_table_new (uint_hash_function, uint_hash_compare); | |
66 | 747 |
748 if (request->hostname != NULL) | |
749 g_free (request->hostname); | |
750 request->hostname = g_strdup (_("local filesystem")); | |
173 | 751 |
177 | 752 return (gftp_set_config_options (request)); |
48 | 753 } |
754 |