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