changeset 499:39e9945288ea

2004-7-13 Brian Masney <masneyb@gftp.org> * lib/gftp.h lib/local.c lib/misc.c lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c src/gtk/chmod_dialog.c src/gtk/delete_dialog.c src/gtk/dnd.c src/gtk/gftp-gtk.c src/gtk/gtkui_transfer.c src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/view_dialog.c src/text/textui.c src/uicommon/gftpui.c src/uicommon/gftpuicallbacks.c - represent the file attributes as a mode_t variable instead of a character string
author masneyb
date Tue, 13 Jul 2004 20:17:42 +0000
parents 76c4e4cd108e
children ba50a7085d93
files ChangeLog lib/gftp.h lib/local.c lib/misc.c lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c src/gtk/chmod_dialog.c src/gtk/delete_dialog.c src/gtk/dnd.c src/gtk/gftp-gtk.c src/gtk/gtkui_transfer.c src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/view_dialog.c src/text/textui.c src/uicommon/gftpui.c src/uicommon/gftpuicallbacks.c
diffstat 19 files changed, 292 insertions(+), 273 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Jul 13 02:44:35 2004 +0000
+++ b/ChangeLog	Tue Jul 13 20:17:42 2004 +0000
@@ -1,3 +1,12 @@
+2004-7-13 Brian Masney <masneyb@gftp.org>
+	* lib/gftp.h lib/local.c lib/misc.c lib/protocols.c lib/rfc2068.c
+	lib/rfc959.c lib/sshv2.c src/gtk/chmod_dialog.c src/gtk/delete_dialog.c
+	src/gtk/dnd.c src/gtk/gftp-gtk.c src/gtk/gtkui_transfer.c
+	src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/view_dialog.c
+	src/text/textui.c src/uicommon/gftpui.c src/uicommon/gftpuicallbacks.c -
+	represent the file attributes as a mode_t variable instead of a
+	character string
+
 2004-7-12 Brian Masney <masneyb@gftp.org>
 	* lib/sshv2.c - added sshv2_decode_file_attributes(). This is used
 	by sshv2_get_next_file() and sshv2_get_file_size().
@@ -2549,7 +2558,7 @@
 
 	* cvsclean - added this script
 
-	* *.[ch] - added $Id: ChangeLog,v 1.277 2004/07/13 02:44:34 masneyb Exp $ tags
+	* *.[ch] - added $Id: ChangeLog,v 1.278 2004/07/13 20:17:42 masneyb Exp $ tags
 
 	* debian/* - updated files from Debian maintainer
 
--- a/lib/gftp.h	Tue Jul 13 02:44:35 2004 +0000
+++ b/lib/gftp.h	Tue Jul 13 20:17:42 2004 +0000
@@ -209,6 +209,8 @@
 #define GFTP_SORT_COL_DATETIME			5
 #define GFTP_SORT_COL_ATTRIBS			6
 
+#define GFTP_IS_SPECIAL_DEVICE(mode)	(S_ISBLK (mode) || S_ISCHR (mode))
+
 struct gftp_file_tag 
 {
   char *file,			/* Our filename */
@@ -217,7 +219,6 @@
 				   UTF-8 */
        *user,			/* User that owns it */
        *group,			/* Group that owns it */
-       *attribs,		/* Attribs (-rwxr-x-rx) */
        *destfile;		/* Full pathname to the destination for the 
                                    file transfer */
 
@@ -227,10 +228,8 @@
   time_t datetime;		/* File date and time */
   off_t size,			/* Size of the file */
         startsize;		/* Size to start the transfer at */
-  unsigned int isdir : 1,	/* File type */
-               isexe : 1,
-               islink : 1,
-               selected : 1,	/* Is this file selected? */
+  mode_t st_mode;		/* File attributes */
+  unsigned int selected : 1,	/* Is this file selected? */
                was_sel : 1,	/* Was this file selected before  */
                shown : 1,	/* Is this file shown? */
                done_view : 1,	/* View the file when done transfering? */
@@ -448,7 +447,7 @@
 					  const char *newname );
   int (*chmod)				( gftp_request * request, 
 					  const char *filename, 
-					  int mode );
+					  mode_t mode );
   int (*set_file_time)			( gftp_request * request, 
 					  const char *filename, 
 					  time_t datettime );
@@ -738,8 +737,6 @@
 					  int column, 
 					  int asds );
 
-mode_t gftp_parse_attribs 		( char *attribs );
-
 char * gftp_gen_ls_string 		( gftp_file * fle, 
 					  char *file_prefixstr, 
 					  char *file_suffixstr );
@@ -924,7 +921,7 @@
 
 int gftp_chmod 				( gftp_request * request, 
 					  const char *file, 
-					  int mode );
+					  mode_t mode );
 
 int gftp_set_file_time 			( gftp_request * request, 
 					  const char *file, 
@@ -1025,6 +1022,11 @@
 					  int *ptymfd,
 					  char **args );
 
+char *gftp_convert_attributes_from_mode_t ( mode_t mode );
+
+mode_t gftp_convert_attributes_to_mode_t ( char *attribs );
+
+
 #ifdef USE_SSL
 /* sslcommon.c */
 int gftp_ssl_startup 			( gftp_request * request );
--- a/lib/local.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/lib/local.c	Tue Jul 13 20:17:42 2004 +0000
@@ -220,74 +220,6 @@
 }
 
 
