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

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