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