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