-static char *
-make_text_mode (mode_t mode)
-{
-  char *str;
-
-  str = g_malloc0 (11);
-  
-  str[0] = '?';
-  if (S_ISREG (mode))
-    str[0] = '-';
-
-  if (S_ISLNK (mode))
-    str[0] = 'l';
-
-  if (S_ISBLK (mode))
-    str[0] = 'b';
-
-  if (S_ISCHR (mode))
-    str[0] = 'c';
-
-  if (S_ISFIFO (mode))
-    str[0] = 'p';
-
-  if (S_ISSOCK (mode))
-    str[0] = 's';
-
-  if (S_ISDIR (mode))
-    str[0] = 'd';
-
-  str[1] = mode & S_IRUSR ? 'r' : '-';
-  str[2] = mode & S_IWUSR ? 'w' : '-';
-
-  if ((mode & S_ISUID) && (mode & S_IXUSR))
-    str[3] = 's';
-  else if (mode & S_ISUID)
-    str[3] = 'S';
-  else if (mode & S_IXUSR)
-    str[3] = 'x';
-  else
-    str[3] = '-';
-    
-  str[4] = mode & S_IRGRP ? 'r' : '-';
-  str[5] = mode & S_IWGRP ? 'w' : '-';
-
-  if ((mode & S_ISGID) && (mode & S_IXGRP))
-    str[6] = 's';
-  else if (mode & S_ISGID)
-    str[6] = 'S';
-  else if (mode & S_IXGRP)
-    str[6] = 'x';
-  else
-    str[6] = '-';
-
-  str[7] = mode & S_IROTH ? 'r' : '-';
-  str[8] = mode & S_IWOTH ? 'w' : '-';
-
-  if ((mode & S_ISVTX) && (mode & S_IXOTH))
-    str[9] = 't';
-  else if (mode & S_ISVTX)
-    str[9] = 'T';
-  else if (mode & S_IXOTH)
-    str[9] = 'x';
-  else
-    str[9] = '-';
-  return (str);
-}
-
-
 static int
 local_get_next_file (gftp_request * request, gftp_file * fle, int fd)
 {
@@ -353,21 +285,14 @@
       g_hash_table_insert (lpd->grouphash, GUINT_TO_POINTER (st.st_gid), group);
     }
 
-  fle->attribs = make_text_mode (fst.st_mode);
+  fle->st_mode = fst.st_mode;
   fle->datetime = st.st_mtime;
 
-  if ((fle->attribs[0] == 'b' || fle->attribs[0] == 'u' ||
-       fle->attribs[0] == 'c'))
+  if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode))
     fle->size = (off_t) st.st_rdev;
   else
     fle->size = fst.st_size;
 
-  fle->isdir = S_ISDIR (fst.st_mode);
-  fle->islink = S_ISLNK (st.st_mode);
-  fle->isexe = (fst.st_mode & S_IXUSR) || 
-               (fst.st_mode & S_IXGRP) ||
-               (fst.st_mode & S_IXOTH);
-
   return (1);
 }
 
@@ -565,7 +490,7 @@
 
 
 static int
-local_chmod (gftp_request * request, const char *file, int mode)
+local_chmod (gftp_request * request, const char *file, mode_t mode)
 {
   char buf[10];
   int newmode;
--- a/lib/misc.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/lib/misc.c	Tue Jul 13 20:17:42 2004 +0000
@@ -469,8 +469,6 @@
     g_free (fle->user);
   if (fle->group)
     g_free (fle->group);
-  if (fle->attribs)
-    g_free (fle->attribs);
   if (fle->destfile)
     g_free (fle->destfile);
   if (fle->fd > 0)
@@ -499,9 +497,6 @@
   if (fle->group)
     newfle->group = g_strdup (fle->group);
 
-  if (fle->attribs)
-    newfle->attribs = g_strdup (fle->attribs);
-
   if (fle->destfile)
     newfle->destfile = g_strdup (fle->destfile);
 
@@ -709,7 +704,12 @@
 
   f1 = a;
   f2 = b;
-  return (strcmp (f1->attribs, f2->attribs));
+  if (f1->st_mode < f2->st_mode)
+    return (-1);
+  else if (f1->st_mode == f2->st_mode)
+    return (0);
+  else
+    return (1);
 }
 
 
@@ -717,12 +717,15 @@
 gftp_attribs_sort_function_ds (gconstpointer a, gconstpointer b)
 {
   const gftp_file * f1, * f2;
-  gint ret;
 
   f1 = a;
   f2 = b;
-  ret = strcmp (f1->attribs, f2->attribs);
-  return (ret * -1);
+  if (f1->st_mode < f2->st_mode)
+    return (1);
+  else if (f1->st_mode == f2->st_mode)
+    return (0);
+  else
+    return (-1);
 }
 
 
@@ -833,7 +836,7 @@
 
       if (dotdot == NULL && strcmp (tempfle->file, "..") == 0)
         dotdot = insitem;
-      else if (sort_dirs_first && tempfle->isdir)
+      else if (sort_dirs_first && S_ISDIR (tempfle->st_mode))
         {
           insitem->next = dirs;
           dirs = insitem;
@@ -869,59 +872,20 @@
 }
 
 
