root/fs/smbfs/dir.c

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

DEFINITIONS

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

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

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