/[mc]/mc/vfs/direntry.c
ViewVC logotype

Diff of /mc/vfs/direntry.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.74 by proski, Thu Oct 16 18:51:41 2003 UTC revision 1.75 by proski, Thu Oct 16 23:58:44 2003 UTC
# Line 35  Line 35 
35    
36  static volatile int total_inodes = 0, total_entries = 0;  static volatile int total_inodes = 0, total_entries = 0;
37    
 static struct vfs_s_entry *vfs_s_resolve_symlink (struct vfs_class * me, struct vfs_s_entry * entry,  
                                            char *path, int follow);  
   
38  struct vfs_s_inode *  struct vfs_s_inode *
39  vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *initstat)  vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *initstat)
40  {  {
# Line 214  vfs_s_automake (struct vfs_class *me, st Line 211  vfs_s_automake (struct vfs_class *me, st
211      return res;      return res;
212  }  }
213    
214    /* If the entry is a symlink, find the entry for its target */
215    static struct vfs_s_entry *
216    vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry,
217                           char *path, int follow)
218    {
219        char *linkname;
220        char *fullname = NULL;
221        struct vfs_s_entry *target;
222    
223        if (follow == LINK_NO_FOLLOW)
224            return entry;
225        if (follow == 0)
226            ERRNOR (ELOOP, NULL);
227        if (!entry)
228            ERRNOR (ENOENT, NULL);
229        if (!S_ISLNK (entry->ino->st.st_mode))
230            return entry;
231    
232        linkname = entry->ino->linkname;
233        if (linkname == NULL)
234            ERRNOR (EFAULT, NULL);
235    
236        /* make full path from relative */
237        if (*linkname != PATH_SEP) {
238            char *fullpath = vfs_s_fullpath (me, entry->dir);
239            fullname = g_strdup_printf ("%s/%s", fullpath, linkname);
240            linkname = fullname;
241            g_free (fullpath);
242        }
243    
244        target =
245            (MEDATA->find_entry) (me, entry->dir->super->root, linkname,
246                                  follow - 1, 0);
247        g_free (fullname);
248        return target;
249    }
250    
251  /*  /*
252   * Follow > 0: follow links, serves as loop protect,   * Follow > 0: follow links, serves as loop protect,
253   *       == -1: do not follow links   *       == -1: do not follow links
254   */   */
255  struct vfs_s_entry *  struct vfs_s_entry *
256  vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root, char *path, int follow, int flags)  vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
257                           char *path, int follow, int flags)
258  {  {
259      unsigned int pseg;      unsigned int pseg;
260      struct vfs_s_entry *ent = NULL;      struct vfs_s_entry *ent = NULL;
261      char p[MC_MAXPATHLEN] = "";      char p[MC_MAXPATHLEN] = "";
262    
263      while (root){      if (strlen(path) >= MC_MAXPATHLEN)
264            return NULL;
265    
266        while (root) {
267          int t;          int t;
268    
269          while (*path == PATH_SEP)       /* Strip leading '/' */          while (*path == PATH_SEP)       /* Strip leading '/' */
270              path++;              path++;
271    
272          if (!path [0])          if (!path[0])
273              return ent;              return ent;
274    
275          for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++)          for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++);
                 ;  
276    
277          strcat (p, PATH_SEP_STR);          strcat (p, PATH_SEP_STR);
278          strncpy (p + (t = strlen (p)), path, pseg);          strncpy (p + (t = strlen (p)), path, pseg);
279          p[t + pseg] = '\0';          p[t + pseg] = '\0';
280    
281          for (ent = root->subdir; ent != NULL; ent = ent->next)          for (ent = root->subdir; ent != NULL; ent = ent->next)
282              if (strlen (ent->name) == pseg && (!strncmp (ent->name, path, pseg)))              if (strlen (ent->name) == pseg
283                    && (!strncmp (ent->name, path, pseg)))
284                  /* FOUND! */                  /* FOUND! */
285                  break;                  break;
286    
287          if (!ent && (flags & (FL_MKFILE | FL_MKDIR)))          if (!ent && (flags & (FL_MKFILE | FL_MKDIR)))
288              ent = vfs_s_automake (me, root, path, flags);              ent = vfs_s_automake (me, root, path, flags);
289          if (!ent) ERRNOR (ENOENT, NULL);          if (!ent)
290                ERRNOR (ENOENT, NULL);
291          path += pseg;          path += pseg;
292  /* here we must follow leading directories always; only the actual file is optional */          /* here we must follow leading directories always;
293          if (!(ent = vfs_s_resolve_symlink (me, ent, p, strchr (path, PATH_SEP) ? LINK_FOLLOW : follow)))             only the actual file is optional */
294            ent =
295                vfs_s_resolve_symlink (me, ent, p,
296                                       strchr (path,
297                                               PATH_SEP) ? LINK_FOLLOW :
298                                       follow);
299            if (!ent)
300              return NULL;              return NULL;
301          root = ent->ino;          root = ent->ino;
302      }      }
# Line 344  vfs_s_find_inode (struct vfs_class *me, Line 389  vfs_s_find_inode (struct vfs_class *me,
389      return ent->ino;      return ent->ino;
390  }  }
391    
 static struct vfs_s_entry *  
 vfs_s_resolve_symlink (struct vfs_class *me, struct vfs_s_entry *entry, char *path, int follow)  
 {  
     char buf[MC_MAXPATHLEN], *linkname;  
   
     if (follow == LINK_NO_FOLLOW)  
         return entry;  
     if (follow == 0)  
         ERRNOR (ELOOP, NULL);  
     if (!entry)  
         ERRNOR (ENOENT, NULL);  
     if (!S_ISLNK (entry->ino->st.st_mode))  
         return entry;  
   
     linkname = entry->ino->linkname;  
   
     if (linkname == NULL)  
         ERRNOR (EFAULT, NULL);  
   
     if (MEDATA->find_entry == vfs_s_find_entry_linear) {  
         if (*linkname == PATH_SEP)  
             return (MEDATA->find_entry) (me, entry->dir->super->root,  
                                          linkname, follow - 1, 0);  
         else {  
             char *fullpath = vfs_s_fullpath (me, entry->dir);  
   
             g_snprintf (buf, sizeof (buf), "%s/%s", fullpath, linkname);  
             g_free (fullpath);  
             return (MEDATA->find_entry) (me, entry->dir->super->root, buf,  
                                          follow - 1, 0);  
         }  
     }  
   
     /* Convert absolute paths to relative ones */  
     if (*linkname == PATH_SEP) {  
         char *p, *q;  
   
         for (p = path, q = entry->ino->linkname; *p == *q; p++, q++);  
         while (*(--q) != PATH_SEP);  
         q++;  
         for (;; p++) {  
             p = strchr (p, PATH_SEP);  
             if (!p) {  
                 strcat (buf, q);  
                 break;  
             }  
             strcat (buf, "..");  
             strcat (buf, PATH_SEP_STR);  
         }  
         linkname = buf;  
     }  
   
     return (MEDATA->find_entry) (me, entry->dir, linkname, follow - 1, 0);  
 }  
   
