Mercurial > gftp.yaz
annotate lib/local.c @ 22:cc6431f1ca55
2002-09-16 Brian Masney <masneyb@gftp.org>
* po/de.po - Updated German translation (from Matthias Haase
<matthias_haase@bennewitz.com>)
* po/ru.po - Updated Russian translation (from Vitaly Lipatov
<LAV@VL3143.spb.edu>)
author | masneyb |
---|---|
date | Tue, 17 Sep 2002 12:29:05 +0000 |
parents | 3b2dcdefc7e9 |
children | c8ec7877432e |
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" | |
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 | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
153 /* Just to simulate that we are actually connected */ |
1 | 154 request->sockfd = (void *) 1; |
155 | |
156 if (request->directory) | |
157 { | |
158 if (chdir (request->directory) != 0) | |
159 { | |
160 request->logging_function (gftp_logging_error, request->user_data, | |
161 _("Could not change local directory to %s: %s\n"), | |
162 request->directory, g_strerror (errno)); | |
163 } | |
164 g_free (request->directory); | |
165 request->directory = NULL; | |
166 } | |
167 | |
168 if (getcwd (tempstr, sizeof (tempstr)) != NULL) | |
169 { | |
170 tempstr[sizeof (tempstr) - 1] = '\0'; | |
171 request->directory = g_malloc (strlen (tempstr) + 1); | |
172 strcpy (request->directory, tempstr); | |
173 } | |
174 else | |
175 request->logging_function (gftp_logging_error, request->user_data, | |
176 _("Could not get current working directory: %s\n"), | |
177 g_strerror (errno)); | |
178 | |
179 return (0); | |
180 } | |
181 | |
182 | |
183 static void | |
184 local_disconnect (gftp_request * request) | |
185 { | |
186 g_return_if_fail (request != NULL); | |
187 g_return_if_fail (request->protonum == GFTP_LOCAL_NUM); | |
188 | |
189 if (request->datafd != NULL) | |
190 { | |
191 if (fclose (request->datafd) < 0) | |
192 request->logging_function (gftp_logging_error, request->user_data, | |
193 _("Error closing file descriptor: %s\n"), | |
194 g_strerror (errno)); | |
195 request->datafd = NULL; | |
196 } | |
197 request->sockfd = NULL; | |
198 } | |
199 | |
200 | |
201 static long | |
202 local_get_file (gftp_request * request, const char *filename, FILE * fd, | |
203 off_t startsize) | |
204 { | |
205 size_t size; | |
7 | 206 int sock, flags; |
1 | 207 |
208 g_return_val_if_fail (request != NULL, -2); | |
209 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
210 g_return_val_if_fail (filename != NULL, -2); | |
211 | |
212 if (fd == NULL) | |
213 { | |
7 | 214 flags = O_RDONLY; |
215 #if defined (_LARGEFILE_SOURCE) | |
216 flags |= O_LARGEFILE; | |
217 #endif | |
218 | |
219 if ((sock = open (filename, flags)) < 0) | |
1 | 220 { |
221 request->logging_function (gftp_logging_error, request->user_data, | |
222 _("Error: Cannot open local file %s: %s\n"), | |
223 filename, g_strerror (errno)); | |
224 return (-2); | |
225 } | |
7 | 226 |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
227 if ((request->datafd = fdopen (sock, "rb+")) == NULL) |
7 | 228 { |
229 request->logging_function (gftp_logging_error, request->user_data, | |
230 _("Cannot fdopen() socket for %s: %s\n"), | |
231 filename, g_strerror (errno)); | |
232 close (sock); | |
233 return (-2); | |
234 } | |
1 | 235 } |
236 else | |
237 request->datafd = fd; | |
238 | |
239 if (lseek (fileno (request->datafd), 0, SEEK_END) == -1) | |
240 { | |
241 request->logging_function (gftp_logging_error, request->user_data, | |
242 _("Error: Cannot seek on file %s: %s\n"), | |
243 filename, g_strerror (errno)); | |
244 fclose (request->datafd); | |
245 request->datafd = NULL; | |
246 } | |
247 | |
248 if ((size = ftell (request->datafd)) == -1) | |
249 { | |
250 request->logging_function (gftp_logging_error, request->user_data, | |
251 _("Error: Cannot seek on file %s: %s\n"), | |
252 filename, g_strerror (errno)); | |
253 fclose (request->datafd); | |
254 request->datafd = NULL; | |
255 } | |
256 | |
257 if (lseek (fileno (request->datafd), startsize, SEEK_SET) == -1) | |
258 { | |
259 request->logging_function (gftp_logging_error, request->user_data, | |
260 _("Error: Cannot seek on file %s: %s\n"), | |
261 filename, g_strerror (errno)); | |
262 fclose (request->datafd); | |
263 request->datafd = NULL; | |
264 } | |
265 | |
266 return (size); | |
267 } | |
268 | |
269 | |
270 static int | |
271 local_put_file (gftp_request * request, const char *filename, FILE * fd, | |
272 off_t startsize, off_t totalsize) | |
273 { | |
7 | 274 int sock, flags; |
1 | 275 |
276 g_return_val_if_fail (request != NULL, -2); | |
277 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
278 g_return_val_if_fail (filename != NULL, -2); | |
279 | |
280 if (fd == NULL) | |
281 { | |
7 | 282 flags = O_WRONLY | O_CREAT; |
283 if (startsize > 0) | |
284 flags |= O_APPEND; | |
285 #if defined (_LARGEFILE_SOURCE) | |
286 flags |= O_LARGEFILE; | |
287 #endif | |
288 | |
289 if ((sock = open (filename, flags, S_IRUSR | S_IWUSR)) < 0) | |
1 | 290 { |
291 request->logging_function (gftp_logging_error, request->user_data, | |
292 _("Error: Cannot open local file %s: %s\n"), | |
293 filename, g_strerror (errno)); | |
294 return (-2); | |
295 } | |
296 | |
19 | 297 if ((request->datafd = fdopen (sock, "ab")) == NULL) |
1 | 298 { |
299 request->logging_function (gftp_logging_error, request->user_data, | |
300 _("Cannot fdopen() socket for %s: %s\n"), | |
301 filename, g_strerror (errno)); | |
302 close (sock); | |
303 return (-2); | |
304 } | |
305 } | |
306 else | |
307 request->datafd = fd; | |
308 | |
309 if (ftruncate (fileno (request->datafd), startsize) == -1) | |
310 { | |
311 request->logging_function (gftp_logging_error, request->user_data, | |
312 _("Error: Cannot truncate local file %s: %s\n"), | |
313 filename, g_strerror (errno)); | |
314 fclose (request->datafd); | |
315 request->datafd = NULL; | |
316 return (-2); | |
317 } | |
318 | |
319 if (fseek (request->datafd, startsize, SEEK_SET) == -1) | |
320 { | |
321 request->logging_function (gftp_logging_error, request->user_data, | |
322 _("Error: Cannot seek on file %s: %s\n"), | |
323 filename, g_strerror (errno)); | |
324 fclose (request->datafd); | |
325 request->datafd = NULL; | |
326 return (-2); | |
327 } | |
328 return (0); | |
329 } | |
330 | |
331 | |
332 static int | |
333 local_end_transfer (gftp_request * request) | |
334 { | |
335 local_protocol_data * lpd; | |
336 | |
337 lpd = request->protocol_data; | |
338 if (lpd->dir) | |
339 { | |
340 closedir (lpd->dir); | |
341 lpd->dir = NULL; | |
342 } | |
343 | |
344 if (request->datafd != NULL) | |
345 { | |
346 if (fclose (request->datafd) < 0) | |
347 request->logging_function (gftp_logging_error, request->user_data, | |
348 _("Error closing file descriptor: %s\n"), | |
349 g_strerror (errno)); | |
350 | |
351 request->datafd = NULL; | |
352 } | |
353 | |
354 return (0); | |
355 } | |
356 | |
357 | |
358 static int | |
359 local_get_next_file (gftp_request * request, gftp_file * fle, FILE * fd) | |
360 { | |
361 local_protocol_data * lpd; | |
362 struct dirent *dirp; | |
363 char *user, *group; | |
364 struct passwd *pw; | |
365 struct group *gr; | |
366 struct stat st; | |
367 | |
368 /* the struct passwd and struct group are not thread safe. But, | |
369 we're ok here because I have threading turned off for the local | |
370 protocol (see use_threads in local_init above) */ | |
371 g_return_val_if_fail (request != NULL, -2); | |
372 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
373 g_return_val_if_fail (fle != NULL, -2); | |
374 | |
375 lpd = request->protocol_data; | |
376 memset (fle, 0, sizeof (*fle)); | |
377 | |
378 if ((dirp = readdir (lpd->dir)) == NULL) | |
379 { | |
380 closedir (lpd->dir); | |
381 lpd->dir = NULL; | |
382 return (-2); | |
383 } | |
384 | |
385 fle->file = g_malloc (strlen (dirp->d_name) + 1); | |
386 strcpy (fle->file, dirp->d_name); | |
387 if (lstat (fle->file, &st) != 0) | |
388 { | |
389 closedir (lpd->dir); | |
390 lpd->dir = NULL; | |
391 return (-2); | |
392 } | |
393 | |
394 if ((user = g_hash_table_lookup (lpd->userhash, | |
395 GUINT_TO_POINTER(st.st_uid))) != NULL) | |
396 { | |
397 fle->user = g_malloc (strlen (user) + 1); | |
398 strcpy (fle->user, user); | |
399 } | |
400 else | |
401 { | |
402 if ((pw = getpwuid (st.st_uid)) == NULL) | |
403 fle->user = g_strdup_printf ("%u", st.st_uid); | |
404 else | |
405 { | |
406 fle->user = g_malloc (strlen (pw->pw_name) + 1); | |
407 strcpy (fle->user, pw->pw_name); | |
408 } | |
409 | |
410 user = g_malloc (strlen (fle->user) + 1); | |
411 strcpy (user, fle->user); | |
412 g_hash_table_insert (lpd->userhash, GUINT_TO_POINTER (st.st_uid), user); | |
413 } | |
414 | |
415 if ((group = g_hash_table_lookup (lpd->grouphash, | |
416 GUINT_TO_POINTER(st.st_gid))) != NULL) | |
417 { | |
418 fle->group = g_malloc (strlen (group) + 1); | |
419 strcpy (fle->group, group); | |
420 } | |
421 else | |
422 { | |
423 if ((gr = getgrgid (st.st_gid)) == NULL) | |
424 fle->group = g_strdup_printf ("%u", st.st_gid); | |
425 else | |
426 { | |
427 fle->group = g_malloc (strlen (gr->gr_name) + 1); | |
428 strcpy (fle->group, gr->gr_name); | |
429 } | |
430 | |
431 group = g_malloc (strlen (fle->group) + 1); | |
432 strcpy (group, fle->group); | |
433 g_hash_table_insert (lpd->grouphash, GUINT_TO_POINTER (st.st_gid), group); | |
434 } | |
435 | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
436 fle->attribs = make_text_mode (fle, st.st_mode); |
1 | 437 fle->datetime = st.st_mtime; |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
438 |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
439 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
|
440 fle->attribs[0] == 'c')) |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
441 { |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
442 /* 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
|
443 #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
|
444 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
|
445 major numbers */ |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
446 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
|
447 fle->size |= st.st_rdev & 0xFF; |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
448 } |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
449 else |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
450 fle->size = st.st_size; |
1 | 451 |
452 if (*fle->attribs == 'd') | |
453 fle->isdir = 1; | |
454 if (*fle->attribs == 'l') | |
455 fle->islink = 1; | |
456 if (strchr (fle->attribs, 'x') != NULL && !fle->isdir && !fle->islink) | |
457 fle->isexe = 1; | |
458 if (*fle->attribs == 'b') | |
459 fle->isblock = 1; | |
460 if (*fle->attribs == 'c') | |
461 fle->ischar = 1; | |
462 if (*fle->attribs == 's') | |
463 fle->issocket = 1; | |
464 if (*fle->attribs == 'p') | |
465 fle->isfifo = 1; | |
466 return (1); | |
467 } | |
468 | |
469 | |
470 static int | |
471 local_list_files (gftp_request * request) | |
472 { | |
473 local_protocol_data *lpd; | |
474 char *tempstr; | |
475 | |
476 g_return_val_if_fail (request != NULL, -2); | |
477 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
478 lpd = request->protocol_data; | |
479 | |
480 tempstr = g_strconcat (request->directory, "/", NULL); | |
481 | |
482 if ((lpd->dir = opendir (tempstr)) == NULL) | |
483 { | |
484 request->logging_function (gftp_logging_error, request->user_data, | |
485 _("Could not get local directory listing %s: %s\n"), | |
486 tempstr, g_strerror (errno)); | |
487 g_free (tempstr); | |
488 return (-1); | |
489 } | |
490 | |
491 g_free (tempstr); | |
492 return (0); | |
493 } | |
494 | |
495 | |
496 static off_t | |
497 local_get_file_size (gftp_request * request, const char *filename) | |
498 { | |
499 struct stat st; | |
500 | |
501 if (stat (filename, &st) == -1) | |
502 return (-1); | |
503 return (st.st_size); | |
504 } | |
505 | |
506 | |
507 static int | |
508 local_chdir (gftp_request * request, const char *directory) | |
509 { | |
510 char tempstr[255]; | |
511 | |
512 g_return_val_if_fail (request != NULL, -2); | |
513 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
514 g_return_val_if_fail (directory != NULL, -2); | |
515 | |
516 if (chdir (directory) == 0) | |
517 { | |
518 request->logging_function (gftp_logging_error, request->user_data, | |
519 _("Successfully changed local directory to %s\n"), | |
520 directory); | |
521 if (request->directory != directory) | |
522 { | |
523 if (getcwd (tempstr, sizeof (tempstr)) == NULL) | |
524 { | |
525 request->logging_function (gftp_logging_error, request->user_data, | |
526 _("Could not get current working directory: %s\n"), | |
527 g_strerror (errno)); | |
528 return (-1); | |
529 } | |
530 if (request->directory) | |
531 g_free (request->directory); | |
532 request->directory = g_malloc (strlen (tempstr) + 1); | |
533 strcpy (request->directory, tempstr); | |
534 } | |
535 return (0); | |
536 } | |
537 request->logging_function (gftp_logging_error, request->user_data, | |
538 _("Could not change local directory to %s: %s\n"), | |
539 directory, g_strerror (errno)); | |
540 return (-1); | |
541 } | |
542 | |
543 | |
544 static int | |
545 local_rmdir (gftp_request * request, const char *directory) | |
546 { | |
547 g_return_val_if_fail (request != NULL, -2); | |
548 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
549 g_return_val_if_fail (directory != NULL, -2); | |
550 | |
551 if (rmdir (directory) == 0) | |
552 { | |
553 request->logging_function (gftp_logging_error, request->user_data, | |
554 _("Successfully removed %s\n"), directory); | |
555 return (0); | |
556 } | |
557 else | |
558 { | |
559 request->logging_function (gftp_logging_error, request->user_data, | |
560 _("Error: Could not remove directory %s: %s\n"), | |
561 directory, g_strerror (errno)); | |
562 return (-1); | |
563 } | |
564 } | |
565 | |
566 | |
567 static int | |
568 local_rmfile (gftp_request * request, const char *file) | |
569 { | |
570 g_return_val_if_fail (request != NULL, -2); | |
571 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
572 g_return_val_if_fail (file != NULL, -2); | |
573 | |
574 if (unlink (file) == 0) | |
575 { | |
576 request->logging_function (gftp_logging_error, request->user_data, | |
577 _("Successfully removed %s\n"), file); | |
578 return (0); | |
579 } | |
580 else | |
581 { | |
582 request->logging_function (gftp_logging_error, request->user_data, | |
583 _("Error: Could not remove file %s: %s\n"), | |
584 file, g_strerror (errno)); | |
585 return (-1); | |
586 } | |
587 } | |
588 | |
589 | |
590 static int | |
591 local_mkdir (gftp_request * request, const char *directory) | |
592 { | |
593 g_return_val_if_fail (request != NULL, -2); | |
594 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
595 g_return_val_if_fail (directory != NULL, -2); | |
596 | |
597 if (mkdir (directory, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0) | |
598 { | |
599 request->logging_function (gftp_logging_error, request->user_data, | |
600 _("Successfully made directory %s\n"), | |
601 directory); | |
602 return (0); | |
603 } | |
604 else | |
605 { | |
606 request->logging_function (gftp_logging_error, request->user_data, | |
607 _("Error: Could not make directory %s: %s\n"), | |
608 directory, g_strerror (errno)); | |
609 return (-1); | |
610 } | |
611 } | |
612 | |
613 | |
614 static int | |
615 local_rename (gftp_request * request, const char *oldname, | |
616 const char *newname) | |
617 { | |
618 g_return_val_if_fail (request != NULL, -2); | |
619 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
620 g_return_val_if_fail (oldname != NULL, -2); | |
621 g_return_val_if_fail (newname != NULL, -2); | |
622 | |
623 if (rename (oldname, newname) == 0) | |
624 { | |
625 request->logging_function (gftp_logging_error, request->user_data, | |
626 _("Successfully renamed %s to %s\n"), | |
627 oldname, newname); | |
628 return (0); | |
629 } | |
630 else | |
631 { | |
632 request->logging_function (gftp_logging_error, request->user_data, | |
633 _("Error: Could not rename %s to %s: %s\n"), | |
634 oldname, newname, g_strerror (errno)); | |
635 return (-1); | |
636 } | |
637 } | |
638 | |
639 | |
640 static int | |
641 local_chmod (gftp_request * request, const char *file, int mode) | |
642 { | |
643 char buf[10]; | |
644 int newmode; | |
645 | |
646 g_return_val_if_fail (request != NULL, -2); | |
647 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
648 g_return_val_if_fail (file != NULL, -2); | |
649 | |
650 g_snprintf (buf, sizeof (buf), "%d", mode); | |
651 newmode = strtol (buf, NULL, 8); | |
652 | |
653 if (chmod (file, newmode) == 0) | |
654 { | |
655 request->logging_function (gftp_logging_error, request->user_data, | |
656 _("Successfully changed mode of %s to %d\n"), | |
657 file, mode); | |
658 return (0); | |
659 } | |
660 else | |
661 { | |
662 request->logging_function (gftp_logging_error, request->user_data, | |
663 _("Error: Could not change mode of %s to %d: %s\n"), | |
664 file, mode, g_strerror (errno)); | |
665 return (-1); | |
666 } | |
667 } | |
668 | |
669 | |
670 static int | |
671 local_set_file_time (gftp_request * request, const char *file, | |
672 time_t datetime) | |
673 { | |
674 struct utimbuf time_buf; | |
675 | |
676 g_return_val_if_fail (request != NULL, -2); | |
677 g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, -2); | |
678 g_return_val_if_fail (file != NULL, -2); | |
679 | |
680 time_buf.modtime = time_buf.actime = datetime; | |
681 return (utime (file, &time_buf)); | |
682 } | |
683 | |
684 | |
685 static char * | |
686 make_text_mode (gftp_file * fle, mode_t mode) | |
687 { | |
688 char *str; | |
689 | |
690 str = g_malloc0 (11); | |
691 | |
692 str[0] = '?'; | |
693 if (S_ISREG (mode)) | |
694 str[0] = '-'; | |
695 | |
696 if (S_ISLNK (mode)) | |
697 { | |
698 fle->islink = 1; | |
699 str[0] = 'l'; | |
700 } | |
701 | |
702 if (S_ISBLK (mode)) | |
703 { | |
704 fle->isblock = 1; | |
705 str[0] = 'b'; | |
706 } | |
707 | |
708 if (S_ISCHR (mode)) | |
709 { | |
710 fle->ischar = 1; | |
711 str[0] = 'c'; | |
712 } | |
713 | |
714 if (S_ISFIFO (mode)) | |
715 { | |
716 fle->isfifo = 1; | |
717 str[0] = 'p'; | |
718 } | |
719 | |
720 if (S_ISSOCK (mode)) | |
721 { | |
722 fle->issocket = 1; | |
723 str[0] = 's'; | |
724 } | |
725 | |
726 if (S_ISDIR (mode)) | |
727 { | |
728 fle->isdir = 1; | |
729 str[0] = 'd'; | |
730 } | |
731 | |
732 str[1] = mode & S_IRUSR ? 'r' : '-'; | |
733 str[2] = mode & S_IWUSR ? 'w' : '-'; | |
734 | |
735 if ((mode & S_ISUID) && (mode & S_IXUSR)) | |
736 str[3] = 's'; | |
737 else if (mode & S_ISUID) | |
738 str[3] = 'S'; | |
739 else if (mode & S_IXUSR) | |
740 str[3] = 'x'; | |
741 else | |
742 str[3] = '-'; | |
743 | |
744 str[4] = mode & S_IRGRP ? 'r' : '-'; | |
745 str[5] = mode & S_IWGRP ? 'w' : '-'; | |
746 | |
747 if ((mode & S_ISGID) && (mode & S_IXGRP)) | |
748 str[6] = 's'; | |
749 else if (mode & S_ISGID) | |
750 str[6] = 'S'; | |
751 else if (mode & S_IXGRP) | |
752 str[6] = 'x'; | |
753 else | |
754 str[6] = '-'; | |
755 | |
756 str[7] = mode & S_IROTH ? 'r' : '-'; | |
757 str[8] = mode & S_IWOTH ? 'w' : '-'; | |
758 | |
759 if ((mode & S_ISVTX) && (mode & S_IXOTH)) | |
760 str[9] = 't'; | |
761 else if (mode & S_ISVTX) | |
762 str[9] = 'T'; | |
763 else if (mode & S_IXOTH) | |
764 str[9] = 'x'; | |
765 else | |
766 str[9] = '-'; | |
767 return (str); | |
768 } | |
769 | |
770 | |
771 static gint | |
772 hash_compare (gconstpointer path1, gconstpointer path2) | |
773 { | |
774 return (GPOINTER_TO_UINT (path1) == GPOINTER_TO_UINT (path2)); | |
775 } | |
776 | |
777 | |
778 static guint | |
779 hash_function (gconstpointer key) | |
780 { | |
781 return (GPOINTER_TO_UINT (key)); | |
782 } | |
783 |