NTSTATUS file_new(struct smb_request *req, connection_struct *conn, files_struct **result) { int i; files_struct *fsp; NTSTATUS status; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to reuse a file descriptor from an earlier smb connection. This code increases the chance that the errant client will get an error rather than causing corruption */ if (first_file == 0) { first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; } /* TODO: Port the id-tree implementation from Samba4 */ i = bitmap_find(file_bmap, first_file); if (i == -1) { DEBUG(0,("ERROR! Out of file structures\n")); /* TODO: We have to unconditionally return a DOS error here, * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with * NTSTATUS negotiated */ return NT_STATUS_TOO_MANY_OPENED_FILES; } /* * Make a child of the connection_struct as an fsp can't exist * indepenedent of a connection. */ fsp = talloc_zero(conn, struct files_struct); if (!fsp) { return NT_STATUS_NO_MEMORY; } /* * This can't be a child of fsp because the file_handle can be ref'd * when doing a dos/fcb open, which will then share the file_handle * across multiple fsps. */ fsp->fh = talloc_zero(conn, struct fd_handle); if (!fsp->fh) { TALLOC_FREE(fsp); return NT_STATUS_NO_MEMORY; } fsp->fh->ref_count = 1; fsp->fh->fd = -1; fsp->conn = conn; fsp->fh->gen_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; bitmap_set(file_bmap, i); files_used++; fsp->fnum = i + FILE_HANDLE_OFFSET; SMB_ASSERT(fsp->fnum < 65536); /* * Create an smb_filename with "" for the base_name. There are very * few NULL checks, so make sure it's initialized with something. to * be safe until an audit can be done. */ status = create_synthetic_smb_fname(fsp, "", NULL, NULL, &fsp->fsp_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(fsp); TALLOC_FREE(fsp->fh); } DLIST_ADD(Files, fsp); DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", i, fsp->fnum, files_used)); if (req != NULL) { req->chain_fsp = fsp; } /* A new fsp invalidates the positive and negative fsp_fi_cache as the new fsp is pushed at the start of the list and we search from a cache hit to the *end* of the list. */ ZERO_STRUCT(fsp_fi_cache); conn->num_files_open++; *result = fsp; return NT_STATUS_OK; }
NTSTATUS file_new(struct smb_request *req, connection_struct *conn, files_struct **result) { int i; files_struct *fsp; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to reuse a file descriptor from an earlier smb connection. This code increases the chance that the errant client will get an error rather than causing corruption */ if (first_file == 0) { first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; } /* TODO: Port the id-tree implementation from Samba4 */ i = bitmap_find(file_bmap, first_file); if (i == -1) { DEBUG(0,("ERROR! Out of file structures\n")); /* TODO: We have to unconditionally return a DOS error here, * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with * NTSTATUS negotiated */ return NT_STATUS_TOO_MANY_OPENED_FILES; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp); fsp->fh = SMB_MALLOC_P(struct fd_handle); if (!fsp->fh) { SAFE_FREE(fsp); return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp->fh); fsp->fh->ref_count = 1; fsp->fh->fd = -1; fsp->conn = conn; fsp->fh->gen_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; bitmap_set(file_bmap, i); files_used++; fsp->fnum = i + FILE_HANDLE_OFFSET; SMB_ASSERT(fsp->fnum < 65536); string_set(&fsp->fsp_name,""); DLIST_ADD(Files, fsp); DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", i, fsp->fnum, files_used)); if (req != NULL) { req->chain_fsp = fsp; } /* A new fsp invalidates the positive and negative fsp_fi_cache as the new fsp is pushed at the start of the list and we search from a cache hit to the *end* of the list. */ ZERO_STRUCT(fsp_fi_cache); conn->num_files_open++; *result = fsp; return NT_STATUS_OK; }