Пример #1
0
gboolean
vfs_parse_ls_lga (const char *p, struct stat * s, char **filename, char **linkname,
                  size_t * num_spaces)
{
    int idx, idx2, num_cols;
    int i;
    char *p_copy = NULL;
    char *t = NULL;
    const char *line = p;
    size_t skipped;

    if (strncmp (p, "total", 5) == 0)
        return FALSE;

    if (!vfs_parse_filetype (p, &skipped, &s->st_mode))
        goto error;
    p += skipped;

    if (*p == ' ')              /* Notwell 4 */
        p++;
    if (*p == '[')
    {
        if (strlen (p) <= 8 || p[8] != ']')
            goto error;
        /* Should parse here the Notwell permissions :) */
        if (S_ISDIR (s->st_mode))
            s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH);
        else
            s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
        p += 9;
    }
    else
    {
        size_t lc_skipped;
        mode_t perms;

        if (!vfs_parse_fileperms (p, &lc_skipped, &perms))
            goto error;
        p += lc_skipped;
        s->st_mode |= perms;
    }

    p_copy = g_strdup (p);
    num_cols = vfs_split_text (p_copy);

    s->st_nlink = atol (columns[0]);
    if (s->st_nlink <= 0)
        goto error;

    if (!is_num (1))
        s->st_uid = vfs_finduid (columns[1]);
    else
        s->st_uid = (uid_t) atol (columns[1]);

    /* Mhm, the ls -lg did not produce a group field */
    for (idx = 3; idx <= 5; idx++)
        if (is_month (columns[idx], NULL) || is_week (columns[idx], NULL)
            || is_dos_date (columns[idx]) || is_localized_month (columns[idx]))
            break;

    if (idx == 6 || (idx == 5 && !S_ISCHR (s->st_mode) && !S_ISBLK (s->st_mode)))
        goto error;

    /* We don't have gid */
    if (idx == 3 || (idx == 4 && (S_ISCHR (s->st_mode) || S_ISBLK (s->st_mode))))
        idx2 = 2;
    else
    {
        /* We have gid field */
        if (is_num (2))
            s->st_gid = (gid_t) atol (columns[2]);
        else
            s->st_gid = vfs_findgid (columns[2]);
        idx2 = 3;
    }

    /* This is device */
    if (S_ISCHR (s->st_mode) || S_ISBLK (s->st_mode))
    {
        int maj, min;

        /* Corner case: there is no whitespace(s) between maj & min */
        if (!is_num (idx2) && idx2 == 2)
        {
            if (!is_num (++idx2) || sscanf (columns[idx2], " %d,%d", &maj, &min) != 2)
                goto error;
        }
        else
        {
            if (!is_num (idx2) || sscanf (columns[idx2], " %d,", &maj) != 1)
                goto error;

            if (!is_num (++idx2) || sscanf (columns[idx2], " %d", &min) != 1)
                goto error;
        }
#ifdef HAVE_STRUCT_STAT_ST_RDEV
        s->st_rdev = makedev (maj, min);
#endif
        s->st_size = 0;

    }
    else
    {
        /* Common file size */
        if (!is_num (idx2))
            goto error;

        s->st_size = (off_t) g_ascii_strtoll (columns[idx2], NULL, 10);
#ifdef HAVE_STRUCT_STAT_ST_RDEV
        s->st_rdev = 0;
#endif
    }

    idx = vfs_parse_filedate (idx, &s->st_mtime);
    if (!idx)
        goto error;
    /* Use resulting time value */
    s->st_atime = s->st_ctime = s->st_mtime;
    /* s->st_dev and s->st_ino must be initialized by vfs_s_new_inode () */
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    s->st_blksize = 512;
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    s->st_blocks = (s->st_size + 511) / 512;
#endif

    if (num_spaces != NULL)
    {
        *num_spaces = column_ptr[idx] - column_ptr[idx - 1] - strlen (columns[idx - 1]);
        if (strcmp (columns[idx], "..") == 0)
            vfs_parce_ls_final_num_spaces = *num_spaces;
    }

    for (i = idx + 1, idx2 = 0; i < num_cols; i++)
        if (strcmp (columns[i], "->") == 0)
        {
            idx2 = i;
            break;
        }

    if (((S_ISLNK (s->st_mode) || (num_cols == idx + 3 && s->st_nlink > 1)))    /* Maybe a hardlink? (in extfs) */
        && idx2)
    {

        if (filename)
        {
            *filename = g_strndup (p + column_ptr[idx], column_ptr[idx2] - column_ptr[idx] - 1);
        }
        if (linkname)
        {
            t = g_strdup (p + column_ptr[idx2 + 1]);
            *linkname = t;
        }
    }
    else
    {
        /* Extract the filename from the string copy, not from the columns
         * this way we have a chance of entering hidden directories like ". ."
         */
        if (filename)
        {
            /*
             * filename = g_strdup (columns [idx++]);
             */

            t = g_strdup (p + column_ptr[idx]);
            *filename = t;
        }
        if (linkname)
            *linkname = NULL;
    }

    if (t)
    {
        int p2 = strlen (t);
        if ((--p2 > 0) && (t[p2] == '\r' || t[p2] == '\n'))
            t[p2] = 0;
        if ((--p2 > 0) && (t[p2] == '\r' || t[p2] == '\n'))
            t[p2] = 0;
    }

    g_free (p_copy);
    return TRUE;

  error:
    {
        static int errorcount = 0;

        if (++errorcount < 5)
        {
            message (D_ERROR, _("Cannot parse:"), "%s", (p_copy && *p_copy) ? p_copy : line);
        }
        else if (errorcount == 5)
            message (D_ERROR, MSG_ERROR, _("More parsing errors will be ignored."));
    }

    g_free (p_copy);
    return FALSE;
}
Пример #2
0
Файл: fish.c Проект: dborca/mc
static int
fish_dir_load(struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
{
    struct vfs_s_super *super = dir->super;
    char buffer[8192];
    struct vfs_s_entry *ent = NULL;
    FILE *logfile;
    char *quoted_path;

    logfile = MEDATA->logfile;

    print_vfs_message(_("fish: Reading directory %s..."), remote_path);

    gettimeofday(&dir->timestamp, NULL);
    dir->timestamp.tv_sec += fish_directory_timeout;
    quoted_path = name_quote (remote_path, 0);
    fish_command (me, super, NONE,
	    /* XXX no -L here, unless -L in RETR; otherwise we'll be inconsistent */
	    /* XXX The trailing slash is needed to accomodate directory symlinks */
	    "#LIST /%s\n"
	    "ls -lan /%s/ 2>/dev/null | grep '^[^cbt]' | (\n"
	      "while read p l u g s m d y n; do\n"
	        "echo \"P$p $u.$g\nS$s\nd$m $d $y\n:$n\n\"\n"
	      "done\n"
	    ")\n"
	    "ls -lan /%s/ 2>/dev/null | grep '^[cb]' | (\n"
	      "while read p l u g a i m d y n; do\n"
	        "echo \"P$p $u.$g\nE$a$i\nd$m $d $y\n:$n\n\"\n"
	      "done\n"
	    ")\n"
	    "echo '### 200'\n",
	    remote_path, quoted_path, quoted_path);
    g_free (quoted_path);
    ent = vfs_s_generate_entry(me, NULL, dir, 0);
    while (1) {
	int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr); 
	if ((!res) || (res == EINTR)) {
	    vfs_s_free_entry(me, ent);
	    me->verrno = ECONNRESET;
	    goto error;
	}
	if (logfile) {
	    fputs (buffer, logfile);
            fputs ("\n", logfile);
	    fflush (logfile);
	}
	if (!strncmp(buffer, "### ", 4))
	    break;
	if ((!buffer[0])) {
	    if (ent->name) {
#define ST ent->ino->st
		if (S_ISLNK(ST.st_mode) && ent->ino->linkname == NULL) {
		    /* Symlink, without 'L' reply.  We assume the name has this form
		     * <pathname of link> -> <contents of link> and that size is the
		     * number of characters in <contents of link>
		     */
		    const char *lsep = " -> ";
		    const int lsep_len = strlen(lsep);
		    int real_len = strlen(ent->name) - ST.st_size - lsep_len;
		    if (real_len > 0 && !strncmp(ent->name + real_len, lsep, lsep_len)) {
			ent->ino->linkname = g_strdup(ent->name + real_len + lsep_len);
			ent->name[real_len] = '\0';
		    } else {
			ST.st_mode = 0;
		    }
		}
		vfs_s_insert_entry(me, dir, ent);
		ent = vfs_s_generate_entry(me, NULL, dir, 0);
	    }
	    continue;
	}

	switch(buffer[0]) {
	case ':': {
		      if (!strcmp(buffer+1, ".") || !strcmp(buffer+1, ".."))
			  break;  /* We'll do . and .. ourself */
		      ent->name = g_strdup(buffer+1); 
		      break;
	          }
	case 'S':
#ifdef HAVE_ATOLL
	    ST.st_size = (off_t) atoll (buffer+1);
#else
	    ST.st_size = (off_t) atof (buffer+1);
#endif
	    break;
	case 'P': {
	    size_t skipped;

	    if (vfs_parse_filemode (buffer + 1, &skipped, &ST.st_mode)) {
		/*if (S_ISLNK(ST.st_mode))
		    ST.st_mode = 0; XXX we'll deal with it, eventually */
	    }
	    break;
	}
	case 'd': {
		      vfs_split_text(buffer+1);
		      if (!vfs_parse_filedate(0, &ST.st_ctime))
			  break;
		      ST.st_atime = ST.st_mtime = ST.st_ctime;
		  }
	          break;
	case 'D': {
	              struct tm tim;
		      if (sscanf(buffer+1, "%d %d %d %d %d %d", &tim.tm_year, &tim.tm_mon, 
				 &tim.tm_mday, &tim.tm_hour, &tim.tm_min, &tim.tm_sec) != 6)
			  break;
		      ST.st_atime = ST.st_mtime = ST.st_ctime = mktime(&tim);
	          }
	          break;
	case 'E': {
	              int maj, min;
	              if (sscanf(buffer+1, "%d,%d", &maj, &min) != 2)
			  break;
#ifdef HAVE_STRUCT_STAT_ST_RDEV
		      ST.st_rdev = makedev (maj, min);
#endif
	          }
	case 'L': ent->ino->linkname = g_strdup(buffer+1);
	          break;
	}
    }
    
    vfs_s_free_entry (me, ent);
    me->verrno = E_REMOTE;
    if (fish_decode_reply(buffer+4, 0) == COMPLETE) {
	g_free (SUP.cwdir);
	SUP.cwdir = g_strdup (remote_path);
	print_vfs_message (_("%s: done."), me->name);
	return 0;
    }

error:
    print_vfs_message (_("%s: failure"), me->name);
    return 1;
}