-mode_t
-gftp_parse_attribs (char *attribs)
-{
-  mode_t mode;
-  int cur;
-
-  cur = 0;
-  if (attribs[1] == 'r')
-    cur += 4;
-  if (attribs[2] == 'w')
-    cur += 2;
-  if (attribs[3] == 'x' ||
-      attribs[3] == 's')
-    cur += 1;
-  mode = cur;
-
-  cur = 0;
-  if (attribs[4] == 'r')
-    cur += 4;
-  if (attribs[5] == 'w')
-    cur += 2;
-  if (attribs[6] == 'x' ||
-      attribs[6] == 's')
-    cur += 1;
-  mode = (mode * 10) + cur;
-
-  cur = 0;
-  if (attribs[7] == 'r')
-    cur += 4;
-  if (attribs[8] == 'w')
-    cur += 2;
-  if (attribs[9] == 'x' ||
-      attribs[9] == 's')
-    cur += 1;
-  mode = (mode * 10) + cur;
-
-  return (mode);
-}
-
-
 char *
 gftp_gen_ls_string (gftp_file * fle, char *file_prefixstr, char *file_suffixstr)
 {
-  char *tempstr1, *tempstr2, *ret, tstr[50];
+  char *tempstr1, *tempstr2, *ret, tstr[50], *attribs;
   struct tm *lt;
   time_t t;
 
   lt = localtime (&fle->datetime);
 
-  tempstr1 = g_strdup_printf ("%10s %8s %8s", fle->attribs, fle->user,
-                              fle->group);
+  attribs = gftp_convert_attributes_from_mode_t (fle->st_mode);
+  tempstr1 = g_strdup_printf ("%10s %8s %8s", attribs, fle->user, fle->group);
+  g_free (attribs);
 
-  if (fle->attribs && (*fle->attribs == 'b' || *fle->attribs == 'c'))
+  if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode))
     tempstr2 = g_strdup_printf ("%d, %d", major (fle->size), minor (fle->size));
   else
     {
--- a/lib/protocols.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/lib/protocols.c	Tue Jul 13 20:17:42 2004 +0000
@@ -112,8 +112,6 @@
     g_free (file->user);
   if (file->group)
     g_free (file->group);
-  if (file->attribs)
-    g_free (file->attribs);
   if (file->destfile)
     g_free (file->destfile);
   memset (file, 0, sizeof (*file));
@@ -980,7 +978,7 @@
 
 
 int
-gftp_chmod (gftp_request * request, const char *file, int mode)
+gftp_chmod (gftp_request * request, const char *file, mode_t mode)
 {
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
 
@@ -1285,25 +1283,29 @@
 }
 
 
-static void 
-gftp_parse_vms_attribs (char *dest, char **src)
+static mode_t
+gftp_parse_vms_attribs (char **src, mode_t mask)
 {
   char *endpos;
+  mode_t ret;
 
   if (*src == NULL)
-    return;
+    return (0);
 
   if ((endpos = strchr (*src, ',')) != NULL)
     *endpos = '\0';
 
+  ret = 0;
   if (strchr (*src, 'R') != NULL)
-    *dest = 'r';
+    ret |= S_IRUSR | S_IRGRP | S_IROTH;
   if (strchr (*src, 'W') != NULL)
-    *(dest + 1) = 'w';
+    ret |= S_IWUSR | S_IWGRP | S_IWOTH;
   if (strchr (*src, 'E') != NULL)
-    *(dest + 2) = 'x';
+    ret |= S_IXUSR | S_IXGRP | S_IXOTH;
 
   *src = endpos + 1;
+
+  return (ret & mask);
 }
 
 
@@ -1335,12 +1337,9 @@
   *curpos = '\0';
   if (strlen (str) > 4 && strcmp (curpos - 4, ".DIR") == 0)
     {
-      fle->isdir = 1;
-      fle->attribs = g_strdup ("d---------");
+      fle->st_mode |= S_IFDIR;
       *(curpos - 4) = '\0';
     }
-  else
-   fle->attribs = g_strdup ("----------");
 
   fle->file = g_strdup (str);
 
@@ -1376,9 +1375,9 @@
     return (0);
   curpos++;
 
-  gftp_parse_vms_attribs (fle->attribs + 1, &curpos);
-  gftp_parse_vms_attribs (fle->attribs + 4, &curpos);
-  gftp_parse_vms_attribs (fle->attribs + 7, &curpos);
+  fle->st_mode = gftp_parse_vms_attribs (&curpos, S_IRWXU);
+  fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXG);
+  fle->st_mode |= gftp_parse_vms_attribs (&curpos, S_IRWXO);
 
   fle->user = g_strdup ("");
   fle->group = g_strdup ("");
@@ -1432,9 +1431,9 @@
     return (GFTP_EFATAL);
 
   if (strncmp (curpos, "PS", 2) == 0)
-    fle->attribs = g_strdup ("-rw-r--r--");
+    fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
   else if (strncmp (curpos, "PO", 2) == 0)
-    fle->attribs = g_strdup ("drwxr-xr-x");
+    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
   else
     return (GFTP_EFATAL);
 
@@ -1477,9 +1476,9 @@
     return (GFTP_EFATAL);
 
   if (isdir)
-    fle->attribs = g_strdup ("drwxr-xr-x");
+    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
   else
-    fle->attribs = g_strdup ("-rw-r--r--");
+    fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
 
   fle->file = g_strdup (startpos + 1);
   fle->user = g_strdup (_("unknown"));
