Ignore:
Timestamp:
May 26, 2009, 9:44:50 AM (16 years ago)
Author:
Herwig Bauernfeind
Message:

Update 3.2 branch to 3.2.6

Location:
branches/samba-3.2.x/source/smbd
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • branches/samba-3.2.x/source/smbd/build_options.c

    r204 r228  
    139139        output(screen, "   HAVE_SYS_ID_H\n");
    140140#endif
     141#ifdef HAVE_SYS_INOTIFY_H
     142        output(screen, "   HAVE_SYS_INOTIFY_H\n");
     143#endif
    141144#ifdef HAVE_SYS_IOCTL_H
    142145        output(screen, "   HAVE_SYS_IOCTL_H\n");
     
    287290        output(screen, "   HAVE_CTYPE_H\n");
    288291#endif
     292#ifdef HAVE_CUPS_CUPS_H
     293        output(screen, "   HAVE_CUPS_CUPS_H\n");
     294#endif
     295#ifdef HAVE_CUPS_LANGUAGE_H
     296        output(screen, "   HAVE_CUPS_LANGUAGE_H\n");
     297#endif
    289298#ifdef HAVE_DEVNM_H
    290299        output(screen, "   HAVE_DEVNM_H\n");
     
    28052814        output(screen, "   SYSCONF_SC_PAGESIZE\n");
    28062815#endif
     2816#ifdef SYSLOG_FACILITY
     2817        output(screen, "   SYSLOG_FACILITY\n");
     2818#endif
    28072819#ifdef SYSV
    28082820        output(screen, "   SYSV\n");
     
    32273239#ifdef vfs_shadow_copy_init
    32283240        output(screen, "   vfs_shadow_copy_init\n");
     3241#endif
     3242#ifdef vfs_smb_traffic_analyzer_init
     3243        output(screen, "   vfs_smb_traffic_analyzer_init\n");
    32293244#endif
    32303245#ifdef vfs_solarisacl_init
  • branches/samba-3.2.x/source/smbd/close.c

    r137 r228  
    107107{
    108108        NTSTATUS status = NT_STATUS_OK;
    109         connection_struct *conn = fsp->conn;
    110    
     109
    111110        if (fsp->fh->fd != -1) {
    112111                if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
     
    116115        }
    117116
    118         conn->num_files_open--;
    119117        return status;
    120 }   
     118}
    121119
    122120/****************************************************************************
     
    583581        DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
    584582                conn->user,fsp->fsp_name,
    585                 conn->num_files_open,
     583                conn->num_files_open - 1,
    586584                nt_errstr(status) ));
    587585
  • branches/samba-3.2.x/source/smbd/conn.c

    r136 r228  
    268268        handle = conn->vfs_handles;
    269269        while(handle) {
     270                thandle = handle->next;
    270271                DLIST_REMOVE(conn->vfs_handles, handle);
    271                 thandle = handle->next;
    272272                if (handle->free_data)
    273273                        handle->free_data(&handle->data);
  • branches/samba-3.2.x/source/smbd/fake_file.c

    r133 r228  
    142142        }
    143143
    144         conn->num_files_open++;
    145144        *result = fsp;
    146145        return NT_STATUS_OK;
  • branches/samba-3.2.x/source/smbd/filename.c

    r149 r228  
    102102
    103103If the saved_last_component != 0, then the unmodified last component
    104 of the pathname is returned there. This is used in an exceptional
    105 case in reply_mv (so far). If saved_last_component == 0 then nothing
     104of the pathname is returned there. If saved_last_component == 0 then nothing
    106105is returned there.
    107106
     
    196195        }
    197196
    198         /*
    199          * Ensure saved_last_component is valid even if file exists.
    200          */
    201 
    202         if(pp_saved_last_component) {
    203                 end = strrchr_m(orig_path, '/');
    204                 if (end) {
    205                         *pp_saved_last_component = talloc_strdup(ctx, end + 1);
    206                 } else {
    207                         *pp_saved_last_component = talloc_strdup(ctx,
    208                                                         orig_path);
    209                 }
    210         }
    211 
    212197        if (!(name = talloc_strdup(ctx, orig_path))) {
    213198                DEBUG(0, ("talloc_strdup failed\n"));
    214199                return NT_STATUS_NO_MEMORY;
    215         }
    216 
    217         if (!lp_posix_pathnames()) {
    218                 stream = strchr_m(name, ':');
    219 
    220                 if (stream != NULL) {
    221                         char *tmp = talloc_strdup(ctx, stream);
    222                         if (tmp == NULL) {
    223                                 TALLOC_FREE(name);
    224                                 return NT_STATUS_NO_MEMORY;
    225                         }
    226                         *stream = '\0';
    227                         stream = tmp;
    228                 }
    229200        }
    230201
     
    241212                        !conn->short_case_preserve) {
    242213                strnorm(name, lp_defaultcase(SNUM(conn)));
     214        }
     215
     216        /*
     217         * Ensure saved_last_component is valid even if file exists.
     218         */
     219
     220        if(pp_saved_last_component) {
     221                end = strrchr_m(name, '/');
     222                if (end) {
     223                        *pp_saved_last_component = talloc_strdup(ctx, end + 1);
     224                } else {
     225                        *pp_saved_last_component = talloc_strdup(ctx,
     226                                                        name);
     227                }
     228        }
     229
     230        if (!lp_posix_pathnames()) {
     231                stream = strchr_m(name, ':');
     232
     233                if (stream != NULL) {
     234                        char *tmp = talloc_strdup(ctx, stream);
     235                        if (tmp == NULL) {
     236                                TALLOC_FREE(name);
     237                                return NT_STATUS_NO_MEMORY;
     238                        }
     239                        *stream = '\0';
     240                        stream = tmp;
     241                }
    243242        }
    244243
  • branches/samba-3.2.x/source/smbd/files.c

    r133 r228  
    123123        chain_fsp = fsp;
    124124
    125         /* A new fsp invalidates a negative fsp_fi_cache. */
    126         if (fsp_fi_cache.fsp == NULL) {
    127                 ZERO_STRUCT(fsp_fi_cache);
    128         }
     125        /* A new fsp invalidates the positive and
     126          negative fsp_fi_cache as the new fsp is pushed
     127          at the start of the list and we search from
     128          a cache hit to the *end* of the list. */
     129
     130        ZERO_STRUCT(fsp_fi_cache);
     131
     132        conn->num_files_open++;
    129133
    130134        *result = fsp;
     
    327331
    328332        for (fsp=Files;fsp;fsp=fsp->next) {
    329                 if ( fsp->fh->fd != -1 &&
    330                      file_id_equal(&fsp->file_id, &id)) {
     333                if (file_id_equal(&fsp->file_id, &id)) {
    331334                        /* Setup positive cache. */
    332335                        fsp_fi_cache.fsp = fsp;
     
    349352
    350353        for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
    351                 if ( fsp->fh->fd != -1 &&
    352                      file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
     354                if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
    353355                        return fsp;
    354356                }
     
    428430                 fsp->fnum, files_used));
    429431
    430         /* this is paranoia, just in case someone tries to reuse the
    431            information */
    432         ZERO_STRUCTP(fsp);
     432        fsp->conn->num_files_open--;
    433433
    434434        if (fsp == chain_fsp) {
     
    445445                vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp);
    446446        }
     447
     448        /* this is paranoia, just in case someone tries to reuse the
     449           information */
     450        ZERO_STRUCTP(fsp);
    447451
    448452        SAFE_FREE(fsp);
     
    501505****************************************************************************/
    502506
    503 NTSTATUS dup_file_fsp(files_struct *fsp,
    504                                 uint32 access_mask,
    505                                 uint32 share_access,
    506                                 uint32 create_options,
    507                                 files_struct **result)
    508 {
    509         NTSTATUS status;
    510         files_struct *dup_fsp;
    511 
    512         status = file_new(fsp->conn, &dup_fsp);
    513 
    514         if (!NT_STATUS_IS_OK(status)) {
    515                 return status;
    516         }
    517 
    518         SAFE_FREE(dup_fsp->fh);
    519 
    520         dup_fsp->fh = fsp->fh;
    521         dup_fsp->fh->ref_count++;
    522 
    523         dup_fsp->file_id = fsp->file_id;
    524         dup_fsp->initial_allocation_size = fsp->initial_allocation_size;
    525         dup_fsp->mode = fsp->mode;
    526         dup_fsp->file_pid = fsp->file_pid;
    527         dup_fsp->vuid = fsp->vuid;
    528         dup_fsp->open_time = fsp->open_time;
    529         dup_fsp->access_mask = access_mask;
    530         dup_fsp->share_access = share_access;
    531         dup_fsp->oplock_type = fsp->oplock_type;
    532         dup_fsp->can_lock = fsp->can_lock;
    533         dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
    534         if (!CAN_WRITE(fsp->conn)) {
    535                 dup_fsp->can_write = False;
     507void dup_file_fsp(files_struct *from,
     508                        uint32 access_mask,
     509                        uint32 share_access,
     510                        uint32 create_options,
     511                        files_struct *to)
     512{
     513        SAFE_FREE(to->fh);
     514
     515        to->fh = from->fh;
     516        to->fh->ref_count++;
     517
     518        to->file_id = from->file_id;
     519        to->initial_allocation_size = from->initial_allocation_size;
     520        to->mode = from->mode;
     521        to->file_pid = from->file_pid;
     522        to->vuid = from->vuid;
     523        to->open_time = from->open_time;
     524        to->access_mask = access_mask;
     525        to->share_access = share_access;
     526        to->oplock_type = from->oplock_type;
     527        to->can_lock = from->can_lock;
     528        to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
     529        if (!CAN_WRITE(from->conn)) {
     530                to->can_write = False;
    536531        } else {
    537                 dup_fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
    538         }
    539         dup_fsp->print_file = fsp->print_file;
    540         dup_fsp->modified = fsp->modified;
    541         dup_fsp->is_directory = fsp->is_directory;
    542         dup_fsp->is_stat = fsp->is_stat;
    543         dup_fsp->aio_write_behind = fsp->aio_write_behind;
    544         string_set(&dup_fsp->fsp_name,fsp->fsp_name);
    545 
    546         *result = dup_fsp;
    547         return NT_STATUS_OK;
    548 }
     532                to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
     533        }
     534        to->print_file = from->print_file;
     535        to->modified = from->modified;
     536        to->is_directory = from->is_directory;
     537        to->is_stat = from->is_stat;
     538        to->aio_write_behind = from->aio_write_behind;
     539        string_set(&to->fsp_name,from->fsp_name);
     540}
  • branches/samba-3.2.x/source/smbd/mangle.c

    r133 r228  
    141141           we just truncate the string */
    142142        if (!lp_manglednames(p)) {
    143                 safe_strcpy(out,in,12);
     143                strlcpy(out, in, 13);
    144144                return True;
    145145        }
  • branches/samba-3.2.x/source/smbd/msdfs.c

    r138 r228  
    896896                                char **ppdata,
    897897                                struct junction_map *junction,
    898                                 int consumedcnt,
    899898                                bool self_referral)
    900899{
     
    961960
    962961        /* create the header */
    963         SSVAL(pdata,0,consumedcnt * 2); /* path consumed */
     962        SSVAL(pdata,0,requestedpathlen - 2); /* UCS2 of path consumed minus
     963                                                2 byte null */
    964964        /* number of referral in this pkt */
    965965        SSVAL(pdata,2,junction->referral_count);
     
    10101010                                char **ppdata,
    10111011                                struct junction_map *junction,
    1012                                 int consumedcnt,
    10131012                                bool self_referral)
    10141013{
     
    10571056
    10581057        /* create the header */
    1059         SSVAL(pdata,0,consumedcnt * 2); /* path consumed */
     1058        SSVAL(pdata,0,reqpathlen - 2); /* UCS2 of path consumed minus
     1059                                          2 byte null */
    10601060        SSVAL(pdata,2,junction->referral_count); /* number of referral */
    10611061        if(self_referral) {
     
    11971197                reply_size = setup_ver2_dfs_referral(pathnamep,
    11981198                                        ppdata, junction,
    1199                                         consumedcnt, self_referral);
     1199                                        self_referral);
    12001200                break;
    12011201        case 3:
    12021202                reply_size = setup_ver3_dfs_referral(pathnamep, ppdata,
    1203                                         junction, consumedcnt, self_referral);
     1203                                        junction, self_referral);
    12041204                break;
    12051205        default:
  • branches/samba-3.2.x/source/smbd/notify.c

    r136 r228  
    360360        char *fullpath;
    361361
     362        if (path[0] == '.' && path[1] == '/') {
     363                path += 2;
     364        }
    362365        if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
    363366                DEBUG(0, ("asprintf failed\n"));
  • branches/samba-3.2.x/source/smbd/notify_inotify.c

    r133 r228  
    2626#ifdef HAVE_INOTIFY
    2727
     28#if HAVE_SYS_INOTIFY_H
     29#include <sys/inotify.h>
     30#else
     31
    2832#ifdef HAVE_ASM_TYPES_H
    2933#include <asm/types.h>
     
    5862
    5963#endif
    60 
     64#endif
    6165
    6266/* older glibc headers don't have these defines either */
     
    244248        if (e == NULL) return;
    245249
    246         if (read(in->fd, e0, bufsize) != bufsize) {
     250        if (sys_read(in->fd, e0, bufsize) != bufsize) {
    247251                DEBUG(0,("Failed to read all inotify data\n"));
    248252                talloc_free(e0);
     
    251255
    252256        /* we can get more than one event in the buffer */
    253         while (bufsize >= sizeof(*e)) {
     257        while (e && (bufsize >= sizeof(*e))) {
    254258                struct inotify_event *e2 = NULL;
    255259                bufsize -= e->len + sizeof(*e);
  • branches/samba-3.2.x/source/smbd/nttrans.c

    r205 r228  
    773773        if (psd->dacl==0) {
    774774                security_info_sent &= ~DACL_SECURITY_INFORMATION;
     775        }
     776
     777        if (DEBUGLEVEL >= 10) {
     778                DEBUG(10,("set_sd for file %s\n", fsp->fsp_name ));
     779                NDR_PRINT_DEBUG(security_descriptor, psd);
    775780        }
    776781
     
    16481653        DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size));
    16491654
     1655        if (DEBUGLEVEL >= 10) {
     1656                DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name ));
     1657                NDR_PRINT_DEBUG(security_descriptor, psd);
     1658        }
     1659
    16501660        SIVAL(params,0,(uint32)sd_size);
    16511661
  • branches/samba-3.2.x/source/smbd/open.c

    r204 r228  
    285285            (!file_existed && (local_flags & O_CREAT)) ||
    286286            ((local_flags & O_TRUNC) == O_TRUNC) ) {
     287                const char *wild;
    287288
    288289                /*
     
    306307
    307308                /* Don't create files with Microsoft wildcard characters. */
     309                if (fsp->base_fsp) {
     310                        /*
     311                         * wildcard characters are allowed in stream names
     312                         * only test the basefilename
     313                         */
     314                        wild = fsp->base_fsp->fsp_name;
     315                } else {
     316                        wild = path;
     317                }
    308318                if ((local_flags & O_CREAT) && !file_existed &&
    309                     ms_has_wild(path))  {
     319                    ms_has_wild(wild))  {
    310320                        return NT_STATUS_OBJECT_NAME_INVALID;
    311321                }
     
    405415                 current_user_info.smb_name : conn->user,fsp->fsp_name,
    406416                 BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
    407                  conn->num_files_open + 1));
     417                 conn->num_files_open));
    408418
    409419        errno = 0;
     
    894904****************************************************************************/
    895905
    896 static files_struct *fcb_or_dos_open(connection_struct *conn,
     906static NTSTATUS fcb_or_dos_open(connection_struct *conn,
     907                                     files_struct *fsp_to_dup_into,
    897908                                     const char *fname,
    898909                                     struct file_id id,
     
    904915{
    905916        files_struct *fsp;
    906         files_struct *dup_fsp;
    907917
    908918        DEBUG(5,("fcb_or_dos_open: attempting old open semantics for "
     
    933943
    934944        if (!fsp) {
    935                 return NULL;
     945                return NT_STATUS_NOT_FOUND;
    936946        }
    937947
     
    940950            (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
    941951                DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n"));
    942                 return NULL;
     952                return NT_STATUS_INVALID_PARAMETER;
    943953        }
    944954
    945955        /* We need to duplicate this fsp. */
    946         if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access,
    947                                           create_options, &dup_fsp))) {
    948                 return NULL;
    949         }
    950 
    951         return dup_fsp;
     956        dup_file_fsp(fsp, access_mask, share_access,
     957                          create_options, fsp_to_dup_into);
     958
     959        return NT_STATUS_OK;
    952960}
    953961
     
    11291137
    11301138/****************************************************************************
    1131  Open a file with a share mode.
     1139 Open a file with a share mode. Passed in an already created files_struct *.
    11321140****************************************************************************/
    11331141
    1134 NTSTATUS open_file_ntcreate(connection_struct *conn,
     1142static NTSTATUS open_file_ntcreate_internal(connection_struct *conn,
    11351143                            struct smb_request *req,
    11361144                            const char *fname,
     
    11441152                                                        /* Information (FILE_EXISTS etc.) */
    11451153                            int *pinfo,
    1146                             files_struct **result)
     1154                            files_struct *fsp)
    11471155{
    11481156        int flags=0;
     
    11541162        struct file_id id;
    11551163        NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
    1156         files_struct *fsp = NULL;
    11571164        mode_t new_unx_mode = (mode_t)0;
    11581165        mode_t unx_mode = (mode_t)0;
     
    11711178
    11721179        if (conn->printer) {
    1173                 /* 
     1180                /*
    11741181                 * Printers are handled completely differently.
    11751182                 * Most of the passed parameters are ignored.
     
    11821189                DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
    11831190
    1184                 return print_fsp_open(conn, fname, result);
     1191                return print_fsp_open(conn, fname, fsp);
    11851192        }
    11861193
     
    14391446        }
    14401447
    1441         status = file_new(conn, &fsp);
    1442         if(!NT_STATUS_IS_OK(status)) {
    1443                 return status;
    1444         }
    1445 
    14461448        fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf);
    14471449        fsp->share_access = share_access;
     
    14681470
    14691471                if (lck == NULL) {
    1470                         file_free(fsp);
    14711472                        DEBUG(0, ("Could not get share mode lock\n"));
    14721473                        return NT_STATUS_SHARING_VIOLATION;
     
    14791480                        schedule_defer_open(lck, request_time, req);
    14801481                        TALLOC_FREE(lck);
    1481                         file_free(fsp);
    14821482                        return NT_STATUS_SHARING_VIOLATION;
    14831483                }
     
    14991499                                schedule_defer_open(lck, request_time, req);
    15001500                                TALLOC_FREE(lck);
    1501                                 file_free(fsp);
    15021501                                return NT_STATUS_SHARING_VIOLATION;
    15031502                        }
     
    15071506                        /* DELETE_PENDING is not deferred for a second */
    15081507                        TALLOC_FREE(lck);
    1509                         file_free(fsp);
    15101508                        return status;
    15111509                }
     
    15221520                            (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
    15231521                             NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
    1524                                 files_struct *fsp_dup;
    1525 
    15261522                                if (req == NULL) {
    15271523                                        DEBUG(0, ("DOS open without an SMB "
    15281524                                                  "request!\n"));
    15291525                                        TALLOC_FREE(lck);
    1530                                         file_free(fsp);
    15311526                                        return NT_STATUS_INTERNAL_ERROR;
    15321527                                }
     
    15341529                                /* Use the client requested access mask here,
    15351530                                 * not the one we open with. */
    1536                                 fsp_dup = fcb_or_dos_open(conn, fname, id,
     1531                                status = fcb_or_dos_open(conn,
     1532                                                          fsp,
     1533                                                          fname,
     1534                                                          id,
    15371535                                                          req->smbpid,
    15381536                                                          req->vuid,
     
    15411539                                                          create_options);
    15421540
    1543                                 if (fsp_dup) {
     1541                                if (NT_STATUS_IS_OK(status)) {
    15441542                                        TALLOC_FREE(lck);
    1545                                         file_free(fsp);
    15461543                                        if (pinfo) {
    15471544                                                *pinfo = FILE_WAS_OPENED;
    15481545                                        }
    1549                                         conn->num_files_open++;
    1550                                         *result = fsp_dup;
    15511546                                        return NT_STATUS_OK;
    15521547                                }
     
    16291624                                status = NT_STATUS_ACCESS_DENIED;
    16301625                        }
    1631                         file_free(fsp);
    16321626                        return status;
    16331627                }
     
    16671661                        TALLOC_FREE(lck);
    16681662                }
    1669                 file_free(fsp);
    16701663                return fsp_open;
    16711664        }
     
    16981691                                  "mode lock for %s\n", fname));
    16991692                        fd_close(fsp);
    1700                         file_free(fsp);
    17011693                        return NT_STATUS_SHARING_VIOLATION;
    17021694                }
     
    17091701                        TALLOC_FREE(lck);
    17101702                        fd_close(fsp);
    1711                         file_free(fsp);
    17121703                        return NT_STATUS_SHARING_VIOLATION;
    17131704                }
     
    17281719                                TALLOC_FREE(lck);
    17291720                                fd_close(fsp);
    1730                                 file_free(fsp);
    17311721                                return NT_STATUS_SHARING_VIOLATION;
    17321722                        }
     
    17371727
    17381728                        fd_close(fsp);
    1739                         file_free(fsp);
    17401729
    17411730                        state.delayed_for_oplocks = False;
     
    17791768                        TALLOC_FREE(lck);
    17801769                        fd_close(fsp);
    1781                         file_free(fsp);
    17821770
    17831771                        return NT_STATUS_SHARING_VIOLATION;
     
    18051793                        TALLOC_FREE(lck);
    18061794                        fd_close(fsp);
    1807                         file_free(fsp);
    18081795                        return status;
    18091796                }
     
    18651852                        TALLOC_FREE(lck);
    18661853                        fd_close(fsp);
    1867                         file_free(fsp);
    18681854                        return status;
    18691855                }
     
    19411927        TALLOC_FREE(lck);
    19421928
    1943         conn->num_files_open++;
     1929        return NT_STATUS_OK;
     1930}
     1931
     1932/****************************************************************************
     1933 Open a file with a share mode.
     1934****************************************************************************/
     1935
     1936NTSTATUS open_file_ntcreate(connection_struct *conn,
     1937                            struct smb_request *req,
     1938                            const char *fname,
     1939                            SMB_STRUCT_STAT *psbuf,
     1940                            uint32 access_mask,         /* access bits (FILE_READ_DATA etc.) */
     1941                            uint32 share_access,        /* share constants (FILE_SHARE_READ etc) */
     1942                            uint32 create_disposition,  /* FILE_OPEN_IF etc. */
     1943                            uint32 create_options,      /* options such as delete on close. */
     1944                            uint32 new_dos_attributes,  /* attributes used for new file. */
     1945                            int oplock_request,         /* internal Samba oplock codes. */
     1946                                                        /* Information (FILE_EXISTS etc.) */
     1947                            int *pinfo,
     1948                            files_struct **result)
     1949{
     1950        NTSTATUS status;
     1951        files_struct *fsp = NULL;
     1952
     1953        *result = NULL;
     1954
     1955        status = file_new(conn, &fsp);
     1956        if(!NT_STATUS_IS_OK(status)) {
     1957                return status;
     1958        }
     1959
     1960        status = open_file_ntcreate_internal(conn,
     1961                                        req,
     1962                                        fname,
     1963                                        psbuf,
     1964                                        access_mask,
     1965                                        share_access,
     1966                                        create_disposition,
     1967                                        create_options,
     1968                                        new_dos_attributes,
     1969                                        oplock_request,
     1970                                        pinfo,
     1971                                        fsp);
     1972
     1973        if(!NT_STATUS_IS_OK(status)) {
     1974                file_free(fsp);
     1975                return status;
     1976        }
    19441977
    19451978        *result = fsp;
    1946         return NT_STATUS_OK;
     1979        return status;
    19471980}
    19481981
     
    19712004                           0, FILE_WRITE_DATA, FILE_WRITE_DATA);
    19722005
    1973         /* 
     2006        /*
    19742007         * This is not a user visible file open.
    1975          * Don't set a share mode and don't increment
    1976          * the conn->num_files_open.
     2008         * Don't set a share mode.
    19772009         */
    19782010
     
    22792311        }
    22802312
    2281         conn->num_files_open++;
    2282 
    22832313        *result = fsp;
    22842314        return NT_STATUS_OK;
     
    23552385        string_set(&fsp->fsp_name,fname);
    23562386
    2357         conn->num_files_open++;
    2358 
    23592387        *result = fsp;
    23602388        return NT_STATUS_OK;
     
    26632691            && (share_access & FILE_SHARE_DELETE)
    26642692            && (access_mask & DELETE_ACCESS)
    2665             && (((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY)
    2666                  && !lp_delete_readonly(SNUM(conn)))
    2667                 || !can_delete_file_in_directory(conn, fname))) {
     2693            && (!can_delete_file_in_directory(conn, fname))) {
    26682694                status = NT_STATUS_ACCESS_DENIED;
    26692695                goto fail;
     
    27102736                        break;
    27112737                }
     2738
     2739                DEBUG(10, ("Recursing into create_file_unixpath for "
     2740                        "base %s\n", base));
    27122741
    27132742                status = create_file_unixpath(conn, NULL, base, 0,
     
    27232752                        goto fail;
    27242753                }
     2754                /* we don't need to low level fd */
     2755                fd_close(base_fsp);
    27252756        }
    27262757
     
    27592790                 */
    27602791
    2761                 status = open_file_ntcreate(
    2762                         conn, req, fname, &sbuf, access_mask, share_access,
    2763                         create_disposition, create_options, file_attributes,
    2764                         oplock_request, &info, &fsp);
     2792                if (base_fsp) {
     2793                        /*
     2794                         * We're opening the stream element of a base_fsp
     2795                         * we already opened. We need to initialize
     2796                         * the fsp first, and set up the base_fsp pointer.
     2797                         */
     2798                        status = file_new(conn, &fsp);
     2799                        if(!NT_STATUS_IS_OK(status)) {
     2800                                goto fail;
     2801                        }
     2802
     2803                        fsp->base_fsp = base_fsp;
     2804
     2805                        status = open_file_ntcreate_internal(conn,
     2806                                                req,
     2807                                                fname,
     2808                                                &sbuf,
     2809                                                access_mask,
     2810                                                share_access,
     2811                                                create_disposition,
     2812                                                create_options,
     2813                                                file_attributes,
     2814                                                oplock_request,
     2815                                                &info,
     2816                                                fsp);
     2817
     2818                        if(!NT_STATUS_IS_OK(status)) {
     2819                                file_free(fsp);
     2820                                fsp = NULL;
     2821                        }
     2822                } else {
     2823                        status = open_file_ntcreate(
     2824                                conn, req, fname, &sbuf, access_mask, share_access,
     2825                                create_disposition, create_options, file_attributes,
     2826                                oplock_request, &info, &fsp);
     2827                }
    27652828
    27662829                if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
     2830
     2831                        /* A stream open never opens a directory */
     2832
     2833                        if (base_fsp) {
     2834                                status = NT_STATUS_FILE_IS_A_DIRECTORY;
     2835                                goto fail;
     2836                        }
    27672837
    27682838                        /*
     
    27882858                goto fail;
    27892859        }
     2860
     2861        fsp->base_fsp = base_fsp;
    27902862
    27912863        /*
     
    28662938        DEBUG(10, ("create_file_unixpath: info=%d\n", info));
    28672939
    2868         /*
    2869          * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In
    2870          * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would
    2871          * also close fsp->base_fsp which we have to also do explicitly in
    2872          * this routine here, as not in all "goto fail:" we have the fsp set
    2873          * up already to be initialized with the base_fsp.
    2874          */
    2875 
    2876         fsp->base_fsp = base_fsp;
    2877 
    28782940        *result = fsp;
    28792941        if (pinfo != NULL) {
     
    28942956
    28952957        if (fsp != NULL) {
     2958                if (base_fsp && fsp->base_fsp == base_fsp) {
     2959                        /*
     2960                         * The close_file below will close
     2961                         * fsp->base_fsp.
     2962                         */
     2963                        base_fsp = NULL;
     2964                }
    28962965                close_file(fsp, ERROR_CLOSE);
    28972966                fsp = NULL;
     
    30533122                         * close it
    30543123                         */
     3124
    30553125                        status = open_fake_file(conn, fake_file_type, fname,
    30563126                                                access_mask, &fsp);
  • branches/samba-3.2.x/source/smbd/posix_acls.c

    r204 r228  
    32223222}
    32233223
     3224#if 0
     3225/* Disable this - prevents ACL inheritance from the ACL editor. JRA. */
     3226
    32243227/****************************************************************************
    32253228 Take care of parent ACL inheritance.
     
    34143417        return status;
    34153418}
     3419#endif
    34163420
    34173421/****************************************************************************
     
    35263530        create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
    35273531
     3532#if 0
     3533        /* Disable this - prevents ACL inheritance from the ACL editor. JRA. */
     3534
     3535        /* See here: http://www.codeproject.com/KB/winsdk/accessctrl2.aspx
     3536         * for details and also the log trace in bug #4308. JRA.
     3537         */
     3538
    35283539        if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
    35293540                psd->dacl != NULL &&
     
    35373548                }
    35383549        }
     3550#endif
    35393551
    35403552        acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
  • branches/samba-3.2.x/source/smbd/process.c

    r204 r228  
    14061406                if (!change_to_user(conn,session_tag)) {
    14071407                        reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
     1408                        remove_deferred_open_smb_message(req->mid);
    14081409                        return conn;
    14091410                }
  • branches/samba-3.2.x/source/smbd/reply.c

    r204 r228  
    5555        NTSTATUS ret = NT_STATUS_OK;
    5656        bool start_of_name_component = True;
     57        bool stream_started = false;
    5758
    5859        *p_last_component_contains_wcard = False;
    5960
    6061        while (*s) {
    61                 if (IS_PATH_SEP(*s,posix_path)) {
     62                if (stream_started) {
     63                        switch (*s) {
     64                        case '/':
     65                        case '\\':
     66                                return NT_STATUS_OBJECT_NAME_INVALID;
     67                        case ':':
     68                                if (s[1] == '\0') {
     69                                        return NT_STATUS_OBJECT_NAME_INVALID;
     70                                }
     71                                if (strchr_m(&s[1], ':')) {
     72                                        return NT_STATUS_OBJECT_NAME_INVALID;
     73                                }
     74                                if (StrCaseCmp(s, ":$DATA") != 0) {
     75                                        return NT_STATUS_INVALID_PARAMETER;
     76                                }
     77                                break;
     78                        }
     79                }
     80
     81                if (!stream_started && *s == ':') {
     82                        if (*p_last_component_contains_wcard) {
     83                                return NT_STATUS_OBJECT_NAME_INVALID;
     84                        }
     85                        /* stream names allow more characters than file names */
     86                        stream_started = true;
     87                        start_of_name_component = false;
     88                        posix_path = true;
     89
     90                        if (s[1] == '\0') {
     91                                return NT_STATUS_OBJECT_NAME_INVALID;
     92                        }
     93                }
     94
     95                if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
    6296                        /*
    6397                         * Safe to assume is not the second part of a mb char
     
    122156                if (!(*s & 0x80)) {
    123157                        if (!posix_path) {
    124                                 if (*s <= 0x1f) {
     158                                if (*s <= 0x1f || *s == '|') {
    125159                                        return NT_STATUS_OBJECT_NAME_INVALID;
    126160                                }
     
    46004634        files_struct *fsp;
    46014635        NTSTATUS status;
    4602        
     4636
    46034637        START_PROFILE(SMBsplopen);
    46044638
     
    46154649        }
    46164650
    4617         /* Open for exclusive use, write only. */
    4618         status = print_fsp_open(conn, NULL, &fsp);
    4619 
    4620         if (!NT_STATUS_IS_OK(status)) {
     4651        status = file_new(conn, &fsp);
     4652        if(!NT_STATUS_IS_OK(status)) {
    46214653                reply_nterror(req, status);
    46224654                END_PROFILE(SMBsplopen);
     
    46244656        }
    46254657
     4658        /* Open for exclusive use, write only. */
     4659        status = print_fsp_open(conn, NULL, fsp);
     4660
     4661        if (!NT_STATUS_IS_OK(status)) {
     4662                file_free(fsp);
     4663                reply_nterror(req, status);
     4664                END_PROFILE(SMBsplopen);
     4665                return;
     4666        }
     4667
    46264668        reply_outbuf(req, 1, 0);
    46274669        SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
    4628  
     4670
    46294671        DEBUG(3,("openprint fd=%d fnum=%d\n",
    46304672                 fsp->fh->fd, fsp->fnum));
     
    50475089                }
    50485090
    5049                 /* We only have veto files/directories. Recursive delete. */
    5050 
     5091                /* We only have veto files/directories.
     5092                 * Are we allowed to delete them ? */
     5093
     5094                if(!lp_recursive_veto_delete(SNUM(conn))) {
     5095                        TALLOC_FREE(dir_hnd);
     5096                        errno = ENOTEMPTY;
     5097                        goto err;
     5098                }
     5099
     5100                /* Do a recursive delete. */
    50515101                RewindDir(dir_hnd,&dirpos);
    50525102                while ((dname = ReadDirName(dir_hnd,&dirpos))) {
     
    50745124                        }
    50755125                        if(st.st_mode & S_IFDIR) {
    5076                                 if(lp_recursive_veto_delete(SNUM(conn))) {
    5077                                         if(!recursive_rmdir(ctx, conn, fullname))
    5078                                                 break;
     5126                                if(!recursive_rmdir(ctx, conn, fullname)) {
     5127                                        break;
    50795128                                }
    50805129                                if(SMB_VFS_RMDIR(conn,fullname) != 0) {
     
    55075556        }
    55085557
     5558        if(replace_if_exists && dst_exists) {
     5559                if (is_ntfs_stream_name(newname)) {
     5560                        return NT_STATUS_INVALID_PARAMETER;
     5561                }
     5562        }
     5563
    55095564        if (dst_exists) {
    55105565                struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
     
    55575612                        fsp->fsp_name,newname));
    55585613
     5614                notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
     5615
    55595616                rename_open_files(conn, lck, newname);
    5560 
    5561                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
    55625617
    55635618                /*
  • branches/samba-3.2.x/source/smbd/server.c

    r149 r228  
    466466                const char *sock_ptr;
    467467
    468                 if (sock_addr[0] == '\0' ||
    469                                 strequal(sock_addr, "0.0.0.0") ||
    470                                 strequal(sock_addr, "::")) {
     468                if (strequal(sock_addr, "0.0.0.0") ||
     469                    strequal(sock_addr, "::")) {
    471470#if HAVE_IPV6
    472471                        sock_addr = "::,0.0.0.0";
  • branches/samba-3.2.x/source/smbd/session.c

    r133 r228  
    114114                        }
    115115
    116                         sess_pid = ((struct sessionid *)rec->value.dptr)->pid;
     116                        memcpy(&sess_pid,
     117                               ((char *)rec->value.dptr)
     118                               + offsetof(struct sessionid, pid),
     119                               sizeof(sess_pid));
    117120
    118121                        if (!process_exists(sess_pid)) {
  • branches/samba-3.2.x/source/smbd/share_access.c

    r133 r228  
    192192 */
    193193
    194 bool user_ok_token(const char *username, struct nt_user_token *token, int snum)
     194bool user_ok_token(const char *username, const struct nt_user_token *token, int snum)
    195195{
    196196        if (lp_invalid_users(snum) != NULL) {
     
    249249
    250250bool is_share_read_only_for_token(const char *username,
    251                                   struct nt_user_token *token, int snum)
    252 {
    253         bool result = lp_readonly(snum);
     251                                const struct nt_user_token *token,
     252                                connection_struct *conn)
     253{
     254        int snum = SNUM(conn);
     255        bool result = conn->read_only;
    254256
    255257        if (lp_readlist(snum) != NULL) {
  • branches/samba-3.2.x/source/smbd/trans2.c

    r205 r228  
    10921092        if (mask[0] == '.' && mask[1] == 0)
    10931093                return False;
     1094        if (dptr_has_wild(conn->dirptr)) {
     1095                return False;
     1096        }
    10941097        if (conn->case_sensitive)
    10951098                return strcmp(str,mask)==0;
    1096         if (StrCaseCmp(str,mask) != 0) {
    1097                 return False;
    1098         }
    1099         if (dptr_has_wild(conn->dirptr)) {
    1100                 return False;
    1101         }
    1102         return True;
     1099        else
     1100                return StrCaseCmp(str,mask) == 0;
    11031101}
    11041102
     
    11341132#endif
    11351133
    1136         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
     1134        DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
    11371135        return UNIX_TYPE_UNKNOWN;
    11381136}
     
    18971895        int info_level;
    18981896        char *directory = NULL;
    1899         const char *mask = NULL;
     1897        char *mask = NULL;
    19001898        char *p;
    19011899        int last_entry_off=0;
     
    19851983        }
    19861984
    1987         ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
     1985        ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
    19881986        if (!NT_STATUS_IS_OK(ntstatus)) {
    19891987                reply_nterror(req, ntstatus);
     
    20011999                /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
    20022000                if((directory[0] == '.') && (directory[1] == '\0')) {
    2003                         mask = "*";
     2001                        mask = talloc_strdup(ctx,"*");
     2002                        if (!mask) {
     2003                                reply_nterror(req, NT_STATUS_NO_MEMORY);
     2004                                return;
     2005                        }
    20042006                        mask_contains_wcard = True;
    2005                 } else {
    2006                         mask = directory;
    20072007                }
    20082008                directory = talloc_strdup(talloc_tos(), "./");
     
    20122012                }
    20132013        } else {
    2014                 mask = p+1;
    20152014                *p = 0;
    20162015        }
     
    39903989                }
    39913990
     3991                if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
     3992                    && is_ntfs_stream_name(fname)) {
     3993                        char *base;
     3994                        SMB_STRUCT_STAT bsbuf;
     3995
     3996                        status = split_ntfs_stream_name(talloc_tos(), fname,
     3997                                                        &base, NULL);
     3998                        if (!NT_STATUS_IS_OK(status)) {
     3999                                DEBUG(10, ("create_file_unixpath: "
     4000                                        "split_ntfs_stream_name failed: %s\n",
     4001                                        nt_errstr(status)));
     4002                                reply_nterror(req, status);
     4003                                return;
     4004                        }
     4005
     4006                        SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
     4007
     4008                        if (INFO_LEVEL_IS_UNIX(info_level)) {
     4009                                /* Always do lstat for UNIX calls. */
     4010                                if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
     4011                                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
     4012                                        reply_unixerror(req,ERRDOS,ERRbadpath);
     4013                                        return;
     4014                                }
     4015                        } else {
     4016                                if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
     4017                                        DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
     4018                                        reply_unixerror(req,ERRDOS,ERRbadpath);
     4019                                        return;
     4020                                }
     4021                        }
     4022
     4023                        fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
     4024                        get_file_infos(fileid, &delete_pending, NULL);
     4025                        if (delete_pending) {
     4026                                reply_nterror(req, NT_STATUS_DELETE_PENDING);
     4027                                return;
     4028                        }
     4029                }
     4030
    39924031                if (INFO_LEVEL_IS_UNIX(info_level)) {
    39934032                        /* Always do lstat for UNIX calls. */
     
    49034942
    49044943                if (fsp != NULL) {
    4905                         set_sticky_write_time_fsp(fsp, ts[1]);
     4944                        if (fsp->base_fsp) {
     4945                                set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
     4946                        } else {
     4947                                set_sticky_write_time_fsp(fsp, ts[1]);
     4948                        }
    49064949                } else {
    49074950                        set_sticky_write_time_path(conn, fname,
     
    49174960#endif
    49184961        DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
     4962
     4963        if (fsp && fsp->base_fsp) {
     4964                fname = fsp->base_fsp->fsp_name;
     4965        }
    49194966
    49204967        if(file_ntimes(conn, fname, ts)!=0) {
     
    53465393        }
    53475394
    5348         /* Create the base directory. */
    5349         base_name = talloc_strdup(ctx, fname);
    5350         if (!base_name) {
    5351                 return NT_STATUS_NO_MEMORY;
    5352         }
    5353         p = strrchr_m(base_name, '/');
    5354         if (p) {
    5355                 p[1] = '\0';
    5356         } else {
    5357                 base_name = talloc_strdup(ctx, "./");
     5395        if (fsp && fsp->base_fsp) {
     5396                if (newname[0] != ':') {
     5397                        return NT_STATUS_NOT_SUPPORTED;
     5398                }
     5399                base_name = talloc_asprintf(ctx, "%s%s",
     5400                                           fsp->base_fsp->fsp_name,
     5401                                           newname);
    53585402                if (!base_name) {
    53595403                        return NT_STATUS_NO_MEMORY;
    53605404                }
    5361         }
    5362         /* Append the new name. */
    5363         base_name = talloc_asprintf_append(base_name,
    5364                         "%s",
    5365                         newname);
    5366         if (!base_name) {
    5367                 return NT_STATUS_NO_MEMORY;
     5405        } else {
     5406                if (is_ntfs_stream_name(newname)) {
     5407                        return NT_STATUS_NOT_SUPPORTED;
     5408                }
     5409
     5410                /* Create the base directory. */
     5411                base_name = talloc_strdup(ctx, fname);
     5412                if (!base_name) {
     5413                        return NT_STATUS_NO_MEMORY;
     5414                }
     5415                p = strrchr_m(base_name, '/');
     5416                if (p) {
     5417                        p[1] = '\0';
     5418                } else {
     5419                        base_name = talloc_strdup(ctx, "./");
     5420                        if (!base_name) {
     5421                                return NT_STATUS_NO_MEMORY;
     5422                        }
     5423                }
     5424                /* Append the new name. */
     5425                base_name = talloc_asprintf_append(base_name,
     5426                                "%s",
     5427                                newname);
     5428                if (!base_name) {
     5429                        return NT_STATUS_NO_MEMORY;
     5430                }
    53685431        }
    53695432
     
    70677130                        return;
    70687131                }
    7069         } else if (IVAL(pdata,0) != 4) {
    7070                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    7071                 return;
    7072         }
     7132        }
     7133        /* If total_data == 4 Windows doesn't care what values
     7134         * are placed in that field, it just ignores them.
     7135         * The System i QNTC IBM SMB client puts bad values here,
     7136         * so ignore them. */
    70737137
    70747138        status = create_directory(conn, req, directory);
  • branches/samba-3.2.x/source/smbd/uid.c

    r133 r228  
    103103        readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
    104104                                                      vuser->nt_user_token,
    105                                                       SNUM(conn));
     105                                                      conn);
    106106
    107107        token = conn->nt_user_token ?
     
    141141        return(True);
    142142}
     143
     144/*******************************************************************
     145 Check if a username is OK in share level security.
     146********************************************************************/
     147
     148static bool check_user_ok_sharelevel_security(connection_struct *conn,
     149                                        const char *unix_name,
     150                                        int snum)
     151{
     152        NT_USER_TOKEN *token = conn->nt_user_token;
     153
     154        if (!user_ok_token(unix_name, token, snum)) {
     155                return false;
     156        }
     157
     158        conn->read_only = is_share_read_only_for_token(unix_name,
     159                                                      token,
     160                                                      conn);
     161
     162        if (!conn->read_only &&
     163            !share_access_check(token, lp_servicename(snum),
     164                                FILE_WRITE_DATA)) {
     165                /* smb.conf allows r/w, but the security descriptor denies
     166                 * write. Fall back to looking at readonly. */
     167                conn->read_only = true;
     168                DEBUG(5,("falling back to read-only access-evaluation due to "
     169                         "security descriptor\n"));
     170        }
     171
     172        if (!share_access_check(token, lp_servicename(snum),
     173                                conn->read_only ?
     174                                FILE_READ_DATA : FILE_WRITE_DATA)) {
     175                return false;
     176        }
     177
     178        conn->admin_user = token_contains_name_in_list(
     179                                unix_name, NULL, token,
     180                                lp_admin_users(SNUM(conn)));
     181
     182        return true;
     183}
     184
    143185
    144186/****************************************************************************
     
    173215         */
    174216
    175         if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
     217        if((sec == SEC_SHARE) && (current_user.conn == conn) &&
    176218           (current_user.ut.uid == conn->uid)) {
    177219                DEBUG(4,("change_to_user: Skipping user change - already "
     
    194236                         lp_servicename(snum)));
    195237                return False;
     238        } else if ((sec == SEC_SHARE) && !check_user_ok_sharelevel_security(conn,
     239                        conn->user, snum)) {
     240                DEBUG(2,("change_to_user: unix user %s "
     241                         "not permitted access to share %s.\n",
     242                         conn->user,
     243                         lp_servicename(snum)));
     244                return false;
    196245        }
    197246
  • branches/samba-3.2.x/source/smbd/vfs.c

    r149 r228  
    626626        flush_write_cache(fsp, SIZECHANGE_FLUSH);
    627627
     628#ifdef HAVE_POSIX_FALLOCATE
     629        set_filelen_write_cache(fsp, len);
     630#else
    628631        if (!sparse_buf) {
    629632                sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
     
    654657        }
    655658
     659        ret = 0;
     660#endif
     661
    656662        set_filelen_write_cache(fsp, len);
    657         return 0;
     663        return ret;
    658664}
    659665
Note: See TracChangeset for help on using the changeset viewer.