root/fs/smbfs/dir.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. str_upper
  2. str_lower
  3. smb_dir_read
  4. smb_readdir
  5. smb_init_dir_cache
  6. smb_invalid_dir_cache
  7. smb_free_dir_cache
  8. get_pname_static
  9. get_pname
  10. put_pname
  11. smb_iget
  12. smb_free_inode_info
  13. smb_init_root
  14. smb_stat_root
  15. smb_free_all_inodes
  16. smb_invalidate_all_inodes
  17. smb_find_inode
  18. smb_lookup
  19. smb_create
  20. smb_mkdir
  21. smb_rmdir
  22. smb_unlink
  23. smb_rename

   1 /*
   2  *  dir.c
   3  *
   4  *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
   5  *
   6  */
   7 
   8 #include <linux/config.h>
   9 #ifdef MODULE
  10 #include <linux/module.h>
  11 #include <linux/version.h>
  12 #endif
  13 
  14 #include <linux/sched.h>
  15 #include <linux/errno.h>
  16 #include <linux/stat.h>
  17 #include <linux/kernel.h>
  18 #include <linux/malloc.h>
  19 #include <linux/mm.h>
  20 #include <linux/smb_fs.h>
  21 #include <asm/segment.h>
  22 #include <linux/errno.h>
  23 
  24 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  25 #define ROUND_UP(x) (((x)+3) & ~3)
  26 
  27 static int 
  28 smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
  29 
  30 static int 
  31 smb_readdir(struct inode *inode, struct file *filp,
  32             void *dirent, filldir_t filldir);
  33 
  34 static int 
  35 get_pname(struct inode *dir, const char *name, int len,
  36           char **res_path, int *res_len);
  37 
  38 static int
  39 get_pname_static(struct inode *dir, const char *name, int len,
  40                  char *path, int *res_len);
  41 
  42 static struct inode *
  43 smb_iget(struct inode *dir, char *path, struct smb_dirent *finfo);
  44 
  45 static void 
  46 put_pname(char *path);
  47 
  48 static struct smb_inode_info *
  49 smb_find_inode(struct smb_server *server, const char *path);
  50 
  51 static int
  52 smb_lookup(struct inode *dir, const char *__name,
  53            int len, struct inode **result);
  54 
  55 static int 
  56 smb_create(struct inode *dir, const char *name, int len, int mode, 
  57            struct inode **result);
  58 
  59 static int 
  60 smb_mkdir(struct inode *dir, const char *name, int len, int mode);
  61 
  62 static int 
  63 smb_rmdir(struct inode *dir, const char *name, int len);
  64 
  65 static int
  66 smb_unlink(struct inode *dir, const char *name, int len);
  67 
  68 static int
  69 smb_rename(struct inode *old_dir, const char *old_name, int old_len, 
  70            struct inode *new_dir, const char *new_name, int new_len);
  71 
  72 static inline void str_upper(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74         while (*name) {
  75                 if (*name >= 'a' && *name <= 'z')
  76                         *name -= ('a' - 'A');
  77                 name++;
  78         }
  79 }
  80 
  81 static inline void str_lower(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         while (*name) {
  84                 if (*name >= 'A' && *name <= 'Z')
  85                         *name += ('a' - 'A');
  86                 name ++;
  87         }
  88 }
  89 
  90 static struct file_operations smb_dir_operations = {
  91         NULL,                   /* lseek - default */
  92         smb_dir_read,           /* read - bad */
  93         NULL,                   /* write - bad */
  94         smb_readdir,            /* readdir */
  95         NULL,                   /* select - default */
  96         smb_ioctl,              /* ioctl - default */
  97         NULL,                   /* mmap */
  98         NULL,                   /* no special open code */
  99         NULL,                   /* no special release code */
 100         NULL                    /* fsync */
 101 };
 102 
 103 struct inode_operations smb_dir_inode_operations = 
 104 {
 105         &smb_dir_operations,    /* default directory file ops */
 106         smb_create,             /* create */
 107         smb_lookup,             /* lookup */
 108         NULL,                   /* link */
 109         smb_unlink,             /* unlink */
 110         NULL,                   /* symlink */
 111         smb_mkdir,              /* mkdir */
 112         smb_rmdir,              /* rmdir */
 113         NULL,                   /* mknod */
 114         smb_rename,             /* rename */
 115         NULL,                   /* readlink */
 116         NULL,                   /* follow_link */
 117         NULL,                   /* bmap */
 118         NULL,                   /* truncate */
 119         NULL,                   /* permission */
 120         NULL                    /* smap */
 121 };
 122 
 123 
 124 static int 
 125 smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127         return -EISDIR;
 128 }
 129 
 130 /*
 131  * Description:
 132  *  smb_readdir provides a listing in the form of filling the dirent structure.
 133  *  Note that dirent resides in the user space. This is to support reading of a
 134  *  directory "stream". 
 135  * Arguments:
 136  *  inode   ---  Pointer to to the directory.
 137  *  filp    ---  The directory stream. (filp->f_pos indicates
 138  *               position in the stream.)
 139  *  dirent  ---  Will hold count directory entries. (Is in user space.)
 140  *  count   ---  Number of entries to be read. Should indicate the total 
 141  *               buffer space available for filling with dirents.
 142  * Return values:
 143  *     < 0     ---  An error occured (linux/errno.h).
 144  *     = 0     ---
 145  *     > 0     ---  Success, amount of bytes written to dirent.
 146  * Notes:
 147  *     Since we want to reduce directory lookups we revert into a
 148  *     dircache. It is taken rather directly out of the nfs_readdir.
 149  */
 150 
 151 /* In smbfs, we have unique inodes across all mounted filesystems, for
 152    all inodes that are in memory. That's why it's enough to index the
 153    directory cache by the inode number. */
 154 
 155 static unsigned long      c_ino = 0;
 156 static int                c_size;
 157 static int                c_seen_eof;
 158 static int                c_last_returned_index;
 159 static struct smb_dirent* c_entry = NULL;
 160 
 161 static int
 162 smb_readdir(struct inode *inode, struct file *filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 163             void *dirent, filldir_t filldir)
 164 {
 165         int result, i = 0;
 166         int index = 0;
 167         struct smb_dirent *entry = NULL;
 168         struct smb_server *server = SMB_SERVER(inode);
 169 
 170         DDPRINTK("smb_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
 171         DDPRINTK("smb_readdir: inode->i_ino = %ld, c_ino = %ld\n",
 172                  inode->i_ino, c_ino);
 173 
 174         if (!inode || !S_ISDIR(inode->i_mode)) {
 175                 printk("smb_readdir: inode is NULL or not a directory\n");
 176                 return -EBADF;
 177         }
 178 
 179         if (c_entry == NULL) 
 180         {
 181                 i = sizeof (struct smb_dirent) * SMB_READDIR_CACHE_SIZE;
 182                 c_entry = (struct smb_dirent *) smb_kmalloc(i, GFP_KERNEL);
 183                 if (c_entry == NULL) {
 184                         printk("smb_readdir: no MEMORY for cache\n");
 185                         return -ENOMEM;
 186                 }
 187                 for (i = 0; i < SMB_READDIR_CACHE_SIZE; i++) {
 188                         c_entry[i].path =
 189                                 (char *) smb_kmalloc(SMB_MAXNAMELEN + 1,
 190                                                      GFP_KERNEL);
 191                         if (c_entry[i].path == NULL) {
 192                                 DPRINTK("smb_readdir: could not alloc path\n");
 193                                 while (--i>=0)
 194                                         kfree(c_entry[i].path);
 195                                 kfree(c_entry);
 196                                 c_entry = NULL;
 197                                 return -ENOMEM;
 198                         }
 199                 }
 200         }
 201 
 202         if (filp->f_pos == 0) {
 203                 smb_invalid_dir_cache(inode->i_ino);
 204         }
 205 
 206         if (inode->i_ino == c_ino) {
 207                 for (i = 0; i < c_size; i++) {
 208                         if (filp->f_pos == c_entry[i].f_pos) {
 209                                 entry = &c_entry[i];
 210                                 c_last_returned_index = i;
 211                                 index = i;
 212                                 break;
 213                         }
 214                 }
 215                 if ((entry == NULL) && c_seen_eof)
 216                         return 0;
 217         }
 218 
 219         if (entry == NULL) {
 220                 DPRINTK("smb_readdir: Not found in cache.\n");
 221                 result = smb_proc_readdir(server, inode,
 222                                           filp->f_pos, SMB_READDIR_CACHE_SIZE,
 223                                           c_entry);
 224 
 225                 if (result < 0) {
 226                         c_ino = 0;
 227                         return result;
 228                 }
 229 
 230                 if (result > 0) {
 231                         c_seen_eof = (result < SMB_READDIR_CACHE_SIZE);
 232                         c_ino  = inode->i_ino;
 233                         c_size = result;
 234                         entry = c_entry;
 235                         c_last_returned_index = 0;
 236                         index = 0;
 237                         for (i = 0; i < c_size; i++) {
 238 
 239                                 switch (server->case_handling) 
 240                                 {
 241                                 case CASE_UPPER:
 242                                         str_upper(c_entry[i].path); break;
 243                                 case CASE_LOWER:
 244                                         str_lower(c_entry[i].path); break;
 245                                 case CASE_DEFAULT:
 246                                         break;
 247                                 }
 248                         }
 249                 }
 250         }
 251 
 252         if (entry == NULL) {
 253                 /* Nothing found, even from a smb call */
 254                 return 0;
 255         }
 256 
 257         while (index < c_size) {
 258 
 259                 /* We found it.  For getwd(), we have to return the
 260                    correct inode in d_ino if the inode is currently in
 261                    use. Otherwise the inode number does not
 262                    matter. (You can argue a lot about this..) */ 
 263 
 264                 int path_len;
 265                 int len;
 266                 struct smb_inode_info *ino_info;
 267                 char complete_path[SMB_MAXPATHLEN];
 268 
 269                 len = strlen(entry->path);
 270                 if ((result = get_pname_static(inode, entry->path, len,
 271                                                complete_path,
 272                                                &path_len)) < 0)
 273                         return result;
 274 
 275                 ino_info = smb_find_inode(server, complete_path);
 276 
 277                 /* Some programs seem to be confused about a zero
 278                    inode number, so we set it to one.  Thanks to
 279                    Gordon Chaffee for this one. */
 280                 if (ino_info == NULL) {
 281                         ino_info = (struct smb_inode_info *) 1;
 282                 }
 283 
 284                 DDPRINTK("smb_readdir: entry->path = %s\n", entry->path);
 285                 DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos);
 286 
 287                 if (filldir(dirent, entry->path, len,
 288                             entry->f_pos, (ino_t)ino_info) < 0) {
 289                         break;
 290                 }
 291 
 292                 if (   (inode->i_ino != c_ino)
 293                     || (entry->f_pos != filp->f_pos)) {
 294                         /* Someone has destroyed the cache while we slept
 295                            in filldir */
 296                         break;
 297                 }
 298                 filp->f_pos += 1;
 299                 index += 1;
 300                 entry += 1;
 301         }
 302         return 0;
 303 }
 304 
 305 void
 306 smb_init_dir_cache(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308         c_ino   = 0;
 309         c_entry = NULL;
 310 }
 311 
 312 void
 313 smb_invalid_dir_cache(unsigned long ino)
     /* [previous][next][first][last][top][bottom][index][help] */
 314 {
 315         if (ino == c_ino) {
 316                 c_ino = 0;
 317                 c_seen_eof = 0;
 318         }
 319 }
 320 
 321 void
 322 smb_free_dir_cache(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 323 {
 324         int i;
 325 
 326         DPRINTK("smb_free_dir_cache: enter\n");
 327         
 328         if (c_entry == NULL)
 329                 return;
 330 
 331         for (i = 0; i < SMB_READDIR_CACHE_SIZE; i++) {
 332                 smb_kfree_s(c_entry[i].path, NAME_MAX + 1);
 333         }
 334 
 335         smb_kfree_s(c_entry,
 336                     sizeof(struct smb_dirent) * SMB_READDIR_CACHE_SIZE);
 337         c_entry = NULL;
 338 
 339         DPRINTK("smb_free_dir_cache: exit\n");
 340 }
 341 
 342 
 343 /* get_pname_static: it expects the res_path to be a preallocated
 344    string of len SMB_MAXPATHLEN. */
 345 
 346 static int
 347 get_pname_static(struct inode *dir, const char *name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 348                  char *path, int *res_len)
 349 {
 350         char *parentname = SMB_INOP(dir)->finfo.path;
 351         int   parentlen  = SMB_INOP(dir)->finfo.len;
 352 
 353 #if 1
 354         if (parentlen != strlen(parentname)) {
 355                 printk("get_pname: parent->finfo.len = %d instead of %d\n",
 356                        parentlen, strlen(parentname));
 357                 parentlen = strlen(parentname);
 358         }
 359         
 360 #endif
 361         DDPRINTK("get_pname_static: parentname = %s, len = %d\n",
 362                  parentname, parentlen);
 363         
 364         if (len > SMB_MAXNAMELEN) {
 365                 return -ENAMETOOLONG;
 366         }
 367 
 368         /* Fast cheat for . */
 369         if (len == 0 || (len == 1 && name[0] == '.')) {
 370 
 371                 memcpy(path, parentname, parentlen + 1);
 372                 *res_len = parentlen;
 373                 return 0;
 374         }
 375         
 376         /* Hmm, what about .. ? */
 377         if (len == 2 && name[0] == '.' && name[1] == '.') {
 378 
 379                 char *pos = strrchr(parentname, '\\');
 380 
 381                 if (   (pos == NULL)
 382                     && (parentlen == 0)) {
 383 
 384                         /* We're at the top */
 385 
 386                         path[0] = '\\';
 387                         path[1] = '\0';
 388                         *res_len  = 2;
 389                         return 0;
 390                 }
 391                         
 392                 
 393                 if (pos == NULL) {
 394                         printk("smb_make_name: Bad parent SMB-name: %s",
 395                                parentname);
 396                         return -ENODATA;
 397                 }
 398                 
 399                 len = pos - parentname;
 400 
 401                 memcpy(path, parentname, len);
 402                 path[len] = '\0';
 403         }
 404         else
 405         {
 406                 if (len + parentlen + 2 > SMB_MAXPATHLEN) 
 407                         return -ENAMETOOLONG;
 408                                 
 409                 memcpy(path, parentname, parentlen);
 410                 path[parentlen] = '\\';
 411                 memcpy(path + parentlen + 1, name, len);
 412                 path[parentlen + 1 + len] = '\0';
 413                 len = parentlen + len + 1;
 414         }
 415 
 416         switch (SMB_SERVER(dir)->case_handling) 
 417         {
 418         case CASE_UPPER: 
 419                 str_upper(path); 
 420                 break;
 421         case CASE_LOWER: 
 422                 str_lower(path); 
 423                 break;
 424         case CASE_DEFAULT: 
 425                 break;
 426         }
 427 
 428         *res_len = len;
 429 
 430         DDPRINTK("get_pname: path = %s, *pathlen = %d\n",
 431                  path, *res_len);
 432         return 0;
 433 }
 434         
 435 static int 
 436 get_pname(struct inode *dir, const char *name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 437           char **res_path, int *res_len)
 438 {
 439         char result[SMB_MAXPATHLEN];
 440         int  result_len;
 441         int  res;
 442 
 443         if ((res = get_pname_static(dir,name,len,result,&result_len) != 0)) {
 444                 return res;
 445         }
 446 
 447         if ((*res_path = smb_kmalloc(result_len+1, GFP_KERNEL)) == NULL) {
 448                 printk("get_pname: Out of memory while allocating name.");
 449                 return -ENOMEM;
 450         }
 451 
 452         strcpy(*res_path, result);
 453         *res_len = result_len;
 454         return 0;
 455 }
 456 
 457 static void
 458 put_pname(char *path)
     /* [previous][next][first][last][top][bottom][index][help] */
 459 {
 460         smb_kfree_s(path, 0);
 461 }
 462 
 463 /* Insert a NEW smb_inode_info into the inode tree of our filesystem,
 464    under dir. The caller must assure that it's not already there. We
 465    assume that path is allocated for us. */
 466 
 467 static struct inode *
 468 smb_iget(struct inode *dir, char *path, struct smb_dirent *finfo)
     /* [previous][next][first][last][top][bottom][index][help] */
 469 {
 470         struct smb_dirent newent = { 0 };
 471         struct inode *inode;
 472         int error, len;
 473         struct smb_inode_info *new_inode_info;
 474         struct smb_inode_info *root;
 475 
 476         if (!dir) {
 477                 printk("smb_iget: dir is NULL\n");
 478                 return NULL;
 479         }
 480 
 481         if (!path) {
 482                 printk("smb_iget: path is NULL\n");
 483                 return NULL;
 484         }
 485 
 486         len = strlen(path);
 487         
 488         if (!finfo) {
 489                 error = smb_proc_getattr(&(SMB_SBP(dir->i_sb)->s_server),
 490                                          path, len, &newent);
 491                 if (error) {
 492                         printk("smb_iget: getattr error = %d\n", -error);
 493                         return NULL;
 494                 }               
 495                 finfo = &newent;
 496                 DPRINTK("smb_iget: Read finfo:\n");
 497                 DPRINTK("smb_iget: finfo->attr = 0x%X\n", finfo->attr);
 498         }
 499 
 500         new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
 501                                      GFP_KERNEL);
 502 
 503         if (new_inode_info == NULL) {
 504                 printk("smb_iget: could not alloc mem for %s\n", path);
 505                 return NULL;
 506         }
 507 
 508         new_inode_info->state = INODE_LOOKED_UP;
 509         new_inode_info->nused = 0;
 510         new_inode_info->dir   = SMB_INOP(dir);
 511 
 512         new_inode_info->finfo        = *finfo;
 513         new_inode_info->finfo.opened = 0;
 514         new_inode_info->finfo.path   = path;
 515         new_inode_info->finfo.len    = len;
 516 
 517         SMB_INOP(dir)->nused += 1;
 518 
 519         /* We have to link the new inode_info into the doubly linked
 520            list of inode_infos to make a complete linear search
 521            possible. */
 522 
 523         root = &(SMB_SERVER(dir)->root);
 524 
 525         new_inode_info->prev = root;
 526         new_inode_info->next = root->next;
 527         root->next->prev = new_inode_info;
 528         root->next = new_inode_info;
 529         
 530         if (!(inode = iget(dir->i_sb, (int)new_inode_info))) {
 531                 printk("smb_iget: iget failed!");
 532                 return NULL;
 533         }
 534 
 535         return inode;
 536 }
 537 
 538 void
 539 smb_free_inode_info(struct smb_inode_info *i)
     /* [previous][next][first][last][top][bottom][index][help] */
 540 {
 541         if (i == NULL) {
 542                 printk("smb_free_inode: i == NULL\n");
 543                 return;
 544         }
 545 
 546         i->state = INODE_CACHED;
 547         while ((i->nused == 0) && (i->state == INODE_CACHED)) {
 548                 struct smb_inode_info *dir = i->dir;
 549 
 550                 i->next->prev = i->prev;
 551                 i->prev->next = i->next;
 552 
 553                 smb_kfree_s(i->finfo.path, i->finfo.len+1);
 554                 smb_kfree_s(i, sizeof(struct smb_inode_info));
 555 
 556                 if (dir == NULL) return;
 557 
 558                 (dir->nused)--;
 559                 i = dir;
 560         }
 561 }
 562         
 563 void
 564 smb_init_root(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 565 {
 566         struct smb_inode_info *root = &(server->root);
 567 
 568         root->finfo.path = server->m.root_path;
 569         root->finfo.len  = strlen(root->finfo.path);
 570         root->finfo.opened = 0;
 571 
 572         root->state = INODE_LOOKED_UP;
 573         root->nused = 1;
 574         root->dir   = NULL;
 575         root->next = root->prev = root;
 576         return;
 577 }
 578 
 579 int
 580 smb_stat_root(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 581 {
 582         struct smb_inode_info *root = &(server->root);
 583         int result;
 584 
 585         if (root->finfo.len == 0) {
 586                 result = smb_proc_getattr(server, "\\", 1, &(root->finfo));
 587         }
 588         else
 589         {
 590                 result = smb_proc_getattr(server, 
 591                                           root->finfo.path, root->finfo.len,
 592                                           &(root->finfo));
 593         }
 594         return result;
 595 }
 596 
 597 void
 598 smb_free_all_inodes(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 599 {
 600         /* Here nothing should be to do. I do not know whether it's
 601            better to leave some memory allocated or be stuck in an
 602            endless loop */
 603 #if 1
 604         struct smb_inode_info *root = &(server->root);
 605 
 606         if (root->next != root) {
 607                 printk("smb_free_all_inodes: INODES LEFT!!!\n");
 608         }
 609 
 610         while (root->next != root) {
 611                 printk("smb_free_all_inodes: freeing inode\n");
 612                 smb_free_inode_info(root->next);
 613                 /* In case we have an endless loop.. */
 614                 schedule();
 615         }
 616 #endif        
 617         
 618         return;
 619 }
 620 
 621 /* This has to be called when a connection has gone down, so that all
 622    file-handles we got from the server are invalid */
 623 
 624 void
 625 smb_invalidate_all_inodes(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 626 {
 627         struct smb_inode_info *ino = &(server->root);
 628 
 629         do {
 630                 ino->finfo.opened = 0;
 631                 ino = ino->next;
 632         } while (ino != &(server->root));
 633         
 634         return;
 635 }
 636         
 637 
 638 /* We will search the inode that belongs to this name, currently by a
 639    complete linear search through the inodes belonging to this
 640    filesystem. This has to be fixed. */
 641 
 642 static struct smb_inode_info *
 643 smb_find_inode(struct smb_server *server, const char *path)
     /* [previous][next][first][last][top][bottom][index][help] */
 644 {
 645         struct smb_inode_info *result = &(server->root);
 646 
 647         if (path == NULL)
 648                 return NULL;
 649 
 650         do {
 651                 if (strcmp(result->finfo.path, path) == 0)
 652                         return result;
 653                 result = result->next;
 654 
 655         } while (result != &(server->root));
 656 
 657         return NULL;
 658 }
 659 
 660 
 661 static int 
 662 smb_lookup(struct inode *dir, const char *__name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 663            struct inode **result)
 664 {
 665         char *name = NULL;
 666         struct smb_dirent finfo;
 667         struct smb_inode_info *result_info;
 668         int error;
 669         int found_in_cache;
 670 
 671         *result = NULL;
 672 
 673         if (!dir || !S_ISDIR(dir->i_mode)) {
 674                 printk("smb_lookup: inode is NULL or not a directory.\n");
 675                 iput(dir);
 676                 return -ENOENT;
 677         }
 678 
 679         DDPRINTK("smb_lookup: %s\n", __name);
 680 
 681         /* Fast cheat for . */
 682         if (len == 0 || (len == 1 && __name[0] == '.')) {
 683                 *result = dir;
 684                 return 0;
 685         }
 686 
 687         /* Now we will have to build up an SMB filename. */
 688         if ((error = get_pname(dir, __name, len, &name, &len)) < 0) {
 689                 iput(dir);
 690                 return error;
 691         }
 692 
 693         result_info = smb_find_inode(SMB_SERVER(dir), name);
 694 
 695         if (result_info != 0) {
 696 
 697                 if (result_info->state == INODE_CACHED)
 698                         result_info->state = INODE_LOOKED_UP;
 699 
 700                 put_pname(name);
 701 
 702                 /* Here we convert the inode_info address into an
 703                    inode number */
 704 
 705                 *result = iget(dir->i_sb, (int)result_info);
 706                 iput(dir);
 707 
 708                 if (*result == NULL) {
 709                         return -EACCES;
 710                 } else {
 711                         return 0;
 712                 }
 713         }
 714 
 715         /* Ok, now we have made our name. We have to build a new
 716            smb_inode_info struct and insert it into the tree, if it is
 717            a name that exists on the server */
 718 
 719         /* If the file is in the dir cache, we do not have to ask the
 720            server. */
 721 
 722         found_in_cache = 0;
 723         
 724         if (dir->i_ino == c_ino) {
 725                 int first = c_last_returned_index;
 726                 int i;
 727 
 728                 i = first;
 729                 do {
 730                         DDPRINTK("smb_lookup: trying index: %d, name: %s\n",
 731                                 i, c_entry[i].path);
 732                         if (strcmp(c_entry[i].path, __name) == 0) {
 733                                 DPRINTK("smb_lookup: found in cache!\n");
 734                                 finfo = c_entry[i];
 735                                 finfo.path = NULL; /* It's not ours! */
 736                                 found_in_cache = 1;
 737                                 break;
 738                         }
 739                         i = (i + 1) % c_size;
 740                         DDPRINTK("smb_lookup: index %d, name %s failed\n",
 741                                  i, c_entry[i].path);
 742                 } while (i != first);
 743         }
 744 
 745         if (found_in_cache == 0) {
 746                 error = smb_proc_getattr(SMB_SERVER(dir), name, len, &finfo);
 747                 if (error < 0) {
 748                         put_pname(name);
 749                         iput(dir);
 750                         return error;
 751                 }
 752         }
 753 
 754         if (!(*result = smb_iget(dir, name, &finfo))) {
 755                 put_pname(name);
 756                 iput(dir);
 757                 return -EACCES;
 758         }
 759 
 760         DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long)result_info);
 761         iput(dir);
 762         return 0;
 763 }
 764 
 765 static int 
 766 smb_create(struct inode *dir, const char *name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 767            struct inode **result)
 768 {
 769         int error;
 770         char *path = NULL;
 771         struct smb_dirent entry;
 772 
 773         *result = NULL;
 774 
 775         if (!dir || !S_ISDIR(dir->i_mode)) {
 776                 printk("smb_create: inode is NULL or not a directory\n");
 777                 iput(dir);
 778                 return -ENOENT;
 779         }
 780 
 781         /* Now we will have to build up an SMB filename. */
 782         if ((error = get_pname(dir, name, len, &path, &len)) < 0) {
 783                 iput(dir);
 784                 return error;
 785         }
 786 
 787         entry.attr  = 0;
 788         entry.ctime = CURRENT_TIME;
 789         entry.atime = CURRENT_TIME;
 790         entry.mtime = CURRENT_TIME;
 791         entry.size  = 0;
 792 
 793         error = smb_proc_create(SMB_SERVER(dir), path, len, &entry);
 794         if (error < 0) {
 795                 put_pname(path);
 796                 iput(dir);
 797                 return error;
 798         }
 799 
 800         smb_invalid_dir_cache(dir->i_ino);
 801 
 802         if (!(*result = smb_iget(dir, path, &entry)) < 0) {
 803                 put_pname(path);
 804                 iput(dir);
 805                 return error;
 806         }
 807         iput(dir);
 808         return 0;       
 809 }
 810 
 811 static int
 812 smb_mkdir(struct inode *dir, const char *name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 813 {
 814         int error;
 815         char path[SMB_MAXPATHLEN];
 816 
 817         if (!dir || !S_ISDIR(dir->i_mode)) {
 818                 printk("smb_mkdir: inode is NULL or not a directory\n");
 819                 iput(dir);
 820                 return -ENOENT;
 821         }
 822 
 823         /* Now we will have to build up an SMB filename. */
 824         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 825                 iput(dir);
 826                 return error;
 827         }
 828 
 829         if ((error = smb_proc_mkdir(SMB_SERVER(dir), path, len)) == 0) {
 830                 smb_invalid_dir_cache(dir->i_ino);
 831         }
 832 
 833         iput(dir);
 834         return error;
 835 }
 836 
 837 static int
 838 smb_rmdir(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 839 {
 840         int error;
 841         char path[SMB_MAXPATHLEN];
 842 
 843         if (!dir || !S_ISDIR(dir->i_mode)) {
 844                 printk("smb_rmdir: inode is NULL or not a directory\n");
 845                 iput(dir);
 846                 return -ENOENT;
 847         }
 848         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 849                 iput(dir);
 850                 return error;
 851         }
 852         if (smb_find_inode(SMB_SERVER(dir), path) != NULL) {
 853                 error = -EBUSY;
 854         } else {
 855                 if ((error = smb_proc_rmdir(SMB_SERVER(dir), path, len)) == 0)
 856                         smb_invalid_dir_cache(dir->i_ino);
 857         }
 858         iput(dir);
 859         return error;
 860 }
 861 
 862 static int
 863 smb_unlink(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 864 {
 865         int error;
 866         char path[SMB_MAXPATHLEN];
 867 
 868         if (!dir || !S_ISDIR(dir->i_mode)) {
 869                 printk("smb_unlink: inode is NULL or not a directory\n");
 870                 iput(dir);
 871                 return -ENOENT;
 872         }
 873         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 874                 iput(dir);
 875                 return error;
 876         }
 877         if (smb_find_inode(SMB_SERVER(dir), path) != NULL) {
 878                 error = -EBUSY;
 879         } else {
 880                 if ((error = smb_proc_unlink(SMB_SERVER(dir), path, len)) == 0)
 881                         smb_invalid_dir_cache(dir->i_ino);
 882         }
 883 
 884         iput(dir);
 885         return error;
 886 }
 887 
 888 static int
 889 smb_rename(struct inode *old_dir, const char *old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 890            struct inode *new_dir, const char *new_name, int new_len)
 891 {
 892         int res;
 893         char old_path[SMB_MAXPATHLEN], new_path[SMB_MAXPATHLEN];
 894 
 895         if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
 896                 printk("smb_rename: old inode is NULL or not a directory\n");
 897                 res = -ENOENT;
 898                 goto finished;
 899         }
 900 
 901         if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
 902                 printk("smb_rename: new inode is NULL or not a directory\n");
 903                 res = -ENOENT;
 904                 goto finished;
 905         }
 906 
 907         res = get_pname_static(old_dir, old_name, old_len, old_path, &old_len);
 908         if (res < 0) {
 909                 goto finished;
 910         }
 911 
 912         res = get_pname_static(new_dir, new_name, new_len, new_path, &new_len);
 913         if (res < 0) {
 914                 goto finished;
 915         }
 916         
 917         if (   (smb_find_inode(SMB_SERVER(old_dir), old_path) != NULL)
 918             || (smb_find_inode(SMB_SERVER(new_dir), new_path) != NULL)) {
 919                 res = -EBUSY;
 920                 goto finished;
 921         }
 922 
 923         res = smb_proc_mv(SMB_SERVER(old_dir), old_path, old_len,
 924                           new_path, new_len);
 925 
 926         if (res == -EEXIST) {
 927                 int res1;
 928                 res1 = smb_proc_unlink(SMB_SERVER(old_dir), new_path, new_len);
 929                 if (res1 == 0) {
 930                         res = smb_proc_mv(SMB_SERVER(old_dir), old_path,
 931                                           old_len, new_path, new_len);
 932                 }
 933         }
 934 
 935         if (res == 0) {
 936                 smb_invalid_dir_cache(old_dir->i_ino);
 937                 smb_invalid_dir_cache(new_dir->i_ino);
 938         }               
 939         
 940  finished:
 941         iput(old_dir); 
 942         iput(new_dir);
 943         return res;
 944 }
 945         
 946 /*
 947  * Overrides for Emacs so that we follow Linus's tabbing style.
 948  * Emacs will notice this stuff at the end of the file and automatically
 949  * adjust the settings for this buffer only.  This must remain at the end
 950  * of the file.
 951  * ---------------------------------------------------------------------------
 952  * Local variables:
 953  * c-indent-level: 8
 954  * c-brace-imaginary-offset: 0
 955  * c-brace-offset: -8
 956  * c-argdecl-indent: 8
 957  * c-label-offset: -8
 958  * c-continued-statement-offset: 8
 959  * c-continued-brace-offset: 0
 960  * End:
 961  */

/* [previous][next][first][last][top][bottom][index][help] */