@@ -1492,7 +1491,7 @@
 gftp_parse_ls_unix (gftp_request * request, char *str, size_t slen,
                     gftp_file * fle)
 {
-  char *endpos, *startpos, *pos;
+  char *endpos, *startpos, *pos, *attribs;
   int cols;
 
   /* If there is no space between the attribs and links field, just make one */
@@ -1525,9 +1524,12 @@
 
   startpos = str;
   /* Copy file attributes */
-  if ((startpos = copy_token (&fle->attribs, startpos)) == NULL)
+  if ((startpos = copy_token (&attribs, startpos)) == NULL)
     return (GFTP_EFATAL);
 
+  fle->st_mode = gftp_convert_attributes_to_mode_t (attribs);
+  g_free (attribs);
+
   if (cols >= 9)
     {
       /* Skip the number of links */
@@ -1567,9 +1569,8 @@
 
   /* See if this is a block or character device. We will store the major number
      in the high word and the minor number in the low word.  */
-  if ((fle->attribs[0] == 'b' || fle->attribs[0] == 'u' || 
-       fle->attribs[0] == 'c') &&
-      ((endpos = strchr (startpos, ',')) != NULL))
+  if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode) &&
+      (endpos = strchr (startpos, ',')) != NULL)
     {
       fle->size = strtol (startpos, NULL, 10) << 16;
 
@@ -1601,7 +1602,7 @@
   startpos = goto_next_token (startpos);
 
   /* Parse the filename. If this file is a symbolic link, remove the -> part */
-  if (fle->attribs[0] == 'l' && ((endpos = strstr (startpos, "->")) != NULL))
+  if (S_ISLNK (fle->st_mode) && ((endpos = strstr (startpos, "->")) != NULL))
     *(endpos - 1) = '\0';
 
   fle->file = g_strdup (startpos);
@@ -1631,11 +1632,12 @@
   fle->group = g_strdup (_("unknown"));
 
   startpos = goto_next_token (startpos);
+
   if (startpos[0] == '<')
-    fle->attribs = g_strdup ("drwxrwxrwx");
+    fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
   else
     {
-      fle->attribs = g_strdup ("-rw-rw-rw-");
+      fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
       fle->size = gftp_parse_file_size (startpos);
     }
 
@@ -1652,8 +1654,9 @@
 
   if (str[12] != ' ')
     return (GFTP_EFATAL);
+
   str[12] = '\0';
-  fle->attribs = g_strdup (str);
+  fle->st_mode = gftp_convert_attributes_to_mode_t (str);
   startpos = str + 13;
 
   while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0')
@@ -1746,16 +1749,6 @@
     }
   g_free (str);
 
-  if (fle->attribs == NULL)
-    return (result);
-
-  if (*fle->attribs == 'd')
-    fle->isdir = 1;
-  if (*fle->attribs == 'l')
-    fle->islink = 1;
-  if (strchr (fle->attribs, 'x') != NULL && !fle->isdir && !fle->islink)
-    fle->isexe = 1;
-
   return (result);
 }
 
@@ -1947,7 +1940,7 @@
     {
       curfle = templist->data;
 
-      if (curfle->isdir)
+      if (S_ISDIR (curfle->st_mode))
         {
           oldfromdir = transfer->fromreq->directory;
           transfer->fromreq->directory = curfle->file;
@@ -2272,22 +2265,27 @@
 {
   gftp_file * tempfle;
   GList * templist;
+  char *attribs;
 
   printf ("--START OF FILE LISTING - TOP TO BOTTOM--\n");
   for (templist = list; ; templist = templist->next)
     {
       tempfle = templist->data;
+      attribs = gftp_convert_attributes_from_mode_t (tempfle->st_mode);
+
 #if defined (_LARGEFILE_SOURCE)
       printf ("%s:%s:%lld:%lld:%s:%s:%s\n", 
               tempfle->file, tempfle->destfile, 
               (long long) tempfle->size, (long long) tempfle->startsize, 
-              tempfle->user, tempfle->group, tempfle->attribs);
+              tempfle->user, tempfle->group, attribs);
 #else
       printf ("%s:%s:%ld:%ld:%s:%s:%s\n", 
               tempfle->file, tempfle->destfile, 
               tempfle->size, tempfle->startsize, 
-              tempfle->user, tempfle->group, tempfle->attribs);
+              tempfle->user, tempfle->group, attribs);
 #endif
+
+      g_free (attribs);
       if (templist->next == NULL)
         break;
     }
@@ -2296,17 +2294,21 @@
   for (; ; templist = templist->prev)
     {
       tempfle = templist->data;
+      attribs = gftp_convert_attributes_from_mode_t (tempfle->st_mode);
+
 #if defined (_LARGEFILE_SOURCE)
       printf ("%s:%s:%lld:%lld:%s:%s:%s\n", 
               tempfle->file, tempfle->destfile, 
               (long long) tempfle->size, (long long) tempfle->startsize, 
-              tempfle->user, tempfle->group, tempfle->attribs);
+              tempfle->user, tempfle->group, attribs);
 #else
       printf ("%s:%s:%ld:%ld:%s:%s:%s\n", 
               tempfle->file, tempfle->destfile, 
               tempfle->size, tempfle->startsize, 
-              tempfle->user, tempfle->group, tempfle->attribs);
+              tempfle->user, tempfle->group, attribs);
 #endif
+
+      g_free (attribs);
       if (templist == list)
         break;
     }
@@ -2897,3 +2899,123 @@
     }
 }
 
