root/source3/libsmb/libsmb_file.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SMBC_open_ctx
  2. SMBC_creat_ctx
  3. SMBC_read_ctx
  4. SMBC_write_ctx
  5. SMBC_close_ctx
  6. SMBC_getatr
  7. SMBC_setatr
  8. SMBC_lseek_ctx
  9. SMBC_ftruncate_ctx

   1 /* 
   2    Unix SMB/Netbios implementation.
   3    SMB client library implementation
   4    Copyright (C) Andrew Tridgell 1998
   5    Copyright (C) Richard Sharpe 2000, 2002
   6    Copyright (C) John Terpstra 2000
   7    Copyright (C) Tom Jansen (Ninja ISD) 2002 
   8    Copyright (C) Derrell Lipman 2003-2008
   9    Copyright (C) Jeremy Allison 2007, 2008
  10    
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15    
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20    
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 #include "includes.h"
  26 #include "libsmbclient.h"
  27 #include "libsmb_internal.h"
  28 
  29 
  30 /*
  31  * Routine to open() a file ...
  32  */
  33 
  34 SMBCFILE *
  35 SMBC_open_ctx(SMBCCTX *context,
     /* [<][>][^][v][top][bottom][index][help] */
  36               const char *fname,
  37               int flags,
  38               mode_t mode)
  39 {
  40         char *server = NULL;
  41         char *share = NULL;
  42         char *user = NULL;
  43         char *password = NULL;
  44         char *workgroup = NULL;
  45         char *path = NULL;
  46         char *targetpath = NULL;
  47         struct cli_state *targetcli = NULL;
  48         SMBCSRV *srv   = NULL;
  49         SMBCFILE *file = NULL;
  50         int fd;
  51         TALLOC_CTX *frame = talloc_stackframe();
  52         
  53         if (!context || !context->internal->initialized) {
  54                 
  55                 errno = EINVAL;  /* Best I can think of ... */
  56                 TALLOC_FREE(frame);
  57                 return NULL;
  58                 
  59         }
  60         
  61         if (!fname) {
  62                 
  63                 errno = EINVAL;
  64                 TALLOC_FREE(frame);
  65                 return NULL;
  66                 
  67         }
  68         
  69         if (SMBC_parse_path(frame,
  70                             context,
  71                             fname,
  72                             &workgroup,
  73                             &server,
  74                             &share,
  75                             &path,
  76                             &user,
  77                             &password,
  78                             NULL)) {
  79                 errno = EINVAL;
  80                 TALLOC_FREE(frame);
  81                 return NULL;
  82         }
  83         
  84         if (!user || user[0] == (char)0) {
  85                 user = talloc_strdup(frame, smbc_getUser(context));
  86                 if (!user) {
  87                         errno = ENOMEM;
  88                         TALLOC_FREE(frame);
  89                         return NULL;
  90                 }
  91         }
  92         
  93         srv = SMBC_server(frame, context, True,
  94                           server, share, &workgroup, &user, &password);
  95         
  96         if (!srv) {
  97                 if (errno == EPERM) errno = EACCES;
  98                 TALLOC_FREE(frame);
  99                 return NULL;  /* SMBC_server sets errno */
 100         }
 101         
 102         /* Hmmm, the test for a directory is suspect here ... FIXME */
 103         
 104         if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') {
 105                 fd = -1;
 106         } else {
 107                 file = SMB_MALLOC_P(SMBCFILE);
 108                 
 109                 if (!file) {
 110                         errno = ENOMEM;
 111                         TALLOC_FREE(frame);
 112                         return NULL;
 113                 }
 114                 
 115                 ZERO_STRUCTP(file);
 116                 
 117                 /*d_printf(">>>open: resolving %s\n", path);*/
 118                 if (!cli_resolve_path(frame, "", context->internal->auth_info,
 119                                 srv->cli, path,
 120                                 &targetcli, &targetpath)) {
 121                         d_printf("Could not resolve %s\n", path);
 122                         errno = ENOENT;
 123                         SAFE_FREE(file);
 124                         TALLOC_FREE(frame);
 125                         return NULL;
 126                 }
 127                 /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
 128                 
 129                 if ((fd = cli_open(targetcli, targetpath, flags,
 130                                    context->internal->share_mode)) < 0) {
 131                         
 132                         /* Handle the error ... */
 133                         
 134                         SAFE_FREE(file);
 135                         errno = SMBC_errno(context, targetcli);
 136                         TALLOC_FREE(frame);
 137                         return NULL;
 138                         
 139                 }
 140                 
 141                 /* Fill in file struct */
 142                 
 143                 file->cli_fd  = fd;
 144                 file->fname   = SMB_STRDUP(fname);
 145                 file->srv     = srv;
 146                 file->offset  = 0;
 147                 file->file    = True;
 148                 
 149                 DLIST_ADD(context->internal->files, file);
 150                 
 151                 /*
 152                  * If the file was opened in O_APPEND mode, all write
 153                  * operations should be appended to the file.  To do that,
 154                  * though, using this protocol, would require a getattrE()
 155                  * call for each and every write, to determine where the end
 156                  * of the file is. (There does not appear to be an append flag
 157                  * in the protocol.)  Rather than add all of that overhead of
 158                  * retrieving the current end-of-file offset prior to each
 159                  * write operation, we'll assume that most append operations
 160                  * will continuously write, so we'll just set the offset to
 161                  * the end of the file now and hope that's adequate.
 162                  *
 163                  * Note to self: If this proves inadequate, and O_APPEND
 164                  * should, in some cases, be forced for each write, add a
 165                  * field in the context options structure, for
 166                  * "strict_append_mode" which would select between the current
 167                  * behavior (if FALSE) or issuing a getattrE() prior to each
 168                  * write and forcing the write to the end of the file (if
 169                  * TRUE).  Adding that capability will likely require adding
 170                  * an "append" flag into the _SMBCFILE structure to track
 171                  * whether a file was opened in O_APPEND mode.  -- djl
 172                  */
 173                 if (flags & O_APPEND) {
 174                         if (SMBC_lseek_ctx(context, file, 0, SEEK_END) < 0) {
 175                                 (void) SMBC_close_ctx(context, file);
 176                                 errno = ENXIO;
 177                                 TALLOC_FREE(frame);
 178                                 return NULL;
 179                         }
 180                 }
 181                 
 182                 TALLOC_FREE(frame);
 183                 return file;
 184                 
 185         }
 186         
 187         /* Check if opendir needed ... */
 188         
 189         if (fd == -1) {
 190                 int eno = 0;
 191                 
 192                 eno = SMBC_errno(context, srv->cli);
 193                 file = smbc_getFunctionOpendir(context)(context, fname);
 194                 if (!file) errno = eno;
 195                 TALLOC_FREE(frame);
 196                 return file;
 197                 
 198         }
 199         
 200         errno = EINVAL; /* FIXME, correct errno ? */
 201         TALLOC_FREE(frame);
 202         return NULL;
 203         
 204 }
 205 
 206 /*
 207  * Routine to create a file 
 208  */
 209 
 210 SMBCFILE *
 211 SMBC_creat_ctx(SMBCCTX *context,
     /* [<][>][^][v][top][bottom][index][help] */
 212                const char *path,
 213                mode_t mode)
 214 {
 215         
 216         if (!context || !context->internal->initialized) {
 217                 
 218                 errno = EINVAL;
 219                 return NULL;
 220                 
 221         }
 222         
 223         return SMBC_open_ctx(context, path,
 224                              O_WRONLY | O_CREAT | O_TRUNC, mode);
 225 }
 226 
 227 /*
 228  * Routine to read() a file ...
 229  */
 230 
 231 ssize_t
 232 SMBC_read_ctx(SMBCCTX *context,
     /* [<][>][^][v][top][bottom][index][help] */
 233               SMBCFILE *file,
 234               void *buf,
 235               size_t count)
 236 {
 237         int ret;
 238         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
 239         char *path = NULL;
 240         char *targetpath = NULL;
 241         struct cli_state *targetcli = NULL;
 242         TALLOC_CTX *frame = talloc_stackframe();
 243         
 244         /*
 245          * offset:
 246          *
 247          * Compiler bug (possibly) -- gcc (GCC) 3.3.5 (Debian 1:3.3.5-2) --
 248          * appears to pass file->offset (which is type off_t) differently than
 249          * a local variable of type off_t.  Using local variable "offset" in
 250          * the call to cli_read() instead of file->offset fixes a problem
 251          * retrieving data at an offset greater than 4GB.
 252          */
 253         off_t offset;
 254         
 255         if (!context || !context->internal->initialized) {
 256                 
 257                 errno = EINVAL;
 258                 TALLOC_FREE(frame);
 259                 return -1;
 260                 
 261         }
 262         
 263         DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count));
 264         
 265         if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
 266                 errno = EBADF;
 267                 TALLOC_FREE(frame);
 268                 return -1;
 269                 
 270         }
 271         
 272         offset = file->offset;
 273         
 274         /* Check that the buffer exists ... */
 275         
 276         if (buf == NULL) {
 277                 errno = EINVAL;
 278                 TALLOC_FREE(frame);
 279                 return -1;
 280                 
 281         }
 282         
 283         /*d_printf(">>>read: parsing %s\n", file->fname);*/
 284         if (SMBC_parse_path(frame,
 285                             context,
 286                             file->fname,
 287                             NULL,
 288                             &server,
 289                             &share,
 290                             &path,
 291                             &user,
 292                             &password,
 293                             NULL)) {
 294                 errno = EINVAL;
 295                 TALLOC_FREE(frame);
 296                 return -1;
 297         }
 298         
 299         /*d_printf(">>>read: resolving %s\n", path);*/
 300         if (!cli_resolve_path(frame, "", context->internal->auth_info,
 301                         file->srv->cli, path,
 302                         &targetcli, &targetpath)) {
 303                 d_printf("Could not resolve %s\n", path);
 304                 errno = ENOENT;
 305                 TALLOC_FREE(frame);
 306                 return -1;
 307         }
 308         /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
 309         
 310         ret = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count);
 311         
 312         if (ret < 0) {
 313                 
 314                 errno = SMBC_errno(context, targetcli);
 315                 TALLOC_FREE(frame);
 316                 return -1;
 317                 
 318         }
 319         
 320         file->offset += ret;
 321         
 322         DEBUG(4, ("  --> %d\n", ret));
 323         
 324         TALLOC_FREE(frame);
 325         return ret;  /* Success, ret bytes of data ... */
 326         
 327 }
 328 
 329 /*
 330  * Routine to write() a file ...
 331  */
 332 
 333 ssize_t
 334 SMBC_write_ctx(SMBCCTX *context,
     /* [<][>][^][v][top][bottom][index][help] */
 335                SMBCFILE *file,
 336                const void *buf,
 337                size_t count)
 338 {
 339         int ret;
 340         off_t offset;
 341         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
 342         char *path = NULL;
 343         char *targetpath = NULL;
 344         struct cli_state *targetcli = NULL;
 345         TALLOC_CTX *frame = talloc_stackframe();
 346         
 347         /* First check all pointers before dereferencing them */
 348         
 349         if (!context || !context->internal->initialized) {
 350                 
 351                 errno = EINVAL;
 352                 TALLOC_FREE(frame);
 353                 return -1;
 354                 
 355         }
 356         
 357         if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
 358                 errno = EBADF;
 359                 TALLOC_FREE(frame);
 360                 return -1;
 361         }
 362         
 363         /* Check that the buffer exists ... */
 364         
 365         if (buf == NULL) {
 366                 errno = EINVAL;
 367                 TALLOC_FREE(frame);
 368                 return -1;
 369                 
 370         }
 371         
 372         offset = file->offset; /* See "offset" comment in SMBC_read_ctx() */
 373         
 374         /*d_printf(">>>write: parsing %s\n", file->fname);*/
 375         if (SMBC_parse_path(frame,
 376                             context,
 377                             file->fname,
 378                             NULL,
 379                             &server,
 380                             &share,
 381                             &path,
 382                             &user,
 383                             &password,
 384                             NULL)) {
 385                 errno = EINVAL;
 386                 TALLOC_FREE(frame);
 387                 return -1;
 388         }
 389 
 390         /*d_printf(">>>write: resolving %s\n", path);*/
 391         if (!cli_resolve_path(frame, "", context->internal->auth_info,
 392                         file->srv->cli, path,
 393                         &targetcli, &targetpath)) {
 394                 d_printf("Could not resolve %s\n", path);
 395                 errno = ENOENT;
 396                 TALLOC_FREE(frame);
 397                 return -1;
 398         }
 399         /*d_printf(">>>write: resolved path as %s\n", targetpath);*/
 400         
 401         ret = cli_write(targetcli, file->cli_fd,
 402                         0, (char *)buf, offset, count);
 403         
 404         if (ret <= 0) {
 405                 errno = SMBC_errno(context, targetcli);
 406                 TALLOC_FREE(frame);
 407                 return -1;
 408                 
 409         }
 410         
 411         file->offset += ret;
 412         
 413         TALLOC_FREE(frame);
 414         return ret;  /* Success, 0 bytes of data ... */
 415 }
 416 
 417 /*
 418  * Routine to close() a file ...
 419  */
 420 
 421 int
 422 SMBC_close_ctx(SMBCCTX *context,
     /* [<][>][^][v][top][bottom][index][help] */
 423                SMBCFILE *file)
 424 {
 425         SMBCSRV *srv;
 426         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
 427         char *path = NULL;
 428         char *targetpath = NULL;
 429         struct cli_state *targetcli = NULL;
 430         TALLOC_CTX *frame = talloc_stackframe();
 431         
 432         if (!context || !context->internal->initialized) {
 433                 
 434                 errno = EINVAL;
 435                 TALLOC_FREE(frame);
 436                 return -1;
 437         }
 438         
 439         if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
 440                 errno = EBADF;
 441                 TALLOC_FREE(frame);
 442                 return -1;
 443         }
 444         
 445         /* IS a dir ... */
 446         if (!file->file) {
 447                 TALLOC_FREE(frame);
 448                 return smbc_getFunctionClosedir(context)(context, file);
 449         }
 450         
 451         /*d_printf(">>>close: parsing %s\n", file->fname);*/
 452         if (SMBC_parse_path(frame,
 453                             context,
 454                             file->fname,
 455                             NULL,
 456                             &server,
 457                             &share,
 458                             &path,
 459                             &user,
 460                             &password,
 461                             NULL)) {
 462                 errno = EINVAL;
 463                 TALLOC_FREE(frame);
 464                 return -1;
 465         }
 466         
 467         /*d_printf(">>>close: resolving %s\n", path);*/
 468         if (!cli_resolve_path(frame, "", context->internal->auth_info,
 469                         file->srv->cli, path,
 470                         &targetcli, &targetpath)) {
 471                 d_printf("Could not resolve %s\n", path);
 472                 errno = ENOENT;
 473                 TALLOC_FREE(frame);
 474                 return -1;
 475         }
 476         /*d_printf(">>>close: resolved path as %s\n", targetpath);*/
 477         
 478         if (!cli_close(targetcli, file->cli_fd)) {
 479                 
 480                 DEBUG(3, ("cli_close failed on %s. purging server.\n", 
 481                           file->fname));
 482                 /* Deallocate slot and remove the server 
 483                  * from the server cache if unused */
 484                 errno = SMBC_errno(context, targetcli);
 485                 srv = file->srv;
 486                 DLIST_REMOVE(context->internal->files, file);
 487                 SAFE_FREE(file->fname);
 488                 SAFE_FREE(file);
 489                 smbc_getFunctionRemoveUnusedServer(context)(context, srv);
 490                 TALLOC_FREE(frame);
 491                 return -1;
 492                 
 493         }
 494         
 495         DLIST_REMOVE(context->internal->files, file);
 496         SAFE_FREE(file->fname);
 497         SAFE_FREE(file);
 498         TALLOC_FREE(frame);
 499         
 500         return 0;
 501 }
 502 
 503 /*
 504  * Get info from an SMB server on a file. Use a qpathinfo call first
 505  * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo
 506  */
 507 bool
 508 SMBC_getatr(SMBCCTX * context,
     /* [<][>][^][v][top][bottom][index][help] */
 509             SMBCSRV *srv,
 510             char *path,
 511             uint16 *mode,
 512             SMB_OFF_T *size,
 513             struct timespec *create_time_ts,
 514             struct timespec *access_time_ts,
 515             struct timespec *write_time_ts,
 516             struct timespec *change_time_ts,
 517             SMB_INO_T *ino)
 518 {
 519         char *fixedpath = NULL;
 520         char *targetpath = NULL;
 521         struct cli_state *targetcli = NULL;
 522         time_t write_time;
 523         TALLOC_CTX *frame = talloc_stackframe();
 524         
 525         if (!context || !context->internal->initialized) {
 526                 
 527                 errno = EINVAL;
 528                 TALLOC_FREE(frame);
 529                 return False;
 530         }
 531         
 532         /* path fixup for . and .. */
 533         if (strequal(path, ".") || strequal(path, "..")) {
 534                 fixedpath = talloc_strdup(frame, "\\");
 535                 if (!fixedpath) {
 536                         errno = ENOMEM;
 537                         TALLOC_FREE(frame);
 538                         return False;
 539                 }
 540         } else {
 541                 fixedpath = talloc_strdup(frame, path);
 542                 if (!fixedpath) {
 543                         errno = ENOMEM;
 544                         TALLOC_FREE(frame);
 545                         return False;
 546                 }
 547                 trim_string(fixedpath, NULL, "\\..");
 548                 trim_string(fixedpath, NULL, "\\.");
 549         }
 550         DEBUG(4,("SMBC_getatr: sending qpathinfo\n"));
 551         
 552         if (!cli_resolve_path(frame, "", context->internal->auth_info,
 553                         srv->cli, fixedpath,
 554                         &targetcli, &targetpath)) {
 555                 d_printf("Couldn't resolve %s\n", path);
 556                 errno = ENOENT;
 557                 TALLOC_FREE(frame);
 558                 return False;
 559         }
 560         
 561         if (!srv->no_pathinfo2 &&
 562             cli_qpathinfo2(targetcli, targetpath,
 563                            create_time_ts,
 564                            access_time_ts,
 565                            write_time_ts,
 566                            change_time_ts,
 567                            size, mode, ino)) {
 568                 TALLOC_FREE(frame);
 569                 return True;
 570         }
 571         
 572         /* if this is NT then don't bother with the getatr */
 573         if (targetcli->capabilities & CAP_NT_SMBS) {
 574                 errno = EPERM;
 575                 TALLOC_FREE(frame);
 576                 return False;
 577         }
 578         
 579         if (cli_getatr(targetcli, targetpath, mode, size, &write_time)) {
 580                 
 581                 struct timespec w_time_ts;
 582                 
 583                 w_time_ts = convert_time_t_to_timespec(write_time);
 584                 
 585                 if (write_time_ts != NULL) {
 586                         *write_time_ts = w_time_ts;
 587                 }
 588                 
 589                 if (create_time_ts != NULL) {
 590                         *create_time_ts = w_time_ts;
 591                 }
 592                 
 593                 if (access_time_ts != NULL) {
 594                         *access_time_ts = w_time_ts;
 595                 }
 596                 
 597                 if (change_time_ts != NULL) {
 598                         *change_time_ts = w_time_ts;
 599                 }
 600                 
 601                 srv->no_pathinfo2 = True;
 602                 TALLOC_FREE(frame);
 603                 return True;
 604         }
 605         
 606         errno = EPERM;
 607         TALLOC_FREE(frame);
 608         return False;
 609         
 610 }
 611 
 612 /*
 613  * Set file info on an SMB server.  Use setpathinfo call first.  If that
 614  * fails, use setattrE..
 615  *
 616  * Access and modification time parameters are always used and must be
 617  * provided.  Create time, if zero, will be determined from the actual create
 618  * time of the file.  If non-zero, the create time will be set as well.
 619  *
 620  * "mode" (attributes) parameter may be set to -1 if it is not to be set.
 621  */
 622 bool
 623 SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, 
     /* [<][>][^][v][top][bottom][index][help] */
 624             time_t create_time,
 625             time_t access_time,
 626             time_t write_time,
 627             time_t change_time,
 628             uint16 mode)
 629 {
 630         int fd;
 631         int ret;
 632         TALLOC_CTX *frame = talloc_stackframe();
 633         
 634         /*
 635          * First, try setpathinfo (if qpathinfo succeeded), for it is the
 636          * modern function for "new code" to be using, and it works given a
 637          * filename rather than requiring that the file be opened to have its
 638          * attributes manipulated.
 639          */
 640         if (srv->no_pathinfo ||
 641             ! cli_setpathinfo(srv->cli, path,
 642                               create_time,
 643                               access_time,
 644                               write_time,
 645                               change_time,
 646                               mode)) {
 647                 
 648                 /*
 649                  * setpathinfo is not supported; go to plan B. 
 650                  *
 651                  * cli_setatr() does not work on win98, and it also doesn't
 652                  * support setting the access time (only the modification
 653                  * time), so in all cases, we open the specified file and use
 654                  * cli_setattrE() which should work on all OS versions, and
 655                  * supports both times.
 656                  */
 657                 
 658                 /* Don't try {q,set}pathinfo() again, with this server */
 659                 srv->no_pathinfo = True;
 660                 
 661                 /* Open the file */
 662                 if ((fd = cli_open(srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
 663                         
 664                         errno = SMBC_errno(context, srv->cli);
 665                         TALLOC_FREE(frame);
 666                         return -1;
 667                 }
 668                 
 669                 /* Set the new attributes */
 670                 ret = cli_setattrE(srv->cli, fd,
 671                                    change_time,
 672                                    access_time,
 673                                    write_time);
 674                 
 675                 /* Close the file */
 676                 cli_close(srv->cli, fd);
 677                 
 678                 /*
 679                  * Unfortunately, setattrE() doesn't have a provision for
 680                  * setting the access mode (attributes).  We'll have to try
 681                  * cli_setatr() for that, and with only this parameter, it
 682                  * seems to work on win98.
 683                  */
 684                 if (ret && mode != (uint16) -1) {
 685                         ret = cli_setatr(srv->cli, path, mode, 0);
 686                 }
 687                 
 688                 if (! ret) {
 689                         errno = SMBC_errno(context, srv->cli);
 690                         TALLOC_FREE(frame);
 691                         return False;
 692                 }
 693         }
 694         
 695         TALLOC_FREE(frame);
 696         return True;
 697 }
 698 
 699 /*
 700  * A routine to lseek() a file
 701  */
 702 
 703 off_t
 704 SMBC_lseek_ctx(SMBCCTX *context,
     /* [<][>][^][v][top][bottom][index][help] */
 705                SMBCFILE *file,
 706                off_t offset,
 707                int whence)
 708 {
 709         SMB_OFF_T size;
 710         char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
 711         char *path = NULL;
 712         char *targetpath = NULL;
 713         struct cli_state *targetcli = NULL;
 714         TALLOC_CTX *frame = talloc_stackframe();
 715         
 716         if (!context || !context->internal->initialized) {
 717                 
 718                 errno = EINVAL;
 719                 TALLOC_FREE(frame);
 720                 return -1;
 721         }
 722         
 723         if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
 724                 
 725                 errno = EBADF;
 726                 TALLOC_FREE(frame);
 727                 return -1;
 728                 
 729         }
 730         
 731         if (!file->file) {
 732                 
 733                 errno = EINVAL;
 734                 TALLOC_FREE(frame);
 735                 return -1;      /* Can't lseek a dir ... */
 736                 
 737         }
 738         
 739         switch (whence) {
 740         case SEEK_SET:
 741                 file->offset = offset;
 742                 break;
 743                 
 744         case SEEK_CUR:
 745                 file->offset += offset;
 746                 break;
 747                 
 748         case SEEK_END:
 749                 /*d_printf(">>>lseek: parsing %s\n", file->fname);*/
 750                 if (SMBC_parse_path(frame,
 751                                     context,
 752                                     file->fname,
 753                                     NULL,
 754                                     &server,
 755                                     &share,
 756                                     &path,
 757                                     &user,
 758                                     &password,
 759                                     NULL)) {
 760                         errno = EINVAL;
 761                         TALLOC_FREE(frame);
 762                         return -1;
 763                 }
 764                 
 765                 /*d_printf(">>>lseek: resolving %s\n", path);*/
 766                 if (!cli_resolve_path(frame, "", context->internal->auth_info,
 767                                 file->srv->cli, path,
 768                                 &targetcli, &targetpath)) {
 769                         d_printf("Could not resolve %s\n", path);
 770                         errno = ENOENT;
 771                         TALLOC_FREE(frame);
 772                         return -1;
 773                 }
 774                 /*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/
 775                 
 776                 if (!cli_qfileinfo(targetcli, file->cli_fd, NULL,
 777                                    &size, NULL, NULL, NULL, NULL, NULL))
 778                 {
 779                         SMB_OFF_T b_size = size;
 780                         if (!cli_getattrE(targetcli, file->cli_fd,
 781                                           NULL, &b_size, NULL, NULL, NULL))
 782                         {
 783                                 errno = EINVAL;
 784                                 TALLOC_FREE(frame);
 785                                 return -1;
 786                         } else
 787                                 size = b_size;
 788                 }
 789                 file->offset = size + offset;
 790                 break;
 791                 
 792         default:
 793                 errno = EINVAL;
 794                 break;
 795                 
 796         }
 797         
 798         TALLOC_FREE(frame);
 799         return file->offset;
 800         
 801 }
 802 
 803 
 804 /*
 805  * Routine to truncate a file given by its file descriptor, to a specified size
 806  */
 807 
 808 int
 809 SMBC_ftruncate_ctx(SMBCCTX *context,
     /* [<][>][^][v][top][bottom][index][help] */
 810                    SMBCFILE *file,
 811                    off_t length)
 812 {
 813         SMB_OFF_T size = length;
 814         char *server = NULL;
 815         char *share = NULL;
 816         char *user = NULL;
 817         char *password = NULL;
 818         char *path = NULL;
 819         char *targetpath = NULL;
 820         struct cli_state *targetcli = NULL;
 821         TALLOC_CTX *frame = talloc_stackframe();
 822         
 823         if (!context || !context->internal->initialized) {
 824                 
 825                 errno = EINVAL;
 826                 TALLOC_FREE(frame);
 827                 return -1;
 828         }
 829         
 830         if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
 831                 errno = EBADF;
 832                 TALLOC_FREE(frame);
 833                 return -1;
 834         }
 835         
 836         if (!file->file) {
 837                 errno = EINVAL;
 838                 TALLOC_FREE(frame);
 839                 return -1;
 840         }
 841         
 842         /*d_printf(">>>fstat: parsing %s\n", file->fname);*/
 843         if (SMBC_parse_path(frame,
 844                             context,
 845                             file->fname,
 846                             NULL,
 847                             &server,
 848                             &share,
 849                             &path,
 850                             &user,
 851                             &password,
 852                             NULL)) {
 853                 errno = EINVAL;
 854                 TALLOC_FREE(frame);
 855                 return -1;
 856         }
 857         
 858         /*d_printf(">>>fstat: resolving %s\n", path);*/
 859         if (!cli_resolve_path(frame, "", context->internal->auth_info,
 860                         file->srv->cli, path,
 861                         &targetcli, &targetpath)) {
 862                 d_printf("Could not resolve %s\n", path);
 863                 errno = ENOENT;
 864                 TALLOC_FREE(frame);
 865                 return -1;
 866         }
 867         /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
 868         
 869         if (!cli_ftruncate(targetcli, file->cli_fd, size)) {
 870                 errno = EINVAL;
 871                 TALLOC_FREE(frame);
 872                 return -1;
 873         }
 874         
 875         TALLOC_FREE(frame);
 876         return 0;
 877         
 878 }

/* [<][>][^][v][top][bottom][index][help] */