392  /* Ook, these were functions around directory entries / inodes */  /* Ook, these were functions around directory entries / inodes */
393  /* -------------------------------- superblock games -------------------------- */  /* -------------------------------- superblock games -------------------------- */
394    
# Line 544  vfs_s_invalidate (struct vfs_class *me, Line 534  vfs_s_invalidate (struct vfs_class *me,
534  char *  char *
535  vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)  vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino)
536  {  {
537  /* For now, usable only on filesystems with _linear structure */      if (!ino->ent)
     if (MEDATA->find_entry != vfs_s_find_entry_linear)  
         vfs_die ("Implement me!");  
     if (!ino->ent) /* That must be directory... */  
538          ERRNOR (EAGAIN, NULL);          ERRNOR (EAGAIN, NULL);
539    
540      if ((!ino->ent->dir) || (!ino->ent->dir->ent)) /* It must be directory */      if (MEDATA->find_entry != vfs_s_find_entry_linear) {
541          return g_strdup (ino->ent->name);          char *newpath;
542            char *path = g_strdup (ino->ent->name);
543            while (1) {
544                ino = ino->ent->dir;
545                if (ino == ino->super->root)
546                    break;
547                newpath = g_strdup_printf ("%s/%s", ino->ent->name, path);
548                g_free (path);
549                path = newpath;
550            }
551            return path;
552        }
553    
554        /* It must be directory */
555        if ((!ino->ent->dir) || (!ino->ent->dir->ent))
556            return g_strdup (ino->ent->name);
557    
558      return  g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR,      return g_strconcat (ino->ent->dir->ent->name, PATH_SEP_STR,
559                              ino->ent->name, NULL);                          ino->ent->name, NULL);
560  }  }
561    
562  /* Support of archives */  /* Support of archives */

Legend:
Removed from v.1.74  
changed lines
  Added in v.1.75

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26