Mercurial > gftp.yaz
annotate lib/local.c @ 100:5c67e6591984
2003-02-06 Christophe Fergeau <teuf@users.sourceforge.net>
* fr.po: Committed updated French translation from
Laurent RICHARD <laurent.richard@lilit.be>
author | cfergeau |
---|---|
date | Thu, 06 Feb 2003 21:27:19 +0000 |
parents | 8c37d73d3f1f |
children | 76e2b58a9440 |
rev | line source |
---|---|
1 | 1 /*****************************************************************************/ |
2 /* local.c - functions that will use the local system */ | |
3 /* Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org> */ | |
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 |
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 | |
55 local_connect (gftp_request * request) | |
56 { | |
57 char tempstr[PATH_MAX]; | |
58 | |
84 | 59 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
60 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
1 | 61 |
62 if (request->directory) | |
63 { | |
64 if (chdir (request->directory) != 0) | |
65 { | |
66 request->logging_function (gftp_logging_error, request->user_data, | |
67 _("Could not change local directory to %s: %s\n"), | |
68 request->directory, g_strerror (errno)); | |
69 } | |
70 g_free (request->directory); | |
71 request->directory = NULL; | |
72 } | |
73 | |
74 if (getcwd (tempstr, sizeof (tempstr)) != NULL) | |
75 { | |
76 tempstr[sizeof (tempstr) - 1] = '\0'; | |
87 | 77 request->directory = g_strdup (tempstr); |
1 | 78 } |
79 else | |
80 request->logging_function (gftp_logging_error, request->user_data, | |
81 _("Could not get current working directory: %s\n"), | |
82 g_strerror (errno)); | |
83 | |
84 return (0); | |
85 } | |
86 | |
87 | |
88 static void | |
89 local_disconnect (gftp_request * request) | |
90 { | |
91 g_return_if_fail (request != NULL); | |
92 g_return_if_fail (request->protonum == GFTP_LOCAL_NUM); | |
93 | |
58 | 94 if (request->datafd != -1) |
1 | 95 { |
87 | 96 if (close (request->datafd) == -1) |
1 | 97 request->logging_function (gftp_logging_error, request->user_data, |
98 _("Error closing file descriptor: %s\n"), | |
99 g_strerror (errno)); | |
58 | 100 request->datafd = -1; |
1 | 101 } |
102 } | |
103 | |
104 | |
58 | 105 static off_t |
106 local_get_file (gftp_request * request, const char *filename, int fd, | |
1 | 107 off_t startsize) |
108 { | |
58 | 109 off_t size; |
110 int flags; | |
1 | 111 |
84 | 112 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
113 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
114 g_return_val_if_fail (filename != NULL, GFTP_EFATAL); | |
1 | 115 |
66 | 116 if (fd <= 0) |
1 | 117 { |
7 | 118 flags = O_RDONLY; |
119 #if defined (_LARGEFILE_SOURCE) | |
120 flags |= O_LARGEFILE; | |
121 #endif | |
122 | |
87 | 123 if ((request->datafd = open (filename, flags)) == -1) |
1 | 124 { |
125 request->logging_function (gftp_logging_error, request->user_data, | |
126 _("Error: Cannot open local file %s: %s\n"), | |
127 filename, g_strerror (errno)); | |
87 | 128 return (GFTP_ERETRYABLE); |
1 | 129 } |
130 } | |
131 else | |
132 request->datafd = fd; | |
133 | |
87 | 134 if ((size = lseek (request->datafd, 0, SEEK_END)) == -1) |
1 | 135 { |
136 request->logging_function (gftp_logging_error, request->user_data, | |
137 _("Error: Cannot seek on file %s: %s\n"), | |
138 filename, g_strerror (errno)); | |
58 | 139 gftp_disconnect (request); |
84 | 140 return (GFTP_ERETRYABLE); |
1 | 141 } |
142 | |
87 | 143 if (lseek (request->datafd, startsize, SEEK_SET) == -1) |
1 | 144 { |
145 request->logging_function (gftp_logging_error, request->user_data, | |
146 _("Error: Cannot seek on file %s: %s\n"), | |
147 filename, g_strerror (errno)); | |
58 | 148 gftp_disconnect (request); |
84 | 149 return (GFTP_ERETRYABLE); |
1 | 150 } |
151 | |
152 return (size); | |
153 } | |
154 | |
155 | |
156 static int | |
58 | 157 local_put_file (gftp_request * request, const char *filename, int fd, |
1 | 158 off_t startsize, off_t totalsize) |
159 { | |
58 | 160 int flags; |
1 | 161 |
84 | 162 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
163 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
164 g_return_val_if_fail (filename != NULL, GFTP_EFATAL); | |
1 | 165 |
66 | 166 if (fd <= 0) |
1 | 167 { |
7 | 168 flags = O_WRONLY | O_CREAT; |
169 if (startsize > 0) | |
170 flags |= O_APPEND; | |
171 #if defined (_LARGEFILE_SOURCE) | |
172 flags |= O_LARGEFILE; | |
173 #endif | |
174 | |
87 | 175 if ((request->datafd = open (filename, flags, S_IRUSR | S_IWUSR)) == -1) |
1 | 176 { |
177 request->logging_function (gftp_logging_error, request->user_data, | |
178 _("Error: Cannot open local file %s: %s\n"), | |
179 filename, g_strerror (errno)); | |
84 | 180 return (GFTP_ERETRYABLE); |
1 | 181 } |
182 } | |
183 else | |
184 request->datafd = fd; | |
185 | |
87 | 186 if (ftruncate (request->datafd, startsize) == -1) |
1 | 187 { |
188 request->logging_function (gftp_logging_error, request->user_data, | |
189 _("Error: Cannot truncate local file %s: %s\n"), | |
190 filename, g_strerror (errno)); | |
58 | 191 gftp_disconnect (request); |
84 | 192 return (GFTP_ERETRYABLE); |
1 | 193 } |
194 | |
87 | 195 if (lseek (request->datafd, startsize, SEEK_SET) == -1) |
1 | 196 { |
197 request->logging_function (gftp_logging_error, request->user_data, | |
198 _("Error: Cannot seek on file %s: %s\n"), | |
199 filename, g_strerror (errno)); | |
58 | 200 gftp_disconnect (request); |
84 | 201 return (GFTP_ERETRYABLE); |
1 | 202 } |
203 return (0); | |
204 } | |
205 | |
206 | |
207 static int | |
208 local_end_transfer (gftp_request * request) | |
209 { | |
210 local_protocol_data * lpd; | |
211 | |
212 lpd = request->protocol_data; | |
213 if (lpd->dir) | |
214 { | |
215 closedir (lpd->dir); | |
216 lpd->dir = NULL; | |
217 } | |
218 | |
58 | 219 if (request->datafd > 0) |
1 | 220 { |
87 | 221 if (close (request->datafd) == -1) |
1 | 222 request->logging_function (gftp_logging_error, request->user_data, |
223 _("Error closing file descriptor: %s\n"), | |
224 g_strerror (errno)); | |
225 | |
58 | 226 request->datafd = -1; |
1 | 227 } |
228 | |
229 return (0); | |
230 } | |
231 | |
232 | |
48 | 233 static char * |
87 | 234 make_text_mode (mode_t mode) |
48 | 235 { |
236 char *str; | |
237 | |
238 str = g_malloc0 (11); | |
239 | |
240 str[0] = '?'; | |
241 if (S_ISREG (mode)) | |
242 str[0] = '-'; | |
243 | |
244 if (S_ISLNK (mode)) | |
87 | 245 str[0] = 'l'; |
48 | 246 |
247 if (S_ISBLK (mode)) | |
87 | 248 str[0] = 'b'; |
48 | 249 |
250 if (S_ISCHR (mode)) | |
87 | 251 str[0] = 'c'; |
48 | 252 |
253 if (S_ISFIFO (mode)) | |
87 | 254 str[0] = 'p'; |
48 | 255 |
256 if (S_ISSOCK (mode)) | |
87 | 257 str[0] = 's'; |
48 | 258 |
259 if (S_ISDIR (mode)) | |
87 | 260 str[0] = 'd'; |
48 | 261 |
262 str[1] = mode & S_IRUSR ? 'r' : '-'; | |
263 str[2] = mode & S_IWUSR ? 'w' : '-'; | |
264 | |
265 if ((mode & S_ISUID) && (mode & S_IXUSR)) | |
266 str[3] = 's'; | |
267 else if (mode & S_ISUID) | |
268 str[3] = 'S'; | |
269 else if (mode & S_IXUSR) | |
270 str[3] = 'x'; | |
271 else | |
272 str[3] = '-'; | |
273 | |
274 str[4] = mode & S_IRGRP ? 'r' : '-'; | |
275 str[5] = mode & S_IWGRP ? 'w' : '-'; | |
276 | |
277 if ((mode & S_ISGID) && (mode & S_IXGRP)) | |
278 str[6] = 's'; | |
279 else if (mode & S_ISGID) | |
280 str[6] = 'S'; | |
281 else if (mode & S_IXGRP) | |
282 str[6] = 'x'; | |
283 else | |
284 str[6] = '-'; | |
285 | |
286 str[7] = mode & S_IROTH ? 'r' : '-'; | |
287 str[8] = mode & S_IWOTH ? 'w' : '-'; | |
288 | |
289 if ((mode & S_ISVTX) && (mode & S_IXOTH)) | |
290 str[9] = 't'; | |
291 else if (mode & S_ISVTX) | |
292 str[9] = 'T'; | |
293 else if (mode & S_IXOTH) | |
294 str[9] = 'x'; | |
295 else | |
296 str[9] = '-'; | |
297 return (str); | |
298 } | |
299 | |
300 | |
1 | 301 static int |
58 | 302 local_get_next_file (gftp_request * request, gftp_file * fle, int fd) |
1 | 303 { |
304 local_protocol_data * lpd; | |
305 struct dirent *dirp; | |
306 char *user, *group; | |
307 struct passwd *pw; | |
308 struct group *gr; | |
309 struct stat st; | |
310 | |
311 /* the struct passwd and struct group are not thread safe. But, | |
312 we're ok here because I have threading turned off for the local | |
313 protocol (see use_threads in local_init above) */ | |
84 | 314 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
315 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
316 g_return_val_if_fail (fle != NULL, GFTP_EFATAL); | |
1 | 317 |
318 lpd = request->protocol_data; | |
87 | 319 |
320 g_return_val_if_fail (lpd != NULL, GFTP_EFATAL); | |
321 | |
1 | 322 memset (fle, 0, sizeof (*fle)); |
323 | |
324 if ((dirp = readdir (lpd->dir)) == NULL) | |
325 { | |
326 closedir (lpd->dir); | |
327 lpd->dir = NULL; | |
84 | 328 return (GFTP_ERETRYABLE); |
1 | 329 } |
330 | |
87 | 331 fle->file = g_strdup (dirp->d_name); |
1 | 332 if (lstat (fle->file, &st) != 0) |
333 { | |
334 closedir (lpd->dir); | |
335 lpd->dir = NULL; | |
84 | 336 return (GFTP_ERETRYABLE); |
1 | 337 } |
338 | |
339 if ((user = g_hash_table_lookup (lpd->userhash, | |
340 GUINT_TO_POINTER(st.st_uid))) != NULL) | |
87 | 341 fle->user = g_strdup (user); |
1 | 342 else |
343 { | |
344 if ((pw = getpwuid (st.st_uid)) == NULL) | |
345 fle->user = g_strdup_printf ("%u", st.st_uid); | |
346 else | |
87 | 347 fle->user = g_strdup (pw->pw_name); |
1 | 348 |
87 | 349 user = g_strdup (fle->user); |
1 | 350 g_hash_table_insert (lpd->userhash, GUINT_TO_POINTER (st.st_uid), user); |
351 } | |
352 | |
353 if ((group = g_hash_table_lookup (lpd->grouphash, | |
354 GUINT_TO_POINTER(st.st_gid))) != NULL) | |
87 | 355 fle->group = g_strdup (group); |
1 | 356 else |
357 { | |
358 if ((gr = getgrgid (st.st_gid)) == NULL) | |
359 fle->group = g_strdup_printf ("%u", st.st_gid); | |
360 else | |
87 | 361 fle->group = g_strdup (gr->gr_name); |
1 | 362 |
87 | 363 group = g_strdup (fle->group); |
1 | 364 g_hash_table_insert (lpd->grouphash, GUINT_TO_POINTER (st.st_gid), group); |
365 } | |
366 | |
87 | 367 fle->attribs = make_text_mode (st.st_mode); |
1 | 368 fle->datetime = st.st_mtime; |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
369 |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
370 if ((fle->attribs[0] == 'b' || fle->attribs[0] == 'u' || |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
371 fle->attribs[0] == 'c')) |
48 | 372 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
|
373 else |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
374 fle->size = st.st_size; |
1 | 375 |
91 | 376 fle->isdir = S_ISDIR (st.st_mode); |
377 fle->islink = S_ISLNK (st.st_mode); | |
87 | 378 fle->isexe = (st.st_mode & S_IXUSR) || |
379 (st.st_mode & S_IXGRP) || | |
380 (st.st_mode & S_IXOTH); | |
381 | |
1 | 382 return (1); |
383 } | |
384 | |
385 | |
386 static int | |
387 local_list_files (gftp_request * request) | |
388 { | |
389 local_protocol_data *lpd; | |
390 char *tempstr; | |
87 | 391 int freeit; |
1 | 392 |
84 | 393 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
87 | 394 g_return_val_if_fail (request->directory != NULL, GFTP_EFATAL); |
84 | 395 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); |
87 | 396 |
1 | 397 lpd = request->protocol_data; |
398 | |
87 | 399 g_return_val_if_fail (lpd != NULL, GFTP_EFATAL); |
400 | |
401 if (request->directory[strlen (request->directory) - 1] != '/') | |
402 { | |
403 tempstr = g_strconcat (request->directory, "/", NULL); | |
404 freeit = 1; | |
405 } | |
406 else | |
407 { | |
408 tempstr = request->directory; | |
409 freeit = 0; | |
410 } | |
1 | 411 |
412 if ((lpd->dir = opendir (tempstr)) == NULL) | |
413 { | |
414 request->logging_function (gftp_logging_error, request->user_data, | |
415 _("Could not get local directory listing %s: %s\n"), | |
416 tempstr, g_strerror (errno)); | |
87 | 417 if (freeit) |
418 g_free (tempstr); | |
84 | 419 return (GFTP_ERETRYABLE); |
1 | 420 } |
421 | |
87 | 422 if (freeit) |
423 g_free (tempstr); | |
424 | |
1 | 425 return (0); |
426 } | |
427 | |
428 | |
429 static off_t | |
430 local_get_file_size (gftp_request * request, const char *filename) | |
431 { | |
432 struct stat st; | |
433 | |
87 | 434 if (stat (filename, &st) == -1) |
84 | 435 return (GFTP_ERETRYABLE); |
1 | 436 return (st.st_size); |
437 } | |
438 | |
439 | |
440 static int | |
441 local_chdir (gftp_request * request, const char *directory) | |
442 { | |
443 char tempstr[255]; | |
444 | |
84 | 445 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
446 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
447 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
1 | 448 |
449 if (chdir (directory) == 0) | |
450 { | |
58 | 451 request->logging_function (gftp_logging_misc, request->user_data, |
1 | 452 _("Successfully changed local directory to %s\n"), |
453 directory); | |
87 | 454 if (request->directory != directory) /* FIXME - take this out ? */ |
1 | 455 { |
456 if (getcwd (tempstr, sizeof (tempstr)) == NULL) | |
457 { | |
458 request->logging_function (gftp_logging_error, request->user_data, | |
459 _("Could not get current working directory: %s\n"), | |
460 g_strerror (errno)); | |
84 | 461 return (GFTP_ERETRYABLE); |
1 | 462 } |
87 | 463 |
1 | 464 if (request->directory) |
465 g_free (request->directory); | |
87 | 466 request->directory = g_strdup (tempstr); |
1 | 467 } |
468 return (0); | |
469 } | |
87 | 470 else |
471 { | |
472 request->logging_function (gftp_logging_error, request->user_data, | |
473 _("Could not change local directory to %s: %s\n"), | |
474 directory, g_strerror (errno)); | |
475 return (GFTP_ERETRYABLE); | |
476 } | |
1 | 477 } |
478 | |
479 | |
480 static int | |
481 local_rmdir (gftp_request * request, const char *directory) | |
482 { | |
84 | 483 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
484 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
485 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
1 | 486 |
487 if (rmdir (directory) == 0) | |
488 { | |
58 | 489 request->logging_function (gftp_logging_misc, request->user_data, |
1 | 490 _("Successfully removed %s\n"), directory); |
491 return (0); | |
492 } | |
493 else | |
494 { | |
495 request->logging_function (gftp_logging_error, request->user_data, | |
496 _("Error: Could not remove directory %s: %s\n"), | |
497 directory, g_strerror (errno)); | |
84 | 498 return (GFTP_ERETRYABLE); |
1 | 499 } |
500 } | |
501 | |
502 | |
503 static int | |
504 local_rmfile (gftp_request * request, const char *file) | |
505 { | |
84 | 506 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
507 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
508 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
1 | 509 |
510 if (unlink (file) == 0) | |
511 { | |
58 | 512 request->logging_function (gftp_logging_misc, request->user_data, |
1 | 513 _("Successfully removed %s\n"), file); |
514 return (0); | |
515 } | |
516 else | |
517 { | |
518 request->logging_function (gftp_logging_error, request->user_data, | |
519 _("Error: Could not remove file %s: %s\n"), | |
520 file, g_strerror (errno)); | |
84 | 521 return (GFTP_ERETRYABLE); |
1 | 522 } |
523 } | |
524 | |
525 | |
526 static int | |
527 local_mkdir (gftp_request * request, const char *directory) | |
528 { | |
84 | 529 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
530 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
531 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
1 | 532 |
533 if (mkdir (directory, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) | |
534 { | |
58 | 535 request->logging_function (gftp_logging_misc, request->user_data, |
1 | 536 _("Successfully made directory %s\n"), |
537 directory); | |
538 return (0); | |
539 } | |
540 else | |
541 { | |
542 request->logging_function (gftp_logging_error, request->user_data, | |
543 _("Error: Could not make directory %s: %s\n"), | |
544 directory, g_strerror (errno)); | |
84 | 545 return (GFTP_ERETRYABLE); |
1 | 546 } |
547 } | |
548 | |
549 | |
550 static int | |
551 local_rename (gftp_request * request, const char *oldname, | |
552 const char *newname) | |
553 { | |
84 | 554 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
555 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
556 g_return_val_if_fail (oldname != NULL, GFTP_EFATAL); | |
557 g_return_val_if_fail (newname != NULL, GFTP_EFATAL); | |
1 | 558 |
559 if (rename (oldname, newname) == 0) | |
560 { | |
58 | 561 request->logging_function (gftp_logging_misc, request->user_data, |
1 | 562 _("Successfully renamed %s to %s\n"), |
563 oldname, newname); | |
564 return (0); | |
565 } | |
566 else | |
567 { | |
568 request->logging_function (gftp_logging_error, request->user_data, | |
569 _("Error: Could not rename %s to %s: %s\n"), | |
570 oldname, newname, g_strerror (errno)); | |
84 | 571 return (GFTP_ERETRYABLE); |
1 | 572 } |
573 } | |
574 | |
575 | |
576 static int | |
577 local_chmod (gftp_request * request, const char *file, int mode) | |
578 { | |
579 char buf[10]; | |
580 int newmode; | |
581 | |
84 | 582 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
583 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
584 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
1 | 585 |
586 g_snprintf (buf, sizeof (buf), "%d", mode); | |
587 newmode = strtol (buf, NULL, 8); | |
588 | |
589 if (chmod (file, newmode) == 0) | |
590 { | |
58 | 591 request->logging_function (gftp_logging_misc, request->user_data, |
1 | 592 _("Successfully changed mode of %s to %d\n"), |
593 file, mode); | |
594 return (0); | |
595 } | |
596 else | |
597 { | |
598 request->logging_function (gftp_logging_error, request->user_data, | |
599 _("Error: Could not change mode of %s to %d: %s\n"), | |
600 file, mode, g_strerror (errno)); | |
84 | 601 return (GFTP_ERETRYABLE); |
1 | 602 } |
603 } | |
604 | |
605 | |
606 static int | |
607 local_set_file_time (gftp_request * request, const char *file, | |
608 time_t datetime) | |
609 { | |
610 struct utimbuf time_buf; | |
611 | |
84 | 612 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
613 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL); | |
614 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
1 | 615 |
616 time_buf.modtime = time_buf.actime = datetime; | |
84 | 617 return (utime (file, &time_buf) == 0 ? 0 : GFTP_ERETRYABLE); |
1 | 618 } |
619 | |
620 | |
621 static gint | |
622 hash_compare (gconstpointer path1, gconstpointer path2) | |
623 { | |
624 return (GPOINTER_TO_UINT (path1) == GPOINTER_TO_UINT (path2)); | |
625 } | |
626 | |
627 | |
628 static guint | |
629 hash_function (gconstpointer key) | |
630 { | |
631 return (GPOINTER_TO_UINT (key)); | |
632 } | |
633 | |
48 | 634 |
635 void | |
636 local_init (gftp_request * request) | |
637 { | |
638 local_protocol_data *lpd; | |
639 | |
640 g_return_if_fail (request != NULL); | |
641 | |
642 request->protonum = GFTP_LOCAL_NUM; | |
643 request->init = local_init; | |
644 request->destroy = local_destroy; | |
645 request->connect = local_connect; | |
646 request->disconnect = local_disconnect; | |
647 request->get_file = local_get_file; | |
648 request->put_file = local_put_file; | |
649 request->transfer_file = NULL; | |
650 request->get_next_file_chunk = NULL; | |
651 request->put_next_file_chunk = NULL; | |
652 request->end_transfer = local_end_transfer; | |
653 request->abort_transfer = local_end_transfer; /* NOTE: uses end_transfer */ | |
654 request->list_files = local_list_files; | |
655 request->get_next_file = local_get_next_file; | |
656 request->set_data_type = NULL; | |
657 request->get_file_size = local_get_file_size; | |
658 request->chdir = local_chdir; | |
659 request->rmdir = local_rmdir; | |
660 request->rmfile = local_rmfile; | |
661 request->mkdir = local_mkdir; | |
662 request->rename = local_rename; | |
663 request->chmod = local_chmod; | |
664 request->set_file_time = local_set_file_time; | |
665 request->site = NULL; | |
666 request->parse_url = NULL; | |
58 | 667 request->set_config_options = NULL; |
63 | 668 request->swap_socks = NULL; |
48 | 669 request->url_prefix = "file"; |
670 request->protocol_name = "Local"; | |
671 request->need_hostport = 0; | |
672 request->need_userpass = 0; | |
673 request->use_cache = 0; | |
674 request->use_threads = 0; | |
675 request->always_connected = 1; | |
676 gftp_set_config_options (request); | |
677 | |
678 lpd = g_malloc0 (sizeof (*lpd)); | |
679 request->protocol_data = lpd; | |
680 lpd->userhash = g_hash_table_new (hash_function, hash_compare); | |
681 lpd->grouphash = g_hash_table_new (hash_function, hash_compare); | |
66 | 682 |
683 if (request->hostname != NULL) | |
684 g_free (request->hostname); | |
685 request->hostname = g_strdup (_("local filesystem")); | |
48 | 686 } |
687 |