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_readdir1
  5. smb_readdir
  6. smb_init_dir_cache
  7. smb_invalid_dir_cache
  8. smb_free_dir_cache
  9. get_pname_static
  10. get_pname
  11. put_pname
  12. smb_iget
  13. smb_free_inode_info
  14. smb_init_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_readdir1(struct inode *inode, const struct file *filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 163              struct smb_dirent *ret,ino_t *ino)
 164 {
 165         int result, i = 0;
 166         struct smb_dirent *entry = NULL;
 167         struct smb_server *server = SMB_SERVER(inode);
 168 
 169         DDPRINTK("smb_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
 170         DDPRINTK("smb_readdir: inode->i_ino = %ld, c_ino = %ld\n",
 171                  inode->i_ino, c_ino);
 172 
 173         if (!inode || !S_ISDIR(inode->i_mode)) {
 174                 printk("smb_readdir: inode is NULL or not a directory\n");
 175                 return -EBADF;
 176         }
 177 
 178         if (c_entry == NULL) 
 179         {
 180                 i = sizeof (struct smb_dirent) * SMB_READDIR_CACHE_SIZE;
 181                 c_entry = (struct smb_dirent *) smb_kmalloc(i, GFP_KERNEL);
 182                 for (i = 0; i < SMB_READDIR_CACHE_SIZE; i++) {
 183                         c_entry[i].path =
 184                                 (char *) smb_kmalloc(SMB_MAXNAMELEN + 1,
 185                                                      GFP_KERNEL);
 186                         if (c_entry[i].path == NULL) {
 187                                 DPRINTK("smb_readdir: could not alloc path\n");
 188                         }
 189                 }
 190         }
 191 
 192         if (filp->f_pos == 0) {
 193                 smb_invalid_dir_cache(inode->i_ino);
 194         }
 195 
 196         if (inode->i_ino == c_ino) {
 197                 for (i = 0; i < c_size; i++) {
 198                         if (filp->f_pos == c_entry[i].f_pos) {
 199                                 entry = &c_entry[i];
 200                                 c_last_returned_index = i;
 201                                 break;
 202                         }
 203                 }
 204                 if ((entry == NULL) && c_seen_eof)
 205                         return 0;
 206         }
 207 
 208         if (entry == NULL) {
 209                 DPRINTK("smb_readdir: Not found in cache.\n");
 210                 result = smb_proc_readdir(server, inode,
 211                                           filp->f_pos, SMB_READDIR_CACHE_SIZE,
 212                                           c_entry);
 213 
 214                 if (result < 0) {
 215                         c_ino = 0;
 216                         return result;
 217                 }
 218 
 219                 if (result > 0) {
 220                         c_seen_eof = (result < SMB_READDIR_CACHE_SIZE);
 221                         c_ino  = inode->i_ino;
 222                         c_size = result;
 223                         entry = c_entry;
 224                         c_last_returned_index = 0;
 225                         for (i = 0; i < c_size; i++) {
 226 
 227                                 switch (server->case_handling) 
 228                                 {
 229                                 case CASE_UPPER:
 230                                         str_upper(c_entry[i].path); break;
 231                                 case CASE_LOWER:
 232                                         str_lower(c_entry[i].path); break;
 233                                 case CASE_DEFAULT:
 234                                         break;
 235                                 }
 236                         }
 237                 }
 238         }
 239         
 240         if (entry) {
 241 
 242                 /* We found it.  For getwd(), we have to return the
 243                    correct inode in d_ino if the inode is currently in
 244                    use. Otherwise the inode number does not
 245                    matter. */ 
 246 
 247                 int  path_len;
 248                 struct smb_inode_info *ino_info;
 249                 char complete_path[SMB_MAXPATHLEN];
 250 
 251                 
 252 
 253                 i = strlen(entry->path);
 254                 if ((result = get_pname_static(inode, entry->path, i,
 255                                                complete_path,
 256                                                &path_len)) < 0)
 257                         return result;
 258 
 259                 ino_info = smb_find_inode(server, complete_path);
 260 
 261                 /* Some programs seem to be confused about a zero
 262                    inode number, so we set it to one.  Thanks to
 263                    Gordon Chaffee for this one. */
 264                 if (ino_info == NULL) {
 265                         ino_info = (struct smb_inode_info *) 1;
 266                 }
 267 
 268                 DDPRINTK("smb_readdir: entry->path = %s\n", entry->path);
 269                 DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos);
 270 
 271                 *ino = (ino_t)ino_info; /* use the pointer as the
 272                                           inode - dangerous if we have
 273                                           64 bit pointers! FIXME */
 274 
 275                 *ret = *entry;
 276                 return 1;
 277         }
 278 
 279         return 0;
 280 }
 281 
 282 static int 
 283 smb_readdir(struct inode *inode, struct file *filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 284             void *dirent, filldir_t filldir)
 285 {
 286         struct smb_dirent d;
 287         ino_t ino;
 288 
 289         while (smb_readdir1(inode,filp,&d,&ino) == 1) {         
 290                 if (filldir(dirent,d.path,strlen(d.path)+1,
 291                             filp->f_pos,ino) < 0) {
 292                         return 0;
 293                 }
 294                 filp->f_pos++;
 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 int
 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         int result;
 562 
 563         root->finfo.path = server->m.root_path;
 564         root->finfo.len  = strlen(root->finfo.path);
 565         root->finfo.opened = 0;
 566 
 567         root->state = INODE_LOOKED_UP;
 568         root->nused = 1;
 569         root->dir   = NULL;
 570         root->next = root->prev = root;
 571 
 572         if (root->finfo.len == 0) {
 573                 result = smb_proc_getattr(server, "\\", 1, &(root->finfo));
 574         }
 575         else
 576         {
 577                 result = smb_proc_getattr(server, 
 578                                           root->finfo.path, root->finfo.len,
 579                                           &(root->finfo));
 580         }
 581         return result;
 582 }
 583 
 584 void
 585 smb_free_all_inodes(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 586 {
 587         /* Here nothing should be to do. I do not know whether it's
 588            better to leave some memory allocated or be stuck in an
 589            endless loop */
 590 #if 1
 591         struct smb_inode_info *root = &(server->root);
 592 
 593         if (root->next != root) {
 594                 printk("smb_free_all_inodes: INODES LEFT!!!\n");
 595         }
 596 
 597         while (root->next != root) {
 598                 printk("smb_free_all_inodes: freeing inode\n");
 599                 smb_free_inode_info(root->next);
 600                 /* In case we have an endless loop.. */
 601                 schedule();
 602         }
 603 #endif        
 604         
 605         return;
 606 }
 607 
 608 /* This has to be called when a connection has gone down, so that all
 609    file-handles we got from the server are invalid */
 610 
 611 void
 612 smb_invalidate_all_inodes(struct smb_server *server)
     /* [previous][next][first][last][top][bottom][index][help] */
 613 {
 614         struct smb_inode_info *ino = &(server->root);
 615 
 616         do {
 617                 ino->finfo.opened = 0;
 618                 ino = ino->next;
 619         } while (ino != &(server->root));
 620         
 621         return;
 622 }
 623         
 624 
 625 /* We will search the inode that belongs to this name, currently by a
 626    complete linear search through the inodes belonging to this
 627    filesystem. This has to be fixed. */
 628 
 629 static struct smb_inode_info *
 630 smb_find_inode(struct smb_server *server, const char *path)
     /* [previous][next][first][last][top][bottom][index][help] */
 631 {
 632         struct smb_inode_info *result = &(server->root);
 633 
 634         if (path == NULL)
 635                 return NULL;
 636 
 637         do {
 638                 if (strcmp(result->finfo.path, path) == 0)
 639                         return result;
 640                 result = result->next;
 641 
 642         } while (result != &(server->root));
 643 
 644         return NULL;
 645 }
 646 
 647 
 648 static int 
 649 smb_lookup(struct inode *dir, const char *__name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 650            struct inode **result)
 651 {
 652         char *name = NULL;
 653         struct smb_dirent finfo;
 654         struct smb_inode_info *result_info;
 655         int error;
 656         int found_in_cache;
 657 
 658         *result = NULL;
 659 
 660         if (!dir || !S_ISDIR(dir->i_mode)) {
 661                 printk("smb_lookup: inode is NULL or not a directory.\n");
 662                 iput(dir);
 663                 return -ENOENT;
 664         }
 665 
 666         DDPRINTK("smb_lookup: %s\n", __name);
 667 
 668         /* Fast cheat for . */
 669         if (len == 0 || (len == 1 && __name[0] == '.')) {
 670                 *result = dir;
 671                 return 0;
 672         }
 673 
 674         /* Now we will have to build up an SMB filename. */
 675         if ((error = get_pname(dir, __name, len, &name, &len)) < 0) {
 676                 iput(dir);
 677                 return error;
 678         }
 679 
 680         result_info = smb_find_inode(SMB_SERVER(dir), name);
 681 
 682         if (result_info != 0) {
 683 
 684                 if (result_info->state == INODE_CACHED)
 685                         result_info->state = INODE_LOOKED_UP;
 686 
 687                 put_pname(name);
 688 
 689                 /* Here we convert the inode_info address into an
 690                    inode number */
 691 
 692                 *result = iget(dir->i_sb, (int)result_info);
 693                 iput(dir);
 694 
 695                 if (*result == NULL) {
 696                         return -EACCES;
 697                 } else {
 698                         return 0;
 699                 }
 700         }
 701 
 702         /* Ok, now we have made our name. We have to build a new
 703            smb_inode_info struct and insert it into the tree, if it is
 704            a name that exists on the server */
 705 
 706         /* If the file is in the dir cache, we do not have to ask the
 707            server. */
 708 
 709         found_in_cache = 0;
 710         
 711         if (dir->i_ino == c_ino) {
 712                 int first = c_last_returned_index - 1;
 713                 int i;
 714 
 715                 if (first < 0) {
 716                         first = c_size - 1;
 717                 }
 718 
 719                 i = first;
 720                 do {
 721                         DDPRINTK("smb_lookup: trying index: %d, name: %s\n",
 722                                 i, c_entry[i].path);
 723                         if (strcmp(c_entry[i].path, __name) == 0) {
 724                                 DPRINTK("smb_lookup: found in cache!\n");
 725                                 finfo = c_entry[i];
 726                                 finfo.path = NULL; /* It's not ours! */
 727                                 found_in_cache = 1;
 728                                 break;
 729                         }
 730                         i = (i + 1) % c_size;
 731 
 732                 } while (i != first);
 733         }
 734 
 735         if (found_in_cache == 0) {
 736                 error = smb_proc_getattr(SMB_SERVER(dir), name, len, &finfo);
 737                 if (error < 0) {
 738                         put_pname(name);
 739                         iput(dir);
 740                         return error;
 741                 }
 742         }
 743 
 744         if (!(*result = smb_iget(dir, name, &finfo))) {
 745                 put_pname(name);
 746                 iput(dir);
 747                 return -EACCES;
 748         }
 749 
 750         DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long)result_info);
 751         iput(dir);
 752         return 0;
 753 }
 754 
 755 static int 
 756 smb_create(struct inode *dir, const char *name, int len, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 757            struct inode **result)
 758 {
 759         int error;
 760         char *path = NULL;
 761         struct smb_dirent entry;
 762 
 763         *result = NULL;
 764 
 765         if (!dir || !S_ISDIR(dir->i_mode)) {
 766                 printk("smb_create: inode is NULL or not a directory\n");
 767                 iput(dir);
 768                 return -ENOENT;
 769         }
 770 
 771         /* Now we will have to build up an SMB filename. */
 772         if ((error = get_pname(dir, name, len, &path, &len)) < 0) {
 773                 iput(dir);
 774                 return error;
 775         }
 776 
 777         entry.attr  = 0;
 778         entry.ctime = CURRENT_TIME;
 779         entry.size  = 0;
 780 
 781         error = smb_proc_create(SMB_SERVER(dir), path, len, &entry);
 782         if (error < 0) {
 783                 put_pname(path);
 784                 iput(dir);
 785                 return error;
 786         }
 787 
 788         smb_invalid_dir_cache(dir->i_ino);
 789 
 790         if (!(*result = smb_iget(dir, path, &entry)) < 0) {
 791                 put_pname(path);
 792                 iput(dir);
 793                 return error;
 794         }
 795         iput(dir);
 796         return 0;       
 797 }
 798 
 799 static int
 800 smb_mkdir(struct inode *dir, const char *name, int len, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 801 {
 802         int error;
 803         char path[SMB_MAXPATHLEN];
 804 
 805         if (!dir || !S_ISDIR(dir->i_mode)) {
 806                 printk("smb_mkdir: inode is NULL or not a directory\n");
 807                 iput(dir);
 808                 return -ENOENT;
 809         }
 810 
 811         /* Now we will have to build up an SMB filename. */
 812         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 813                 iput(dir);
 814                 return error;
 815         }
 816 
 817         if ((error = smb_proc_mkdir(SMB_SERVER(dir), path, len)) == 0) {
 818                 smb_invalid_dir_cache(dir->i_ino);
 819         }
 820 
 821         iput(dir);
 822         return error;
 823 }
 824 
 825 static int
 826 smb_rmdir(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 827 {
 828         int error;
 829         char path[SMB_MAXPATHLEN];
 830 
 831         if (!dir || !S_ISDIR(dir->i_mode)) {
 832                 printk("smb_rmdir: inode is NULL or not a directory\n");
 833                 iput(dir);
 834                 return -ENOENT;
 835         }
 836         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 837                 iput(dir);
 838                 return error;
 839         }
 840         if (smb_find_inode(SMB_SERVER(dir), path) != NULL) {
 841                 error = -EBUSY;
 842         } else {
 843                 if ((error = smb_proc_rmdir(SMB_SERVER(dir), path, len)) == 0)
 844                         smb_invalid_dir_cache(dir->i_ino);
 845         }
 846         iput(dir);
 847         return error;
 848 }
 849 
 850 static int
 851 smb_unlink(struct inode *dir, const char *name, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 852 {
 853         int error;
 854         char path[SMB_MAXPATHLEN];
 855 
 856         if (!dir || !S_ISDIR(dir->i_mode)) {
 857                 printk("smb_unlink: inode is NULL or not a directory\n");
 858                 iput(dir);
 859                 return -ENOENT;
 860         }
 861         if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
 862                 iput(dir);
 863                 return error;
 864         }
 865         if (smb_find_inode(SMB_SERVER(dir), path) != NULL) {
 866                 error = -EBUSY;
 867         } else {
 868                 if ((error = smb_proc_unlink(SMB_SERVER(dir), path, len)) == 0)
 869                         smb_invalid_dir_cache(dir->i_ino);
 870         }
 871 
 872         iput(dir);
 873         return error;
 874 }
 875 
 876 static int
 877 smb_rename(struct inode *old_dir, const char *old_name, int old_len,
     /* [previous][next][first][last][top][bottom][index][help] */
 878            struct inode *new_dir, const char *new_name, int new_len)
 879 {
 880         int res;
 881         char old_path[SMB_MAXPATHLEN], new_path[SMB_MAXPATHLEN];
 882 
 883         if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
 884                 printk("smb_rename: old inode is NULL or not a directory\n");
 885                 res = -ENOENT;
 886                 goto finished;
 887         }
 888 
 889         if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
 890                 printk("smb_rename: new inode is NULL or not a directory\n");
 891                 res = -ENOENT;
 892                 goto finished;
 893         }
 894 
 895         res = get_pname_static(old_dir, old_name, old_len, old_path, &old_len);
 896         if (res < 0) {
 897                 goto finished;
 898         }
 899 
 900         res = get_pname_static(new_dir, new_name, new_len, new_path, &new_len);
 901         if (res < 0) {
 902                 goto finished;
 903         }
 904         
 905         if (   (smb_find_inode(SMB_SERVER(old_dir), old_path) != NULL)
 906             || (smb_find_inode(SMB_SERVER(new_dir), new_path) != NULL)) {
 907                 res = -EBUSY;
 908                 goto finished;
 909         }
 910 
 911         res = smb_proc_mv(SMB_SERVER(old_dir), old_path, old_len,
 912                           new_path, new_len);
 913 
 914         if (res == 0) {
 915                 smb_invalid_dir_cache(old_dir->i_ino);
 916                 smb_invalid_dir_cache(new_dir->i_ino);
 917         }
 918         
 919  finished:
 920         iput(old_dir); 
 921         iput(new_dir);
 922         return res;
 923 }
 924         
 925 /*
 926  * Overrides for Emacs so that we follow Linus's tabbing style.
 927  * Emacs will notice this stuff at the end of the file and automatically
 928  * adjust the settings for this buffer only.  This must remain at the end
 929  * of the file.
 930  * ---------------------------------------------------------------------------
 931  * Local variables:
 932  * c-indent-level: 8
 933  * c-brace-imaginary-offset: 0
 934  * c-brace-offset: -8
 935  * c-argdecl-indent: 8
 936  * c-label-offset: -8
 937  * c-continued-statement-offset: 8
 938  * c-continued-brace-offset: 0
 939  * End:
 940  */

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