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

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