+
+char *
+gftp_convert_attributes_from_mode_t (mode_t mode)
+{
+  char *str;
+
+  str = g_malloc0 (11);
+  
+  str[0] = '?';
+  if (S_ISREG (mode))
+    str[0] = '-';
+
+  if (S_ISLNK (mode))
+    str[0] = 'l';
+
+  if (S_ISBLK (mode))
+    str[0] = 'b';
+
+  if (S_ISCHR (mode))
+    str[0] = 'c';
+
+  if (S_ISFIFO (mode))
+    str[0] = 'p';
+
+  if (S_ISSOCK (mode))
+    str[0] = 's';
+
+  if (S_ISDIR (mode))
+    str[0] = 'd';
+
+  str[1] = mode & S_IRUSR ? 'r' : '-';
+  str[2] = mode & S_IWUSR ? 'w' : '-';
+
+  if ((mode & S_ISUID) && (mode & S_IXUSR))
+    str[3] = 's';
+  else if (mode & S_ISUID)
+    str[3] = 'S';
+  else if (mode & S_IXUSR)
+    str[3] = 'x';
+  else
+    str[3] = '-';
+    
+  str[4] = mode & S_IRGRP ? 'r' : '-';
+  str[5] = mode & S_IWGRP ? 'w' : '-';
+
+  if ((mode & S_ISGID) && (mode & S_IXGRP))
+    str[6] = 's';
+  else if (mode & S_ISGID)
+    str[6] = 'S';
+  else if (mode & S_IXGRP)
+    str[6] = 'x';
+  else
+    str[6] = '-';
+
+  str[7] = mode & S_IROTH ? 'r' : '-';
+  str[8] = mode & S_IWOTH ? 'w' : '-';
+
+  if ((mode & S_ISVTX) && (mode & S_IXOTH))
+    str[9] = 't';
+  else if (mode & S_ISVTX)
+    str[9] = 'T';
+  else if (mode & S_IXOTH)
+    str[9] = 'x';
+  else
+    str[9] = '-';
+
+  return (str);
+}
+
+
+mode_t
+gftp_convert_attributes_to_mode_t (char *attribs)
+{
+  mode_t mode;
+
+  if (attribs[0] == 'd')
+    mode = S_IFDIR;
+  else if (attribs[0] == 'l')
+    mode = S_IFLNK;
+  else if (attribs[0] == 's')
+    mode = S_IFSOCK;
+  else if (attribs[0] == 'b')
+    mode = S_IFBLK;
+  else if (attribs[0] == 'c')
+    mode = S_IFCHR;
+  else
+    mode = S_IFREG;
+
+  if (attribs[1] == 'r')
+    mode |= S_IRUSR;
+  if (attribs[2] == 'w')
+    mode |= S_IWUSR;
+  if (attribs[3] == 'x' || attribs[3] == 's')
+    mode |= S_IXUSR;
+  if (attribs[3] == 's' || attribs[3] == 'S')
+    mode |= S_ISUID;
+
+  if (attribs[4] == 'r')
+    mode |= S_IRGRP;
+  if (attribs[5] == 'w')
+    mode |= S_IWGRP;
+  if (attribs[6] == 'x' ||
+      attribs[6] == 's')
+    mode |= S_IXGRP;
+  if (attribs[6] == 's' || attribs[6] == 'S')
+    mode |= S_ISGID;
+
+  if (attribs[7] == 'r')
+    mode |= S_IROTH;
+  if (attribs[8] == 'w')
+    mode |= S_IWOTH;
+  if (attribs[9] == 'x' ||
+      attribs[9] == 's')
+    mode |= S_IXOTH;
+  if (attribs[9] == 't' || attribs[9] == 'T')
+    mode |= S_ISVTX;
+
+  return (mode);
+}
+
--- a/lib/rfc2068.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/lib/rfc2068.c	Tue Jul 13 20:17:42 2004 +0000
@@ -502,12 +502,11 @@
      is a directory or not */
   if (*(pos - 1) == '/')
     {
-      fle->attribs = g_strdup ("drwxr-xr-x");
+      fle->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
       *(pos - 1) = '\0';
-      fle->isdir = 1;
     }
   else
