Browse Source

fish: partially fixed perl backend for FISH
Broken:
* spacy files are still broken (like " a b")
Changes:
* vfs/fish.c learned to parse 'R' (raw filemode)
* fixed perl backend escaping

Signed-off-by: Sergei Trofimovich <slyfox@inbox.ru>

Sergei Trofimovich 16 years ago
parent
commit
a944b8ca5b
3 changed files with 84 additions and 6 deletions
  1. 24 6
      vfs/fish.c
  2. 58 0
      vfs/utilvfs.c
  3. 2 0
      vfs/utilvfs.h

+ 24 - 6
vfs/fish.c

@@ -392,19 +392,30 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
 		   "while( (my $filename = readdir(DIR))){\n"
 		   "while( (my $filename = readdir(DIR))){\n"
 		   "my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = lstat(\"$dirname/$filename\");\n"
 		   "my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = lstat(\"$dirname/$filename\");\n"
 		   "my $mloctime= scalar localtime $mtime;\n"
 		   "my $mloctime= scalar localtime $mtime;\n"
+		   "\n"
+		   "# shell escs are taken from here: http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html\n"
+		   "  sub esc_shell_chars {\n"
+		   "     my $s = $_[0];\n"
+		   "     $s =~ s/([;<>\\*\\|`&\\$!#\\(\\)\\[\\]\\{\\}:'\\''\"\\ ])/\\\\$1/g;\n"
+		   "     return $s;\n"
+		   "  }\n"
+		   "\n"
+		   "my $e_filename = esc_shell_chars($filename);\n"
 		   "if (S_ISLNK($mode) ) {\n"
 		   "if (S_ISLNK($mode) ) {\n"
 		   "my $linkname = readlink (\"$dirname/$filename\");\n"
 		   "my $linkname = readlink (\"$dirname/$filename\");\n"
-			  "printf(\"P$mode $uid.$gid\\n"
+		   "my $e_linkname = esc_shell_chars($linkname);\n"
+		   "\n"
+			  "printf(\"R%%o %%o $uid.$gid\\n"
 				    "S$size\\n"
 				    "S$size\\n"
 				    "d$mloctime\\n"
 				    "d$mloctime\\n"
-				    ":\\\"$filename\\\" -> \\\"$linkname\\\"\\n"
-				    "\\n\");\n"
+				    ":\\\"$e_filename\\\" -> \\\"$e_linkname\\\"\\n"
+				    "\\n\", S_IMODE($mode), S_IFMT($mode));\n"
 		   "} else {\n"
 		   "} else {\n"
-			  "printf(\"P$mode $uid.$gid\\n"
+			  "printf(\"R%%o %%o $uid.$gid\\n"
 				    "S$size\\n"
 				    "S$size\\n"
 				    "d$mloctime\\n"
 				    "d$mloctime\\n"
-				    ":\\\"$filename\\\"\\n"
-				    "\\n\");\n"
+				    ":\\\"$e_filename\\\"\\n"
+				    "\\n\", S_IMODE($mode), S_IFMT($mode));\n"
 		   "}}\n"
 		   "}}\n"
 		   "printf(\"### 200\\n\");\n"
 		   "printf(\"### 200\\n\");\n"
 		   "closedir(DIR);\n"
 		   "closedir(DIR);\n"
@@ -544,6 +555,13 @@ fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
 	    vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode);
 	    vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode);
 	    break;
 	    break;
 	}
 	}
+	case 'R': {
+	    // raw filemode:
+	    // we expect: Roctal-filemode octal-filetype uid.gid
+	    size_t skipped;
+	    vfs_parse_raw_filemode (buffer + 1, &skipped, &ST.st_mode);
+	    break;
+	}
 	case 'd': {
 	case 'd': {
 		      vfs_split_text(buffer+1);
 		      vfs_split_text(buffer+1);
 		      if (!vfs_parse_filedate(0, &ST.st_ctime))
 		      if (!vfs_parse_filedate(0, &ST.st_ctime))

+ 58 - 0
vfs/utilvfs.c

@@ -539,6 +539,64 @@ vfs_parse_filemode (const char *s, size_t *ret_skipped,
     return TRUE;
     return TRUE;
 }
 }
 
 
+gboolean
+vfs_parse_raw_filemode (const char *s, size_t *ret_skipped,
+		    mode_t *ret_mode)
+{
+    const char *p;
+    mode_t remote_type = 0, local_type, perms = 0;
+
+    p = s;
+
+    // isoctal
+    while(*p >= '0' && *p <= '7')
+    {
+	perms *= 010;
+	perms += (*p - '0');
+	++p;
+    }
+
+    if (*p++ != ' ')
+	return FALSE;
+
+    while(*p >= '0' && *p <= '7')
+    {
+	remote_type *= 010;
+	remote_type += (*p - '0');
+	++p;
+    }
+
+    if (*p++ != ' ')
+	return FALSE;
+
+    /* generated with:
+        $ perl -e 'use Fcntl ":mode";
+                   my @modes = (S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFREG);
+                   foreach $t (@modes) { printf ("%o\n", $t); };'
+        TODO: S_IFDOOR, S_IFIFO, S_IFSOCK (if supported by os)
+              (see vfs_parse_filetype)
+     */
+
+    switch (remote_type)
+    {
+	case 020000:
+	    local_type = S_IFCHR; break;
+	case 040000:
+	    local_type = S_IFDIR; break;
+	case 060000:
+	    local_type = S_IFBLK; break;
+	case 0120000:
+	    local_type = S_IFLNK; break;
+	case 0100000:
+	default:// don't know what is it
+	    local_type = S_IFREG; break;
+    }
+
+    *ret_skipped = p - s;
+    *ret_mode = local_type | perms;
+    return TRUE;
+}
+
 /* This function parses from idx in the columns[] array */
 /* This function parses from idx in the columns[] array */
 int
 int
 vfs_parse_filedate (int idx, time_t *t)
 vfs_parse_filedate (int idx, time_t *t)

+ 2 - 0
vfs/utilvfs.h

@@ -24,6 +24,8 @@ gboolean vfs_parse_fileperms (const char *s, size_t *ret_skipped,
 			      mode_t *ret_perms);
 			      mode_t *ret_perms);
 gboolean vfs_parse_filemode (const char *s, size_t *ret_skipped,
 gboolean vfs_parse_filemode (const char *s, size_t *ret_skipped,
 			     mode_t *ret_mode);
 			     mode_t *ret_mode);
+gboolean vfs_parse_raw_filemode (const char *s, size_t *ret_skipped,
+			     mode_t *ret_mode);
 
 
 int vfs_parse_ls_lga (const char *p, struct stat *s, char **filename,
 int vfs_parse_ls_lga (const char *p, struct stat *s, char **filename,
 		      char **linkname);
 		      char **linkname);