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