-    fle->attribs = g_strdup ("-rw-r--r--");
+    fle->st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
 
   /* Copy filename */
   if (strchr (stpos, '/') != NULL || strncmp (stpos, "mailto:", 7) == 0 ||
--- a/lib/rfc959.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/lib/rfc959.c	Tue Jul 13 20:17:42 2004 +0000
@@ -1656,7 +1656,7 @@
 
 
 static int
-rfc959_chmod (gftp_request * request, const char *file, int mode)
+rfc959_chmod (gftp_request * request, const char *file, mode_t mode)
 {
   char *tempstr, ret;
 
--- a/lib/sshv2.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/lib/sshv2.c	Tue Jul 13 20:17:42 2004 +0000
@@ -1483,7 +1483,7 @@
 
 
 static int 
-sshv2_chmod (gftp_request * request, const char *file, int mode)
+sshv2_chmod (gftp_request * request, const char *file, mode_t mode)
 {
   char *tempstr, *endpos, buf[10];
   sshv2_params * params;
--- a/src/gtk/chmod_dialog.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/chmod_dialog.c	Tue Jul 13 20:17:42 2004 +0000
@@ -22,7 +22,7 @@
 
 static GtkWidget *suid, *sgid, *sticky, *ur, *uw, *ux, *gr, *gw, *gx, *or, *ow,
                  *ox;
-static int mode; 
+static mode_t mode; 
 
 
 static int
@@ -59,42 +59,36 @@
 dochmod (GtkWidget * widget, gftp_window_data * wdata)
 {
   gftpui_callback_data * cdata;
-  int cur, ret;
+  int ret;
 
   mode = 0;
   if (GTK_TOGGLE_BUTTON (suid)->active)
-    mode += 4;
+    mode |= S_ISUID;
   if (GTK_TOGGLE_BUTTON (sgid)->active)
-    mode += 2;
+    mode |= S_ISGID;
   if (GTK_TOGGLE_BUTTON (sticky)->active)
-    mode += 1;
+    mode |= S_ISVTX;
 
-  cur = 0;
   if (GTK_TOGGLE_BUTTON (ur)->active)
-    cur += 4;
+    mode |= S_IRUSR;
   if (GTK_TOGGLE_BUTTON (uw)->active)
-    cur += 2;
+    mode |= S_IWUSR;
   if (GTK_TOGGLE_BUTTON (ux)->active)
-    cur += 1;
-  mode = mode * 10 + cur;
+    mode |= S_IXUSR;
 
-  cur = 0;
   if (GTK_TOGGLE_BUTTON (gr)->active)
-    cur += 4;
+    mode |= S_IRGRP;
   if (GTK_TOGGLE_BUTTON (gw)->active)
-    cur += 2;
+    mode |= S_IWGRP;
   if (GTK_TOGGLE_BUTTON (gx)->active)
-    cur += 1;
-  mode = mode * 10 + cur;
+    mode |= S_IWOTH;
 
-  cur = 0;
   if (GTK_TOGGLE_BUTTON (or)->active)
-    cur += 4;
+    mode |= S_IROTH;
   if (GTK_TOGGLE_BUTTON (ow)->active)
-    cur += 2;
+    mode |= S_IWOTH;
   if (GTK_TOGGLE_BUTTON (ox)->active)
-    cur += 1;
-  mode = mode * 10 + cur;
+    mode |= S_IXOTH;
 
   if (check_reconnect (wdata) < 0)
     return;
@@ -289,33 +283,33 @@
       num = 0;
       templist = get_next_selection (templist, &filelist, &num);
       tempfle = filelist->data;
+
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (suid),
-				    tolower (tempfle->attribs[3]) == 's');
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sgid),
-				    tolower (tempfle->attribs[6]) == 's');
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sticky),
-				    tolower (tempfle->attribs[9]) == 't');
+                                    tempfle->st_mode & S_ISUID);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ur),
-				    tempfle->attribs[1] == 'r');
+                                    tempfle->st_mode & S_IRUSR);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uw),
-				    tempfle->attribs[2] == 'w');
+                                    tempfle->st_mode & S_IWUSR);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ux),
-				    tempfle->attribs[3] == 'x' ||
-                                    tempfle->attribs[3] == 's');
+                                    tempfle->st_mode & S_IXUSR);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sgid),
+                                    tempfle->st_mode & S_ISGID);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gr),
-				    tempfle->attribs[4] == 'r');
+                                    tempfle->st_mode & S_IRGRP);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gw),
-				    tempfle->attribs[5] == 'w');
+                                    tempfle->st_mode & S_IWGRP);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gx),
-				    tempfle->attribs[6] == 'x' ||
-                                    tempfle->attribs[6] == 's');
+                                    tempfle->st_mode & S_IXGRP);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sticky),
+                                    tempfle->st_mode & S_ISVTX);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (or),
-				    tempfle->attribs[7] == 'r');
+                                    tempfle->st_mode & S_IROTH);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ow),
-				    tempfle->attribs[8] == 'w');
+                                    tempfle->st_mode & S_IWOTH);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ox),
-				    tempfle->attribs[9] == 'x' ||
-                                    tempfle->attribs[9] == 't');
+                                    tempfle->st_mode & S_IXOTH);
     }
   gtk_widget_show (dialog);
 }
