The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/umsdos/emd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  linux/fs/umsdos/emd.c
    3  *
    4  *  Written 1993 by Jacques Gelinas
    5  *
    6  *  Extended MS-DOS directory handling functions
    7  */
    8 
    9 #include <linux/types.h>
   10 #include <linux/fcntl.h>
   11 #include <linux/kernel.h>
   12 #include <linux/sched.h>
   13 #include <linux/errno.h>
   14 #include <linux/string.h>
   15 #include <linux/msdos_fs.h>
   16 #include <linux/umsdos_fs.h>
   17 #include <linux/dcache.h>
   18 #include <linux/pagemap.h>
   19 #include <linux/delay.h>
   20 
   21 void put_entry (struct umsdos_dirent *p, struct umsdos_dirent *q)
   22 {
   23         p->name_len = q->name_len;
   24         p->flags = q->flags;
   25         p->nlink = cpu_to_le16(q->nlink);
   26         p->uid = cpu_to_le16(q->uid);
   27         p->gid = cpu_to_le16(q->gid);
   28         p->atime = cpu_to_le32(q->atime);
   29         p->mtime = cpu_to_le32(q->mtime);
   30         p->ctime = cpu_to_le32(q->ctime);
   31         p->rdev = cpu_to_le16(q->rdev);
   32         p->mode = cpu_to_le16(q->mode);
   33 }
   34 
   35 static void get_entry(struct umsdos_dirent *p, struct umsdos_dirent *q)
   36 {
   37         p->name_len = q->name_len;
   38         p->name[p->name_len]='\0';
   39         p->flags = q->flags;
   40         p->nlink = le16_to_cpu (q->nlink);
   41         /* FIXME -- 32bit UID/GID issues */
   42         p->uid = le16_to_cpu (q->uid);
   43         p->gid = le16_to_cpu (q->gid);
   44         p->atime = le32_to_cpu (q->atime);
   45         p->mtime = le32_to_cpu (q->mtime);
   46         p->ctime = le32_to_cpu (q->ctime);
   47         p->rdev = le16_to_cpu (q->rdev);
   48         p->mode = le16_to_cpu (q->mode);
   49 }
   50 
   51 /*
   52  * Lookup the EMD dentry for a directory.
   53  *
   54  * Note: the caller must hold a lock on the parent directory.
   55  */
   56 struct dentry *umsdos_get_emd_dentry(struct dentry *parent)
   57 {
   58         struct dentry *demd;
   59 
   60         demd = umsdos_lookup_dentry(parent, UMSDOS_EMD_FILE, 
   61                                         UMSDOS_EMD_NAMELEN, 1);
   62         return demd;
   63 }
   64 
   65 /*
   66  * Check whether a directory has an EMD file.
   67  *
   68  * Note: the caller must hold a lock on the parent directory.
   69  */
   70 int umsdos_have_emd(struct dentry *dir)
   71 {
   72         struct dentry *demd = umsdos_get_emd_dentry (dir);
   73         int found = 0;
   74 
   75         if (!IS_ERR(demd)) {
   76                 if (demd->d_inode)
   77                         found = 1;
   78                 dput(demd);
   79         }
   80         return found;
   81 }
   82 
   83 /*
   84  * Create the EMD file for a directory if it doesn't
   85  * already exist. Returns 0 or an error code.
   86  *
   87  * Note: the caller must hold a lock on the parent directory.
   88  */
   89 int umsdos_make_emd(struct dentry *parent)
   90 {
   91         struct dentry *demd = umsdos_get_emd_dentry(parent);
   92         int err = PTR_ERR(demd);
   93 
   94         if (IS_ERR(demd)) {
   95                 printk("umsdos_make_emd: can't get dentry in %s, err=%d\n",
   96                         parent->d_name.name, err);
   97                 goto out;
   98         }
   99 
  100         /* already created? */
  101         err = 0;
  102         if (demd->d_inode)
  103                 goto out_set;
  104 
  105 Printk(("umsdos_make_emd: creating EMD %s/%s\n",
  106 parent->d_name.name, demd->d_name.name));
  107 
  108         err = msdos_create(parent->d_inode, demd, S_IFREG | 0777);
  109         if (err) {
  110                 printk (KERN_WARNING
  111                         "umsdos_make_emd: create %s/%s failed, err=%d\n",
  112                         parent->d_name.name, demd->d_name.name, err);
  113         }
  114 out_set:
  115         dput(demd);
  116 out:
  117         return err;
  118 }
  119 
  120 
  121 /*
  122  * Read an entry from the EMD file.
  123  * Support variable length record.
  124  * Return -EIO if error, 0 if OK.
  125  *
  126  * does not change {d,i}_count
  127  */
  128 
  129 int umsdos_emd_dir_readentry (struct dentry *demd, loff_t *pos, struct umsdos_dirent *entry)
  130 {
  131         struct address_space *mapping = demd->d_inode->i_mapping;
  132         struct page *page;
  133         struct umsdos_dirent *p;
  134         int offs = *pos & ~PAGE_CACHE_MASK;
  135         int recsize;
  136         int ret = 0;
  137 
  138         page = read_cache_page(mapping, *pos>>PAGE_CACHE_SHIFT,
  139                         (filler_t*)mapping->a_ops->readpage, NULL);
  140         if (IS_ERR(page))
  141                 goto sync_fail;
  142         wait_on_page(page);
  143         if (!Page_Uptodate(page))
  144                 goto async_fail;
  145         p = (struct umsdos_dirent*)(kmap(page)+offs);
  146 
  147         /* if this is an invalid entry (invalid name length), ignore it */
  148         if( p->name_len > UMSDOS_MAXNAME )
  149         {
  150                 printk (KERN_WARNING "Ignoring invalid EMD entry with size %d\n", entry->name_len);
  151                 p->name_len = 0; 
  152                 ret = -ENAMETOOLONG; /* notify umssync(8) code that something is wrong */
  153                 /* FIXME: does not work if we did 'ls -l' before 'udosctl uls' ?! */
  154         }
  155 
  156         recsize = umsdos_evalrecsize(p->name_len);
  157         if (offs + recsize > PAGE_CACHE_SIZE) {
  158                 struct page *page2;
  159                 int part = (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare;
  160                 page2 = read_cache_page(mapping, 1+(*pos>>PAGE_CACHE_SHIFT),
  161                                 (filler_t*)mapping->a_ops->readpage, NULL);
  162                 if (IS_ERR(page2)) {
  163                         kunmap(page);
  164                         page_cache_release(page);
  165                         page = page2;
  166                         goto sync_fail;
  167                 }
  168                 wait_on_page(page2);
  169                 if (!Page_Uptodate(page2)) {
  170                         kunmap(page);
  171                         page_cache_release(page2);
  172                         goto async_fail;
  173                 }
  174                 memcpy(entry->spare,p->spare,part);
  175                 memcpy(entry->spare+part,kmap(page2),
  176                                 recsize+offs-PAGE_CACHE_SIZE);
  177                 kunmap(page2);
  178                 page_cache_release(page2);
  179         } else
  180                 memcpy(entry->spare,p->spare,((char*)p+recsize)-p->spare);
  181         get_entry(entry, p);
  182         kunmap(page);
  183         page_cache_release(page);
  184         *pos += recsize;
  185         return ret;
  186 async_fail:
  187         page_cache_release(page);
  188         page = ERR_PTR(-EIO);
  189 sync_fail:
  190         return PTR_ERR(page);
  191 }
  192 
  193 
  194 /*
  195  * Write an entry in the EMD file.
  196  * Return 0 if OK, -EIO if some error.
  197  *
  198  * Note: the caller must hold a lock on the parent directory.
  199  */
  200 int umsdos_writeentry (struct dentry *parent, struct umsdos_info *info,
  201                                 int free_entry)
  202 {
  203         struct inode *dir = parent->d_inode;
  204         struct umsdos_dirent *entry = &info->entry;
  205         struct dentry *emd_dentry;
  206         int ret;
  207         struct umsdos_dirent entry0,*p;
  208         struct address_space *mapping;
  209         struct page *page, *page2 = NULL;
  210         int offs;
  211 
  212         emd_dentry = umsdos_get_emd_dentry(parent);
  213         ret = PTR_ERR(emd_dentry);
  214         if (IS_ERR(emd_dentry))
  215                 goto out;
  216         /* make sure there's an EMD file */
  217         ret = -EIO;
  218         if (!emd_dentry->d_inode) {
  219                 printk(KERN_WARNING
  220                         "umsdos_writeentry: no EMD file in %s/%s\n",
  221                         parent->d_parent->d_name.name, parent->d_name.name);
  222                 goto out_dput;
  223         }
  224 
  225         if (free_entry) {
  226                 /* #Specification: EMD file / empty entries
  227                  * Unused entries in the EMD file are identified
  228                  * by the name_len field equal to 0. However to
  229                  * help future extension (or bug correction :-( ),
  230                  * empty entries are filled with 0.
  231                  */
  232                 memset (&entry0, 0, sizeof (entry0));
  233                 entry = &entry0;
  234         } else if (entry->name_len > 0) {
  235                 memset (entry->name + entry->name_len, '\0', 
  236                         sizeof (entry->name) - entry->name_len);
  237                 /* #Specification: EMD file / spare bytes
  238                  * 10 bytes are unused in each record of the EMD. They
  239                  * are set to 0 all the time, so it will be possible
  240                  * to do new stuff and rely on the state of those
  241                  * bytes in old EMD files.
  242                  */
  243                 memset (entry->spare, 0, sizeof (entry->spare));
  244         }
  245 
  246         /* write the entry and update the parent timestamps */
  247         mapping = emd_dentry->d_inode->i_mapping;
  248         offs = info->f_pos & ~PAGE_CACHE_MASK;
  249         ret = -ENOMEM;
  250         page = grab_cache_page(mapping, info->f_pos>>PAGE_CACHE_SHIFT);
  251         if (!page)
  252                 goto out_dput;
  253         p = (struct umsdos_dirent *) (page_address(page) + offs);
  254         if (offs + info->recsize > PAGE_CACHE_SIZE) {
  255                 ret = mapping->a_ops->prepare_write(NULL,page,offs,
  256                                         PAGE_CACHE_SIZE);
  257                 if (ret)
  258                         goto out_unlock;
  259                 page2 = grab_cache_page(mapping,
  260                                         (info->f_pos>>PAGE_CACHE_SHIFT)+1);
  261                 if (!page2)
  262                         goto out_unlock2;
  263                 ret = mapping->a_ops->prepare_write(NULL,page2,0,
  264                                         offs+info->recsize-PAGE_CACHE_SIZE);
  265                 if (ret)
  266                         goto out_unlock3;
  267                 put_entry (p, entry);
  268                 memcpy(p->spare,entry->spare,
  269                         (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare);
  270                 memcpy(page_address(page2),
  271                                 ((char*)entry)+PAGE_CACHE_SIZE-offs,
  272                                 offs+info->recsize-PAGE_CACHE_SIZE);
  273                 ret = mapping->a_ops->commit_write(NULL,page2,0,
  274                                         offs+info->recsize-PAGE_CACHE_SIZE);
  275                 if (ret)
  276                         goto out_unlock3;
  277                 ret = mapping->a_ops->commit_write(NULL,page,offs,
  278                                         PAGE_CACHE_SIZE);
  279                 UnlockPage(page2);
  280                 page_cache_release(page2);
  281                 if (ret)
  282                         goto out_unlock;
  283         } else {
  284                 ret = mapping->a_ops->prepare_write(NULL,page,offs,
  285                                         offs + info->recsize);
  286                 if (ret)
  287                         goto out_unlock;
  288                 put_entry (p, entry);
  289                 memcpy(p->spare,entry->spare,((char*)p+info->recsize)-p->spare);
  290                 ret = mapping->a_ops->commit_write(NULL,page,offs,
  291                                         offs + info->recsize);
  292                 if (ret)
  293                         goto out_unlock;
  294         }
  295         UnlockPage(page);
  296         page_cache_release(page);
  297                 
  298         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  299         mark_inode_dirty(dir);
  300 
  301 out_dput:
  302         dput(emd_dentry);
  303 out:
  304         Printk (("umsdos_writeentry /mn/: returning %d...\n", ret));
  305         return ret;
  306 out_unlock3:
  307         UnlockPage(page2);
  308         page_cache_release(page2);
  309 out_unlock2:
  310         ClearPageUptodate(page);
  311         kunmap(page);
  312 out_unlock:
  313         UnlockPage(page);
  314         page_cache_release(page);
  315         printk ("UMSDOS:  problem with EMD file:  can't write\n");
  316         goto out_dput;
  317 }
  318 
  319 /*
  320  * General search, locate a name in the EMD file or an empty slot to
  321  * store it. if info->entry.name_len == 0, search the first empty
  322  * slot (of the proper size).
  323  * 
  324  * Return 0 if found, -ENOENT if not found, another error code if
  325  * other problem.
  326  * 
  327  * So this routine is used to either find an existing entry or to
  328  * create a new one, while making sure it is a new one. After you
  329  * get -ENOENT, you make sure the entry is stuffed correctly and
  330  * call umsdos_writeentry().
  331  * 
  332  * To delete an entry, you find it, zero out the entry (memset)
  333  * and call umsdos_writeentry().
  334  * 
  335  * All this to say that umsdos_writeentry must be called after this
  336  * function since it relies on the f_pos field of info.
  337  *
  338  * Note: the caller must hold a lock on the parent directory.
  339  */
  340 /* #Specification: EMD file structure
  341  * The EMD file uses a fairly simple layout.  It is made of records
  342  * (UMSDOS_REC_SIZE == 64).  When a name can't be written in a single
  343  * record, multiple contiguous records are allocated.
  344  */
  345 
  346 static int umsdos_find (struct dentry *demd, struct umsdos_info *info)
  347 {
  348         struct umsdos_dirent *entry = &info->entry;
  349         int recsize = info->recsize;
  350         struct inode *emd_dir;
  351         int ret = -ENOENT;
  352         struct {
  353                 off_t posok;    /* Position available to store the entry */
  354                 off_t one;      /* One empty position -> maybe <- large enough */
  355         } empty;
  356         int found = 0;
  357         int empty_size = 0;
  358         struct address_space *mapping;
  359         filler_t *readpage;
  360         struct page *page = NULL;
  361         int index = -1;
  362         int offs = PAGE_CACHE_SIZE,max_offs = PAGE_CACHE_SIZE;
  363         char *p = NULL;
  364         loff_t pos = 0;
  365 
  366         /* make sure there's an EMD file ... */
  367         ret = -ENOENT;
  368         emd_dir = demd->d_inode;
  369         if (!emd_dir)
  370                 goto out_dput;
  371         mapping = emd_dir->i_mapping;
  372         readpage = (filler_t*)mapping->a_ops->readpage;
  373 
  374         empty.posok = emd_dir->i_size;
  375         while (1) {
  376                 struct umsdos_dirent *rentry;
  377                 int entry_size;
  378 
  379                 if (offs >= max_offs) {
  380                         if (page) {
  381                                 kunmap(page);
  382                                 page_cache_release(page);
  383                                 page = NULL;
  384                         }
  385                         if (pos >= emd_dir->i_size) {
  386                                 info->f_pos = empty.posok;
  387                                 break;
  388                         }
  389                         if (++index == (emd_dir->i_size>>PAGE_CACHE_SHIFT))
  390                                 max_offs = emd_dir->i_size & ~PAGE_CACHE_MASK;
  391                         offs -= PAGE_CACHE_SIZE;
  392                         page = read_cache_page(mapping,index,readpage,NULL);
  393                         if (IS_ERR(page))
  394                                 goto sync_fail;
  395                         wait_on_page(page);
  396                         if (!Page_Uptodate(page))
  397                                 goto async_fail;
  398                         p = kmap(page);
  399                 }
  400 
  401                 rentry = (struct umsdos_dirent *)(p+offs);
  402 
  403                 if (rentry->name_len == 0) {
  404                         /* We are looking for an empty section at least */
  405                         /* as large as recsize. */
  406                         if (entry->name_len == 0) {
  407                                 info->f_pos = pos;
  408                                 ret = 0;
  409                                 break;
  410                         }
  411                         offs += UMSDOS_REC_SIZE;
  412                         pos += UMSDOS_REC_SIZE;
  413                         if (found)
  414                                 continue;
  415                         if (!empty_size)
  416                                 empty.one = pos-UMSDOS_REC_SIZE;
  417                         empty_size += UMSDOS_REC_SIZE;
  418                         if (empty_size == recsize) {
  419                                 /* Here is a large enough section. */
  420                                 empty.posok = empty.one;
  421                                 found = 1;
  422                         }
  423                         continue;
  424                 }
  425 
  426                 entry_size = umsdos_evalrecsize(rentry->name_len);
  427                 if (entry_size > PAGE_CACHE_SIZE)
  428                         goto async_fail;
  429                 empty_size = 0;
  430                 if (entry->name_len != rentry->name_len)
  431                         goto skip_it;
  432 
  433                 if (entry_size + offs > PAGE_CACHE_SIZE) {
  434                         /* Sucker spans the page boundary */
  435                         int len = (p+PAGE_CACHE_SIZE)-rentry->name;
  436                         struct page *next_page;
  437                         char *q;
  438                         next_page = read_cache_page(mapping,index+1,readpage,NULL);
  439                         if (IS_ERR(next_page)) {
  440                                 page_cache_release(page);
  441                                 page = next_page;
  442                                 goto sync_fail;
  443                         }
  444                         wait_on_page(next_page);
  445                         if (!Page_Uptodate(next_page)) {
  446                                 page_cache_release(page);
  447                                 page = next_page;
  448                                 goto async_fail;
  449                         }
  450                         q = kmap(next_page);
  451                         if (memcmp(entry->name, rentry->name, len) ||
  452                             memcmp(entry->name+len, q, entry->name_len-len)) {
  453                                 kunmap(next_page);
  454                                 page_cache_release(next_page);
  455                                 goto skip_it;
  456                         }
  457                         kunmap(next_page);
  458                         page_cache_release(next_page);
  459                 } else if (memcmp (entry->name, rentry->name, entry->name_len))
  460                         goto skip_it;
  461 
  462                 info->f_pos = pos;
  463                 get_entry(entry, rentry);
  464                 ret = 0;
  465                 break;
  466 skip_it:
  467                 offs+=entry_size;
  468                 pos+=entry_size;
  469         }
  470         if (page) {
  471                 kunmap(page);
  472                 page_cache_release(page);
  473         }
  474         umsdos_manglename (info);
  475 
  476 out_dput:
  477         dput(demd);
  478         return ret;
  479 
  480 async_fail:
  481         page_cache_release(page);
  482         page = ERR_PTR(-EIO);
  483 sync_fail:
  484         return PTR_ERR(page);
  485 }
  486 
  487 
  488 /*
  489  * Add a new entry in the EMD file.
  490  * Return 0 if OK or a negative error code.
  491  * Return -EEXIST if the entry already exists.
  492  *
  493  * Complete the information missing in info.
  494  * 
  495  * N.B. What if the EMD file doesn't exist?
  496  */
  497 
  498 int umsdos_newentry (struct dentry *parent, struct umsdos_info *info)
  499 {
  500         int err, ret = -EEXIST;
  501         struct dentry *demd = umsdos_get_emd_dentry(parent);
  502 
  503         ret = PTR_ERR(demd);
  504         if (IS_ERR(demd))
  505                 goto out;
  506         err = umsdos_find (demd, info);
  507         if (err && err == -ENOENT) {
  508                 ret = umsdos_writeentry (parent, info, 0);
  509                 Printk (("umsdos_writeentry EMD ret = %d\n", ret));
  510         }
  511 out:
  512         return ret;
  513 }
  514 
  515 
  516 /*
  517  * Create a new hidden link.
  518  * Return 0 if OK, an error code if not.
  519  */
  520 
  521 /* #Specification: hard link / hidden name
  522  * When a hard link is created, the original file is renamed
  523  * to a hidden name. The name is "..LINKNNN" where NNN is a
  524  * number define from the entry offset in the EMD file.
  525  */
  526 int umsdos_newhidden (struct dentry *parent, struct umsdos_info *info)
  527 {
  528         int ret;
  529         struct dentry *demd = umsdos_get_emd_dentry(parent);
  530         ret = PTR_ERR(demd);
  531         if (IS_ERR(demd))
  532                 goto out;
  533 
  534         umsdos_parse ("..LINK", 6, info);
  535         info->entry.name_len = 0;
  536         ret = umsdos_find (demd, info);
  537         if (ret == -ENOENT || ret == 0) {
  538                 info->entry.name_len = sprintf (info->entry.name,
  539                                                 "..LINK%ld", info->f_pos);
  540                 ret = 0;
  541         }
  542 out:
  543         return ret;
  544 }
  545 
  546 
  547 /*
  548  * Remove an entry from the EMD file.
  549  * Return 0 if OK, a negative error code otherwise.
  550  * 
  551  * Complete the information missing in info.
  552  */
  553 
  554 int umsdos_delentry (struct dentry *parent, struct umsdos_info *info, int isdir)
  555 {
  556         int ret;
  557         struct dentry *demd = umsdos_get_emd_dentry(parent);
  558 
  559         ret = PTR_ERR(demd);
  560         if (IS_ERR(demd))
  561                 goto out;
  562         ret = umsdos_find (demd, info);
  563         if (ret)
  564                 goto out;
  565         if (info->entry.name_len == 0)
  566                 goto out;
  567 
  568         if ((isdir != 0) != (S_ISDIR (info->entry.mode) != 0)) {
  569                 if (S_ISDIR (info->entry.mode)) {
  570                         ret = -EISDIR;
  571                 } else {
  572                         ret = -ENOTDIR;
  573                 }
  574                 goto out;
  575         }
  576         ret = umsdos_writeentry (parent, info, 1);
  577 
  578 out:
  579         return ret;
  580 }
  581 
  582 
  583 /*
  584  * Verify that an EMD directory is empty.
  585  * Return: 
  586  * 0 if not empty,
  587  * 1 if empty (except for EMD file),
  588  * 2 if empty or no EMD file.
  589  */
  590 
  591 int umsdos_isempty (struct dentry *dentry)
  592 {
  593         struct dentry *demd;
  594         int ret = 2;
  595         loff_t pos = 0;
  596 
  597         demd = umsdos_get_emd_dentry(dentry);
  598         if (IS_ERR(demd))
  599                 goto out;
  600         /* If the EMD file does not exist, it is certainly empty. :-) */
  601         if (!demd->d_inode)
  602                 goto out_dput;
  603 
  604         ret = 1;
  605         while (pos < demd->d_inode->i_size) {
  606                 struct umsdos_dirent entry;
  607 
  608                 if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0) {
  609                         ret = 0;
  610                         break;
  611                 }
  612                 if (entry.name_len != 0) {
  613                         ret = 0;
  614                         break;
  615                 }
  616         }
  617 
  618 out_dput:
  619         dput(demd);
  620 out:
  621         return ret;
  622 }
  623 
  624 /*
  625  * Locate an entry in a EMD directory.
  626  * Return 0 if OK, error code if not, generally -ENOENT.
  627  *
  628  * expect argument:
  629  *      0: anything
  630  *      1: file
  631  *      2: directory
  632  */
  633 
  634 int umsdos_findentry (struct dentry *parent, struct umsdos_info *info,
  635                         int expect)
  636 {               
  637         int ret;
  638         struct dentry *demd = umsdos_get_emd_dentry(parent);
  639 
  640         ret = PTR_ERR(demd);
  641         if (IS_ERR(demd))
  642                 goto out;
  643         ret = umsdos_find (demd, info);
  644         if (ret)
  645                 goto out;
  646 
  647         switch (expect) {
  648         case 1:
  649                 if (S_ISDIR (info->entry.mode))
  650                         ret = -EISDIR;
  651                 break;
  652         case 2:
  653                 if (!S_ISDIR (info->entry.mode))
  654                         ret = -ENOTDIR;
  655         }
  656 
  657 out:
  658         Printk (("umsdos_findentry: returning %d\n", ret));
  659         return ret;
  660 }

Cache object: e6f63fdda4789d41375b4985ba81a10d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.