--- a/src/gtk/delete_dialog.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/delete_dialog.c	Tue Jul 13 20:17:42 2004 +0000
@@ -58,7 +58,7 @@
       for (; templist != NULL; templist = templist->prev)
         {
           tempfle = templist->data;
-          if (tempfle->isdir)
+          if (S_ISDIR (tempfle->st_mode))
             success = gftp_remove_directory (transfer->fromreq, tempfle->file);
           else
             success = gftp_remove_file (transfer->fromreq, tempfle->file);
--- a/src/gtk/dnd.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/dnd.c	Tue Jul 13 20:17:42 2004 +0000
@@ -42,7 +42,7 @@
   newfle->shown = 1;
   if (url[strlen (url) - 1] == '/') 
     {
-      newfle->isdir = 1;
+      newfle->st_mode |= S_IFDIR;
       url[strlen (url) - 1] = '\0';
     }
 
@@ -192,7 +192,7 @@
 
       /* Note, I am allocating memory for this byte above. Note the extra space
          at the end of the g_strdup_printf() format argument */
-      if (tempfle->isdir)
+      if (S_ISDIR (tempfle->st_mode))
         tempstr[strlen (tempstr) - 1] = '/';
       else
         tempstr[strlen (tempstr) - 1] = '\0';
--- a/src/gtk/gftp-gtk.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/gftp-gtk.c	Tue Jul 13 20:17:42 2004 +0000
@@ -579,8 +579,8 @@
 {
   intptr_t list_dblclk_action;
   GList *templist, *filelist;
-  int num, dir, success;
   gftp_file *tempfle;
+  int num, success;
   char *directory;
 
   gftp_lookup_request_option (wdata->request, "list_dblclk_action", 
@@ -592,12 +592,10 @@
   templist = get_next_selection (templist, &filelist, &num);
   tempfle = (gftp_file *) filelist->data;
 
-  dir = tempfle->isdir;
-
   if (check_reconnect (wdata) < 0) 
     return;
 
-  if (tempfle->islink || tempfle->isdir)
+  if (S_ISLNK (tempfle->st_mode) || S_ISDIR (tempfle->st_mode))
     {
       directory = gftp_build_path (wdata->request->directory, tempfle->file, NULL);
       success = gftpui_run_chdir (wdata, directory);
@@ -606,7 +604,7 @@
   else
     success = 0;
 
-  if (!dir && !success)
+  if (!S_ISDIR (tempfle->st_mode) && !success)
     {
       switch (list_dblclk_action)
         {
--- a/src/gtk/gtkui_transfer.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/gtkui_transfer.c	Tue Jul 13 20:17:42 2004 +0000
@@ -279,7 +279,7 @@
        templist = templist->next)
     {
       tempfle = templist->data;
-      if (tempfle->startsize == 0 || tempfle->isdir)
+      if (tempfle->startsize == 0 || S_ISDIR (tempfle->st_mode))
         {
            tempfle->shown = 0;
            continue;
--- a/src/gtk/menu-items.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/menu-items.c	Tue Jul 13 20:17:42 2004 +0000
@@ -216,7 +216,7 @@
       tempfle = (gftp_file *) templist->data;
       if (tempfle->shown)
 	{
-	  if (tempfle->isdir)
+	  if (S_ISDIR (tempfle->st_mode))
 	    gtk_clist_unselect_row (GTK_CLIST (wdata->listbox), i, 0);
 	  else
 	    gtk_clist_select_row (GTK_CLIST (wdata->listbox), i, 0);
@@ -642,7 +642,7 @@
 {
   gftp_file * curfle, * otherfle;
   GList * curlist, * otherlist;
-  int row;
+  int row, curdir, othdir;
 
   if (!check_status (_("Compare Windows"), &window2, 1, 0, 0, 1))
     return;
@@ -671,9 +671,12 @@
               continue;
             }
 
+          curdir = S_ISDIR (curfle->st_mode);
+          othdir = S_ISDIR (otherfle->st_mode);
+
           if (strcmp (otherfle->file, curfle->file) == 0 &&
-              otherfle->isdir == curfle->isdir &&
-              (curfle->isdir || otherfle->size == curfle->size))
+              curdir == othdir &&
+              (curdir || otherfle->size == curfle->size))
 	    break;
 
           otherlist = otherlist->next;
@@ -706,9 +709,12 @@
               continue;
             }
 
+          curdir = S_ISDIR (curfle->st_mode);
+          othdir = S_ISDIR (otherfle->st_mode);
+
           if (strcmp (otherfle->file, curfle->file) == 0 &&
-              otherfle->isdir == curfle->isdir &&
-              (curfle->isdir || otherfle->size == curfle->size))
+              curdir == othdir &&
+              (curdir || otherfle->size == curfle->size))
 	    break;
 
           otherlist = otherlist->next;
--- a/src/gtk/misc-gtk.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/misc-gtk.c	Tue Jul 13 20:17:42 2004 +0000
@@ -646,15 +646,15 @@
 void
 add_file_listbox (gftp_window_data * wdata, gftp_file * fle)
 {
-  char *add_data[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }, *pos;
+  char *add_data[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+  char *tempstr, *str, *pos, *attribs;
   gftp_config_list_vars * tmplistvar;
-  int clist_num;
+  gftp_file_extensions * tempext;
   intptr_t show_hidden_files;
-  gftp_file_extensions * tempext;
-  char *tempstr, *str;
   GdkBitmap * bitmap;
   GList * templist;
   GdkPixmap * pix;
+  int clist_num;
   size_t stlen;
 
   gftp_lookup_request_option (wdata->request, "show_hidden_files", 
@@ -689,13 +689,15 @@
   bitmap = NULL;
   if (strcmp (fle->file, "..") == 0)
     gftp_get_pixmap (wdata->listbox, "dotdot.xpm", &pix, &bitmap);
-  else if (fle->islink && fle->isdir)
+  else if (S_ISLNK (fle->st_mode) && S_ISDIR (fle->st_mode))
     gftp_get_pixmap (wdata->listbox, "linkdir.xpm", &pix, &bitmap);
-  else if (fle->islink)
+  else if (S_ISLNK (fle->st_mode))
     gftp_get_pixmap (wdata->listbox, "linkfile.xpm", &pix, &bitmap);
-  else if (fle->isdir)
+  else if (S_ISLNK (fle->st_mode))
     gftp_get_pixmap (wdata->listbox, "dir.xpm", &pix, &bitmap);
-  else if (fle->isexe)
+  else if ((fle->st_mode & S_IXUSR) ||
+           (fle->st_mode & S_IXGRP) ||
+           (fle->st_mode & S_IXOTH))
     gftp_get_pixmap (wdata->listbox, "exe.xpm", &pix, &bitmap); 
   else
     {
@@ -727,7 +729,7 @@
   else if (fle->file)
     gtk_clist_set_text (GTK_CLIST (wdata->listbox), clist_num, 1, fle->file);
 
-  if (fle->attribs && (*fle->attribs == 'b' || *fle->attribs == 'c'))
+  if (GFTP_IS_SPECIAL_DEVICE (fle->st_mode))
     tempstr = g_strdup_printf ("%d, %d", major (fle->size),
                                minor (fle->size));
   else
@@ -746,8 +748,10 @@
         *pos = '\0';
       gtk_clist_set_text (GTK_CLIST (wdata->listbox), clist_num, 5, str);
     }
-  if (fle->attribs)
-    gtk_clist_set_text (GTK_CLIST (wdata->listbox), clist_num, 6, fle->attribs);
+
+  attribs = gftp_convert_attributes_from_mode_t (fle->st_mode);
+  gtk_clist_set_text (GTK_CLIST (wdata->listbox), clist_num, 6, attribs);
+  g_free (attribs);
 
 }
 
--- a/src/gtk/view_dialog.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/gtk/view_dialog.c	Tue Jul 13 20:17:42 2004 +0000
@@ -42,7 +42,7 @@
   templist = get_next_selection (templist, &filelist, &num);
   curfle = filelist->data;
 
-  if (curfle->isdir)
+  if (S_ISDIR (curfle->st_mode))
     {
       ftp_log (gftp_logging_misc, NULL,
 	       _("View: %s is a directory. Cannot view it.\n"), curfle->file);
@@ -121,7 +121,7 @@
   templist = get_next_selection (templist, &filelist, &num);
   curfle = filelist->data;
 
-  if (curfle->isdir)
+  if (S_ISDIR (curfle->st_mode))
     {
       ftp_log (gftp_logging_misc, NULL,
 	       _("Edit: %s is a directory. Cannot edit it.\n"), curfle->file);
--- a/src/text/textui.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/text/textui.c	Tue Jul 13 20:17:42 2004 +0000
@@ -24,11 +24,13 @@
 gftpui_lookup_file_colors (gftp_file * fle, char **start_color,
                            char ** end_color)
 {
-  if (*fle->attribs == 'd')
+  if (S_ISDIR (fle->st_mode))
     *start_color = GFTPUI_COMMON_COLOR_BLUE;
-  else if (*fle->attribs == 'l')
+  else if (S_ISLNK (fle->st_mode))
     *start_color = GFTPUI_COMMON_COLOR_WHITE;
-  else if (strchr (fle->attribs, 'x') != NULL)
+  else if ((fle->st_mode & S_IXUSR) ||
+           (fle->st_mode & S_IXGRP) ||
+           (fle->st_mode & S_IXOTH))
     *start_color = GFTPUI_COMMON_COLOR_GREEN;
   else
     *start_color = GFTPUI_COMMON_COLOR_DEFAULT;
@@ -103,7 +105,7 @@
   for (templist = tdata->files; templist != NULL; templist = templist->next)
     {
       tempfle = templist->data;
-      if (tempfle->startsize == 0 || tempfle->isdir)
+      if (tempfle->startsize == 0 || S_ISDIR (tempfle->st_mode))
         continue;
 
       while (action == -1)
--- a/src/uicommon/gftpui.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/uicommon/gftpui.c	Tue Jul 13 20:17:42 2004 +0000
@@ -1159,7 +1159,7 @@
             {
               tempfle = curfle->data;
 
-              if (tempfle->isdir)
+              if (S_ISDIR (tempfle->st_mode))
                 tdata->numdirs++;
               else
                 tdata->numfiles++;
@@ -1198,7 +1198,7 @@
       for (curfle = files; curfle != NULL; curfle = curfle->next)
         {
           tempfle = curfle->data;
-          if (tempfle->isdir)
+          if (S_ISDIR (tempfle->st_mode))
             tdata->numdirs++;
           else
             tdata->numfiles++;
@@ -1258,9 +1258,9 @@
 gftpui_common_transfer_files (gftp_transfer * tdata)
 {
   intptr_t preserve_permissions;
-  int i, mode, tofd, fromfd;
   struct timeval updatetime;
   ssize_t num_read, ret;
+  int i, tofd, fromfd;
   gftp_file * curfle; 
   char buf[8192];
 
@@ -1299,7 +1299,7 @@
       if (gftp_connect (tdata->fromreq) == 0 &&
           gftp_connect (tdata->toreq) == 0)
         {
-          if (curfle->isdir)
+          if (S_ISDIR (curfle->st_mode))
             {
               if (tdata->toreq->mkdir != NULL)
                 {
@@ -1446,12 +1446,8 @@
 
       if (!curfle->is_fd && preserve_permissions)
         {
-          if (curfle->attribs)
-            {
-              mode = gftp_parse_attribs (curfle->attribs);
-              if (mode != 0)
-                gftp_chmod (tdata->toreq, curfle->destfile, mode);
-            }
+          if (curfle->st_mode != 0)
+            gftp_chmod (tdata->toreq, curfle->destfile, curfle->st_mode);
 
           if (curfle->datetime != 0)
             gftp_set_file_time (tdata->toreq, curfle->destfile,
--- a/src/uicommon/gftpuicallbacks.c	Tue Jul 13 02:44:35 2004 +0000
+++ b/src/uicommon/gftpuicallbacks.c	Tue Jul 13 20:17:42 2004 +0000
@@ -106,9 +106,7 @@
       fle->file = g_strdup ("..");
       fle->user = g_malloc0 (1);
       fle->group = g_malloc0 (1);
-      fle->attribs = g_malloc0 (1);
-      *fle->attribs = '\0';
-      fle->isdir = 1;
+      fle->st_mode |= S_IFDIR;
       cdata->files = g_list_prepend (cdata->files, fle);
     }