diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/Makefile.in | 3 | ||||
-rw-r--r-- | source3/include/locking.h | 19 | ||||
-rw-r--r-- | source3/include/smb.h | 11 | ||||
-rw-r--r-- | source3/lib/file_id.c | 102 | ||||
-rw-r--r-- | source3/libsmb/smb_share_modes.c | 12 | ||||
-rw-r--r-- | source3/locking/brlock.c | 20 | ||||
-rw-r--r-- | source3/locking/locking.c | 86 | ||||
-rw-r--r-- | source3/locking/posix.c | 26 | ||||
-rw-r--r-- | source3/printing/printfsp.c | 3 | ||||
-rw-r--r-- | source3/rpc_server/srv_srvsvc_nt.c | 3 | ||||
-rw-r--r-- | source3/smbd/close.c | 17 | ||||
-rw-r--r-- | source3/smbd/filename.c | 2 | ||||
-rw-r--r-- | source3/smbd/files.c | 48 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 6 | ||||
-rw-r--r-- | source3/smbd/open.c | 69 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 94 | ||||
-rw-r--r-- | source3/smbd/oplock_irix.c | 44 | ||||
-rw-r--r-- | source3/smbd/oplock_linux.c | 24 | ||||
-rw-r--r-- | source3/smbd/reply.c | 39 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 8 | ||||
-rw-r--r-- | source3/torture/locktest.c | 7 | ||||
-rw-r--r-- | source3/torture/locktest2.c | 6 | ||||
-rw-r--r-- | source3/utils/status.c | 29 |
23 files changed, 365 insertions, 313 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index c2853f4e8c..72bc8cfcfb 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -284,7 +284,8 @@ LIB_WITH_PROTO_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \ lib/module.o lib/events.o lib/ldap_escape.o @CHARSET_STATIC@ \ lib/secdesc.o lib/util_seaccess.o lib/secace.o lib/secacl.o \ - libads/krb5_errs.o lib/system_smbd.o lib/audit.o $(LIBNDR_OBJ) + libads/krb5_errs.o lib/system_smbd.o lib/audit.o $(LIBNDR_OBJ) \ + lib/file_id.o LIB_OBJ = $(LIB_WITHOUT_PROTO_OBJ) $(LIB_WITH_PROTO_OBJ) diff --git a/source3/include/locking.h b/source3/include/locking.h index e675755839..f02d817133 100644 --- a/source3/include/locking.h +++ b/source3/include/locking.h @@ -42,33 +42,34 @@ struct lock_context { struct server_id pid; }; -/* The key used in the brlock database. */ +struct files_struct; -struct lock_key { - SMB_DEV_T device; - SMB_INO_T inode; +struct file_id { + /* we don't use SMB_DEV_T and SMB_INO_T as we want a fixed size here, + and we may be using file system specific code to fill in something + other than a dev_t for the device */ + uint64_t devid; + uint64_t inode; }; -struct files_struct; - struct byte_range_lock { struct files_struct *fsp; unsigned int num_locks; BOOL modified; BOOL read_only; - struct lock_key key; + struct file_id key; struct lock_struct *lock_data; struct db_record *record; }; #define BRLOCK_FN_CAST() \ - void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct server_id pid, \ + void (*)(struct file_id id, struct server_id pid, \ enum brl_type lock_type, \ enum brl_flavour lock_flav, \ br_off start, br_off size) #define BRLOCK_FN(fn) \ - void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct server_id pid, \ + void (*fn)(struct file_id id, struct server_id pid, \ enum brl_type lock_type, \ enum brl_flavour lock_flav, \ br_off start, br_off size) diff --git a/source3/include/smb.h b/source3/include/smb.h index 2375d47fdc..abdb3f37ba 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -422,7 +422,7 @@ struct fd_handle { * DELETE_ON_CLOSE is not stored in the share * mode database. */ - unsigned long file_id; + unsigned long gen_id; }; struct event_context; @@ -486,8 +486,7 @@ typedef struct files_struct { struct fd_handle *fh; unsigned int num_smb_operations; uint16 rap_print_jobid; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id file_id; SMB_BIG_UINT initial_allocation_size; /* Faked up initial allocation on disk. */ mode_t mode; uint16 file_pid; @@ -756,8 +755,7 @@ struct share_mode_entry { * NTCREATEX_OPTIONS_PRIVATE_DENY_FCB for * smbstatus and swat */ struct timeval time; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; unsigned long share_file_id; uint32 uid; /* uid of file opener. */ uint16 flags; /* See SHARE_MODE_XX above. */ @@ -787,8 +785,7 @@ Offset Data length. struct share_mode_lock { const char *servicepath; /* canonicalized. */ const char *filename; - SMB_DEV_T dev; - SMB_INO_T ino; + struct file_id id; int num_share_modes; struct share_mode_entry *share_modes; UNIX_USER_TOKEN *delete_token; diff --git a/source3/lib/file_id.c b/source3/lib/file_id.c new file mode 100644 index 0000000000..335c1829fb --- /dev/null +++ b/source3/lib/file_id.c @@ -0,0 +1,102 @@ +/* + Unix SMB/CIFS implementation. + + file_id structure handling + + Copyright (C) Andrew Tridgell 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + return a file_id which gives a unique ID for a file given the device and + inode numbers + */ +static struct file_id file_id_create(SMB_DEV_T dev, SMB_INO_T inode) +{ + struct file_id key; + /* the ZERO_STRUCT ensures padding doesn't break using the key as a + * blob */ + ZERO_STRUCT(key); + key.devid = dev; + key.inode = inode; + return key; +} + +/* + generate a file_id from a stat structure + */ +struct file_id file_id_sbuf(const SMB_STRUCT_STAT *sbuf) +{ + return file_id_create(sbuf->st_dev, sbuf->st_ino); +} + + +/* + return True if two file_id structures are equal + */ +BOOL file_id_equal(const struct file_id *id1, const struct file_id *id2) +{ + return id1->inode == id2->inode && id1->devid == id2->devid; +} + +/* + a static string for a file_id structure + */ +const char *file_id_static_string(const struct file_id *id) +{ + static char buf[32]; + snprintf(buf, sizeof(buf), "%llx:%llx", + (unsigned long long)id->devid, + (unsigned long long)id->inode); + return buf; +} + +/* + a 2nd static string for a file_id structure so we can print 2 at once + */ +const char *file_id_static_string2(const struct file_id *id) +{ + static char buf[32]; + snprintf(buf, sizeof(buf), "%llx:%llx", + (unsigned long long)id->devid, + (unsigned long long)id->inode); + return buf; +} + +/* + push a 16 byte version of a file id into a buffer + */ +void push_file_id_16(char *buf, const struct file_id *id) +{ + SIVAL(buf, 0, id->devid&0xFFFFFFFF); + SIVAL(buf, 4, id->devid>>32); + SIVAL(buf, 8, id->inode&0xFFFFFFFF); + SIVAL(buf, 12, id->inode>>32); +} + +/* + pul a 16 byte version of a file id from a buffer + */ +void pull_file_id_16(char *buf, struct file_id *id) +{ + ZERO_STRUCTP(id); + id->devid = IVAL(buf, 0); + id->devid |= ((uint64_t)IVAL(buf,4))<<32; + id->inode = IVAL(buf, 8); + id->inode |= ((uint64_t)IVAL(buf,12))<<32; +} diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index da8d9e1fdc..89395fe373 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -137,8 +137,8 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, e_entry->open_time.tv_usec == entry->time.tv_usec && e_entry->share_access == (uint32_t)entry->share_access && e_entry->access_mask == (uint32_t)entry->access_mask && - e_entry->dev == (uint64_t)entry->dev && - e_entry->ino == (uint64_t)entry->inode); + e_entry->dev == entry->id.devid && + e_entry->ino == entry->id.inode); } /* @@ -156,8 +156,8 @@ static void create_share_mode_entry(struct share_mode_entry *out, out->time.tv_usec = in->open_time.tv_usec; out->share_access = in->share_access; out->access_mask = in->access_mask; - out->dev = (SMB_DEV_T)in->dev; - out->inode = (SMB_INO_T)in->ino; + out->id.devid = in->dev; + out->id.inode = in->ino; out->uid = (uint32)geteuid(); out->flags = 0; } @@ -224,8 +224,8 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, } /* Copy into the external list. */ - sme->dev = (uint64_t)share->dev; - sme->ino = (uint64_t)share->inode; + sme->dev = share->id.devid; + sme->ino = share->id.inode; sme->share_access = (uint32_t)share->share_access; sme->access_mask = (uint32_t)share->access_mask; sme->open_time.tv_sec = share->time.tv_sec; diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 8e2f7ce41a..a37afbddd5 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1455,7 +1455,7 @@ static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct static int traverse_fn(struct db_record *rec, void *state) { struct lock_struct *locks; - struct lock_key *key; + struct file_id *key; unsigned int i; unsigned int num_locks = 0; unsigned int orig_num_locks = 0; @@ -1471,7 +1471,7 @@ static int traverse_fn(struct db_record *rec, void *state) return -1; /* Terminate traversal. */ } - key = (struct lock_key *)rec->key.dptr; + key = (struct file_id *)rec->key.dptr; orig_num_locks = num_locks = rec->value.dsize/sizeof(*locks); /* Ensure the lock db is clean of entries from invalid processes. */ @@ -1493,8 +1493,7 @@ static int traverse_fn(struct db_record *rec, void *state) } for ( i=0; i<num_locks; i++) { - traverse_callback(key->device, - key->inode, + traverse_callback(*key, locks[i].context.pid, locks[i].lock_type, locks[i].lock_flav, @@ -1529,7 +1528,7 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) TDB_DATA key; key.dptr = (uint8 *)&br_lck->key; - key.dsize = sizeof(struct lock_key); + key.dsize = sizeof(struct file_id); if (br_lck->read_only) { SMB_ASSERT(!br_lck->modified); @@ -1588,12 +1587,11 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, br_lck->fsp = fsp; br_lck->num_locks = 0; br_lck->modified = False; - memset(&br_lck->key, '\0', sizeof(struct lock_key)); - br_lck->key.device = fsp->dev; - br_lck->key.inode = fsp->inode; + memset(&br_lck->key, '\0', sizeof(struct file_id)); + br_lck->key = fsp->file_id; key.dptr = (uint8 *)&br_lck->key; - key.dsize = sizeof(struct lock_key); + key.dsize = sizeof(struct file_id); if (!fsp->lockdb_clean) { /* We must be read/write to clean @@ -1649,9 +1647,9 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, if (DEBUGLEVEL >= 10) { unsigned int i; struct lock_struct *locks = br_lck->lock_data; - DEBUG(10,("brl_get_locks_internal: %u current locks on dev=%.0f, inode=%.0f\n", + DEBUG(10,("brl_get_locks_internal: %u current locks on file_id %s\n", br_lck->num_locks, - (double)fsp->dev, (double)fsp->inode )); + file_id_static_string(&fsp->file_id))); for( i = 0; i < br_lck->num_locks; i++) { print_lock_struct(i, &locks[i]); } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index cc6957b4e3..c02304addf 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -416,24 +416,11 @@ BOOL locking_end(void) Form a static locking key for a dev/inode pair. ******************************************************************/ -/* key and data records in the tdb locking database */ -struct locking_key { - SMB_DEV_T dev; - SMB_INO_T ino; -}; - -/******************************************************************* - Form a static locking key for a dev/inode pair. -******************************************************************/ - -static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) +static TDB_DATA locking_key(struct file_id id) { - static struct locking_key key; + static struct file_id key; TDB_DATA kbuf; - - memset(&key, '\0', sizeof(key)); - key.dev = dev; - key.ino = inode; + key = id; kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); return kbuf; @@ -449,15 +436,15 @@ char *share_mode_str(int num, struct share_mode_entry *e) slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " - "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " - "uid = %u, flags = %u, dev = 0x%x, inode = %.0f", + "access_mask = 0x%x, mid = 0x%x, type= 0x%x, gen_id = %lu, " + "uid = %u, flags = %u, file_id %s", num, e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "", procid_str_static(&e->pid), e->share_access, e->private_options, e->access_mask, e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->uid, (unsigned int)e->flags, - (unsigned int)e->dev, (double)e->inode ); + file_id_static_string(&e->id)); return share_str; } @@ -734,7 +721,7 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) } static BOOL fill_share_mode_lock(struct share_mode_lock *lck, - SMB_DEV_T dev, SMB_INO_T ino, + struct file_id id, const char *servicepath, const char *fname, TDB_DATA share_mode_data) @@ -744,8 +731,7 @@ static BOOL fill_share_mode_lock(struct share_mode_lock *lck, lck->servicepath = NULL; lck->filename = NULL; - lck->dev = dev; - lck->ino = ino; + lck->id = id; lck->num_share_modes = 0; lck->share_modes = NULL; lck->delete_token = NULL; @@ -776,12 +762,15 @@ static BOOL fill_share_mode_lock(struct share_mode_lock *lck, } struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, - SMB_DEV_T dev, SMB_INO_T ino, + struct file_id id, const char *servicepath, const char *fname) { struct share_mode_lock *lck; - TDB_DATA key = locking_key(dev, ino); + TDB_DATA key; + + key.dptr = (unsigned char *)&id; + key.dsize = sizeof(id); if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { DEBUG(0, ("talloc failed\n")); @@ -794,7 +783,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return NULL; } - if (!fill_share_mode_lock(lck, dev, ino, servicepath, fname, + if (!fill_share_mode_lock(lck, id, servicepath, fname, lck->record->value)) { DEBUG(3, ("fill_share_mode_lock failed\n")); TALLOC_FREE(lck); @@ -807,12 +796,12 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, } struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, - SMB_DEV_T dev, SMB_INO_T ino, + struct file_id id, const char *servicepath, const char *fname) { struct share_mode_lock *lck; - TDB_DATA key = locking_key(dev, ino); + TDB_DATA key = locking_key(id); TDB_DATA data; if (!(lck = TALLOC_P(mem_ctx, struct share_mode_lock))) { @@ -826,7 +815,7 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, return NULL; } - if (!fill_share_mode_lock(lck, dev, ino, servicepath, fname, data)) { + if (!fill_share_mode_lock(lck, id, servicepath, fname, data)) { DEBUG(3, ("fill_share_mode_lock failed\n")); TALLOC_FREE(lck); return NULL; @@ -889,8 +878,7 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, return False; } - SDEV_T_VAL(frm,0,lck->dev); - SINO_T_VAL(frm,8,lck->ino); + push_file_id_16(frm, &lck->id); DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len )); @@ -909,10 +897,10 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, } DEBUG(10,("rename_share_filename: sending rename message to pid %s " - "dev %x, inode %.0f sharepath %s newname %s\n", - procid_str_static(&se->pid), - (unsigned int)lck->dev, (double)lck->ino, - lck->servicepath, lck->filename )); + "file_id %s sharepath %s newname %s\n", + procid_str_static(&se->pid), + file_id_static_string(&lck->id), + lck->servicepath, lck->filename )); messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, (uint8 *)frm, msg_len); @@ -921,12 +909,12 @@ BOOL rename_share_filename(struct messaging_context *msg_ctx, return True; } -BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) +BOOL get_delete_on_close_flag(struct file_id id) { BOOL result; struct share_mode_lock *lck; - if (!(lck = fetch_share_mode_unlocked(NULL, dev, inode, NULL, NULL))) { + if (!(lck = fetch_share_mode_unlocked(NULL, id, NULL, NULL))) { return False; } result = lck->delete_on_close; @@ -973,16 +961,15 @@ static void fill_share_mode_entry(struct share_mode_entry *e, e->op_type = op_type; e->time.tv_sec = fsp->open_time.tv_sec; e->time.tv_usec = fsp->open_time.tv_usec; - e->dev = fsp->dev; - e->inode = fsp->inode; - e->share_file_id = fsp->fh->file_id; + e->id = fsp->file_id; + e->share_file_id = fsp->fh->gen_id; e->uid = (uint32)uid; e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0; } static void fill_deferred_open_entry(struct share_mode_entry *e, const struct timeval request_time, - SMB_DEV_T dev, SMB_INO_T ino, uint16 mid) + struct file_id id, uint16 mid) { ZERO_STRUCTP(e); e->pid = procid_self(); @@ -990,8 +977,7 @@ static void fill_deferred_open_entry(struct share_mode_entry *e, e->op_type = DEFERRED_OPEN_ENTRY; e->time.tv_sec = request_time.tv_sec; e->time.tv_usec = request_time.tv_usec; - e->dev = dev; - e->inode = ino; + e->id = id; e->uid = (uint32)-1; e->flags = 0; } @@ -1030,10 +1016,10 @@ void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, void add_deferred_open(struct share_mode_lock *lck, uint16 mid, struct timeval request_time, - SMB_DEV_T dev, SMB_INO_T ino) + struct file_id id) { struct share_mode_entry entry; - fill_deferred_open_entry(&entry, request_time, dev, ino, mid); + fill_deferred_open_entry(&entry, request_time, id, mid); add_share_mode_entry(lck, &entry); } @@ -1052,8 +1038,7 @@ static BOOL share_modes_identical(struct share_mode_entry *e1, fsp->share_access field. */ return (procid_equal(&e1->pid, &e2->pid) && - e1->dev == e2->dev && - e1->inode == e2->inode && + file_id_equal(&e1->id, &e2->id) && e1->share_file_id == e2->share_file_id ); } @@ -1062,8 +1047,7 @@ static BOOL deferred_open_identical(struct share_mode_entry *e1, { return (procid_equal(&e1->pid, &e2->pid) && (e1->op_mid == e2->op_mid) && - (e1->dev == e2->dev) && - (e1->inode == e2->inode)); + file_id_equal(&e1->id, &e2->id)); } static struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lck, @@ -1114,7 +1098,7 @@ void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid) struct share_mode_entry entry, *e; fill_deferred_open_entry(&entry, timeval_zero(), - lck->dev, lck->ino, mid); + lck->id, mid); e = find_share_mode_entry(lck, &entry); if (e == NULL) { @@ -1325,7 +1309,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE return True; } - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { return False; } @@ -1383,7 +1367,7 @@ static int traverse_fn(struct db_record *rec, void *_state) int i; /* Ensure this is a locking_key record. */ - if (rec->key.dsize != sizeof(struct locking_key)) + if (rec->key.dsize != sizeof(struct file_id)) return 0; data = (struct locking_data *)rec->value.dptr; diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 338ee0416b..73fc2c7bd0 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -318,28 +318,19 @@ BOOL is_posix_locked(files_struct *fsp, /* The key used in the in-memory POSIX databases. */ struct lock_ref_count_key { - SMB_DEV_T device; - SMB_INO_T inode; + struct file_id id; char r; }; -struct fd_key { - SMB_DEV_T device; - SMB_INO_T inode; -}; - /******************************************************************* Form a static locking key for a dev/inode pair for the fd array. ******************************************************************/ -static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) +static TDB_DATA fd_array_key(struct file_id id) { - static struct fd_key key; + static struct file_id key; TDB_DATA kbuf; - - memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; + key = id; kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); return kbuf; @@ -349,14 +340,13 @@ static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode) Form a static locking key for a dev/inode pair for the lock ref count ******************************************************************/ -static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) +static TDB_DATA locking_ref_count_key(struct file_id id) { static struct lock_ref_count_key key; TDB_DATA kbuf; memset(&key, '\0', sizeof(key)); - key.device = dev; - key.inode = inode; + key.id = id; key.r = 'r'; kbuf.dptr = (uint8 *)&key; kbuf.dsize = sizeof(key); @@ -369,7 +359,7 @@ static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode) static TDB_DATA fd_array_key_fsp(files_struct *fsp) { - return fd_array_key(fsp->dev, fsp->inode); + return fd_array_key(fsp->file_id); } /******************************************************************* @@ -378,7 +368,7 @@ static TDB_DATA fd_array_key_fsp(files_struct *fsp) static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp) { - return locking_ref_count_key(fsp->dev, fsp->inode); + return locking_ref_count_key(fsp->file_id); } /******************************************************************* diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c index 5278c60f99..062a72080d 100644 --- a/source3/printing/printfsp.c +++ b/source3/printing/printfsp.c @@ -87,8 +87,7 @@ NTSTATUS print_fsp_open(connection_struct *conn, const char *fname, fsp->wcp = NULL; SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf); fsp->mode = sbuf.st_mode; - fsp->inode = sbuf.st_ino; - fsp->dev = sbuf.st_dev; + fsp->file_id = file_id_sbuf(&sbuf); conn->num_files_open++; diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 06c733fe49..7132f92c93 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -152,8 +152,7 @@ static void enum_file_fn( const struct share_mode_entry *e, /* need to count the number of locks on a file */ ZERO_STRUCT( fsp ); - fsp.dev = e->dev; - fsp.inode = e->inode; + fsp.file_id = e->id; if ( (brl = brl_get_locks_readonly(NULL,&fsp)) != NULL ) { num_locks = brl->num_locks; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 38b4988415..c4aa2e2e28 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -155,6 +155,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; NTSTATUS status = NT_STATUS_OK; + struct file_id id; /* * Lock the share entries, and determine if we should delete @@ -162,7 +163,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, * This prevents race conditions with the file being created. JRA. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_remove_share_mode: Could not get share mode " @@ -258,15 +259,17 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, goto done; } - if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { + id = file_id_sbuf(&sbuf); + + if (!file_id_equal(&fsp->file_id, &id)) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and dev and/or inode does not match\n", fsp->fsp_name )); - DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, " - "inode = %.0f stat dev = %x, inode = %.0f\n", + DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, " + "stat file_id %s\n", fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); + file_id_static_string(&fsp->file_id), + file_id_static_string2(&id))); /* * Don't save the errno here, we ignore this error */ @@ -405,7 +408,7 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty * reference to a directory also. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index eb86a0efd1..c26eba2ded 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -463,7 +463,7 @@ NTSTATUS unix_convert(connection_struct *conn, } /* end else */ #ifdef DEVELOPER - if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) { + if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) { return NT_STATUS_DELETE_PENDING; } #endif diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 062bebd58e..5ee0696ef9 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -38,8 +38,7 @@ static int files_used; /* A singleton cache to speed up searching by dev/inode. */ static struct fsp_singleton_cache { files_struct *fsp; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; } fsp_fi_cache; /**************************************************************************** @@ -104,7 +103,7 @@ NTSTATUS file_new(connection_struct *conn, files_struct **result) fsp->fh->fd = -1; fsp->conn = conn; - fsp->fh->file_id = get_gen_count(); + fsp->fh->gen_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; @@ -233,9 +232,9 @@ void file_dump_open_table(void) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { - DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n", - count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->file_id, - (unsigned int)fsp->dev, (double)fsp->inode )); + DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n", + count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id, + file_id_static_string(&fsp->file_id))); } } @@ -264,16 +263,15 @@ files_struct *file_find_fd(int fd) Find a fsp given a device, inode and file_id. ****************************************************************************/ -files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id) +files_struct *file_find_dif(struct file_id id, unsigned long gen_id) { int count=0; files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */ - if (fsp->dev == dev && - fsp->inode == inode && - fsp->fh->file_id == file_id ) { + if (file_id_equal(&fsp->file_id, &id) && + fsp->fh->gen_id == gen_id ) { if (count > 10) { DLIST_PROMOTE(Files, fsp); } @@ -281,10 +279,11 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i if ((fsp->fh->fd == -1) && (fsp->oplock_type != NO_OPLOCK) && (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { - DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \ -oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, (unsigned int)fsp->fh->file_id, - (unsigned int)fsp->oplock_type )); + DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \ +oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, + file_id_static_string(&fsp->file_id), + (unsigned int)fsp->fh->gen_id, + (unsigned int)fsp->oplock_type )); smb_panic("file_find_dif\n"); } return fsp; @@ -316,22 +315,20 @@ files_struct *file_find_fsp(files_struct *orig_fsp) calls. ****************************************************************************/ -files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) +files_struct *file_find_di_first(struct file_id id) { files_struct *fsp; - if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { + if (file_id_equal(&fsp_fi_cache.id, &id)) { /* Positive or negative cache hit. */ return fsp_fi_cache.fsp; } - fsp_fi_cache.dev = dev; - fsp_fi_cache.inode = inode; + fsp_fi_cache.id = id; for (fsp=Files;fsp;fsp=fsp->next) { if ( fsp->fh->fd != -1 && - fsp->dev == dev && - fsp->inode == inode ) { + file_id_equal(&fsp->file_id, &id)) { /* Setup positive cache. */ fsp_fi_cache.fsp = fsp; return fsp; @@ -353,9 +350,9 @@ files_struct *file_find_di_next(files_struct *start_fsp) for (fsp = start_fsp->next;fsp;fsp=fsp->next) { if ( fsp->fh->fd != -1 && - fsp->dev == start_fsp->dev && - fsp->inode == start_fsp->inode ) + file_id_equal(&fsp->file_id, &start_fsp->file_id)) { return fsp; + } } return NULL; @@ -392,9 +389,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod) } for (fsp = Files;fsp;fsp=fsp->next) { - if ( fsp->fh->fd != -1 && - fsp->dev == tfsp->dev && - fsp->inode == tfsp->inode ) { + if ( fsp->fh->fd != -1 && file_id_equal(&fsp->file_id, &tfsp->file_id)) { fsp->pending_modtime = mod; fsp->pending_modtime_owner = False; } @@ -542,8 +537,7 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->fh = fsp->fh; dup_fsp->fh->ref_count++; - dup_fsp->dev = fsp->dev; - dup_fsp->inode = fsp->inode; + dup_fsp->file_id = fsp->file_id; dup_fsp->initial_allocation_size = fsp->initial_allocation_size; dup_fsp->mode = fsp->mode; dup_fsp->file_pid = fsp->file_pid; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index eb4a6cd969..e8919f9faf 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -2300,11 +2300,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou if (pdata == NULL) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - SINO_T_VAL(pdata,0,fsp->inode); - SDEV_T_VAL(pdata,8,fsp->dev); + push_file_id_16(pdata, &fsp->file_id); memcpy(pdata+16,create_volume_objectid(conn,objid),16); - SINO_T_VAL(pdata,32,fsp->inode); - SDEV_T_VAL(pdata,40,fsp->dev); + push_file_id_16(pdata+32, &fsp->file_id); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); return -1; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 987da7a94d..30576f1e08 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,8 +30,7 @@ extern BOOL global_client_failed_oplock_break; struct deferred_open_record { BOOL delayed_for_oplocks; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; }; /**************************************************************************** @@ -359,8 +358,7 @@ static NTSTATUS open_file(files_struct *fsp, } fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = True; @@ -513,7 +511,7 @@ static void validate_my_share_entries(int num, return; } - fsp = file_find_dif(share_entry->dev, share_entry->inode, + fsp = file_find_dif(share_entry->id, share_entry->share_file_id); if (!fsp) { DEBUG(0,("validate_my_share_entries: PANIC : %s\n", @@ -803,7 +801,7 @@ static void defer_open(struct share_mode_lock *lck, (char *)state, sizeof(*state))) { exit_server("push_deferred_smb_message failed"); } - add_deferred_open(lck, mid, request_time, state->dev, state->inode); + add_deferred_open(lck, mid, request_time, state->id); /* * Push the MID of this packet on the signing queue. @@ -871,8 +869,8 @@ static BOOL open_match_attributes(connection_struct *conn, ****************************************************************************/ static files_struct *fcb_or_dos_open(connection_struct *conn, - const char *fname, SMB_DEV_T dev, - SMB_INO_T inode, + const char *fname, + struct file_id id, uint32 access_mask, uint32 share_access, uint32 create_options) @@ -883,7 +881,7 @@ static files_struct *fcb_or_dos_open(connection_struct *conn, DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " "file %s.\n", fname )); - for(fsp = file_find_di_first(dev, inode); fsp; + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " @@ -1093,8 +1091,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, struct timeval requ a 1 second delay for share mode conflicts. */ state.delayed_for_oplocks = True; - state.dev = lck->dev; - state.inode = lck->ino; + state.id = lck->id; if (!request_timed_out(request_time, timeout)) { defer_open(lck, request_time, timeout, &state); @@ -1124,8 +1121,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, BOOL def_acl = False; BOOL posix_open = False; BOOL new_file_created = False; - SMB_DEV_T dev = 0; - SMB_INO_T inode = 0; + struct file_id id; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; @@ -1142,6 +1138,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, char *parent_dir; const char *newname; + ZERO_STRUCT(id); + if (conn->printer) { /* * Printers are handled completely differently. @@ -1192,7 +1190,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, request_time = pml->request_time; /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, state->id, NULL, NULL); if (lck == NULL) { DEBUG(0, ("could not get share mode lock\n")); } else { @@ -1404,8 +1402,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, return status; } - fsp->dev = psbuf->st_dev; - fsp->inode = psbuf->st_ino; + fsp->file_id = file_id_sbuf(psbuf); fsp->share_access = share_access; fsp->fh->private_options = create_options; fsp->access_mask = open_access_mask; /* We change this to the @@ -1421,10 +1418,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { - dev = psbuf->st_dev; - inode = psbuf->st_ino; + id = file_id_sbuf(psbuf); - lck = get_share_mode_lock(NULL, dev, inode, + lck = get_share_mode_lock(NULL, id, conn->connectpath, fname); @@ -1483,8 +1479,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Use the client requested access mask here, * not the one we open with. */ - fsp_dup = fcb_or_dos_open(conn, fname, dev, - inode, access_mask, + fsp_dup = fcb_or_dos_open(conn, fname, id, + access_mask, share_access, create_options); @@ -1556,8 +1552,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, a 1 second delay for share mode conflicts. */ state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + state.id = id; if (!request_timed_out(request_time, timeout)) { @@ -1635,10 +1630,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, * Nadav Danieli <nadavd@exanet.com>. JRA. */ - dev = fsp->dev; - inode = fsp->inode; + id = fsp->file_id; - lck = get_share_mode_lock(NULL, dev, inode, + lck = get_share_mode_lock(NULL, id, conn->connectpath, fname); @@ -1684,8 +1678,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, file_free(fsp); state.delayed_for_oplocks = False; - state.dev = dev; - state.inode = inode; + state.id = id; /* Do it all over again immediately. In the second * round we will find that the file existed and handle @@ -2127,8 +2120,7 @@ NTSTATUS open_directory(connection_struct *conn, */ fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; @@ -2149,7 +2141,7 @@ NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, + lck = get_share_mode_lock(NULL, fsp->file_id, conn->connectpath, fname); @@ -2255,8 +2247,7 @@ NTSTATUS open_file_stat(connection_struct *conn, const char *fname, */ fsp->mode = psbuf->st_mode; - fsp->inode = psbuf->st_ino; - fsp->dev = psbuf->st_dev; + fsp->file_id = file_id_sbuf(psbuf); fsp->vuid = current_user.vuid; fsp->file_pid = global_smbpid; fsp->can_lock = False; @@ -2289,8 +2280,7 @@ void msg_file_was_renamed(struct messaging_context *msg, { files_struct *fsp; char *frm = (char *)data->data; - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; const char *sharepath; const char *newname; size_t sp_len; @@ -2303,17 +2293,16 @@ void msg_file_was_renamed(struct messaging_context *msg, } /* Unpack the message. */ - dev = DEV_T_VAL(frm,0); - inode = INO_T_VAL(frm,8); + pull_file_id_16(frm, &id); sharepath = &frm[16]; newname = sharepath + strlen(sharepath) + 1; sp_len = strlen(sharepath); DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " - "dev %x, inode %.0f\n", - sharepath, newname, (unsigned int)dev, (double)inode )); + "file_id %s\n", + sharepath, newname, file_id_static_string(&id))); - for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", fsp->fnum, fsp->fsp_name, newname )); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 63f88b7824..9f3679390b 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -87,9 +87,8 @@ void process_kernel_oplocks(struct messaging_context *msg_ctx, fd_set *pfds) } /* Put the kernel break info into the message. */ - SDEV_T_VAL(msg,0,fsp->dev); - SINO_T_VAL(msg,8,fsp->inode); - SIVAL(msg,16,fsp->fh->file_id); + push_file_id_16(msg, &fsp->file_id); + SIVAL(msg,16,fsp->fh->gen_id); /* Don't need to be root here as we're only ever sending to ourselves. */ @@ -119,10 +118,10 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type) exclusive_oplocks_open++; } - DEBUG(5,("set_file_oplock: granted oplock on file %s, 0x%x/%.0f/%lu, " + DEBUG(5,("set_file_oplock: granted oplock on file %s, %s/%lu, " "tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id, (int)fsp->open_time.tv_sec, + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); return True; @@ -178,13 +177,11 @@ static void downgrade_file_oplock(files_struct *fsp) BOOL remove_oplock(files_struct *fsp) { - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; BOOL ret; struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -193,9 +190,8 @@ BOOL remove_oplock(files_struct *fsp) ret = remove_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("remove_oplock: failed to remove share oplock for " - "file %s fnum %d, 0x%x/%.0f\n", - fsp->fsp_name, fsp->fnum, (unsigned int)dev, - (double)inode)); + "file %s fnum %d, %s\n", + fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id))); } release_file_oplock(fsp); TALLOC_FREE(lck); @@ -207,12 +203,10 @@ BOOL remove_oplock(files_struct *fsp) */ BOOL downgrade_oplock(files_struct *fsp) { - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; BOOL ret; struct share_mode_lock *lck; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " "file %s\n", fsp->fsp_name )); @@ -221,9 +215,8 @@ BOOL downgrade_oplock(files_struct *fsp) ret = downgrade_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " - "for file %s fnum %d, dev = %x, inode = %.0f\n", - fsp->fsp_name, fsp->fnum, (unsigned int)dev, - (double)inode)); + "for file %s fnum %d, file_id %s\n", + fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id))); } downgrade_file_oplock(fsp); @@ -289,13 +282,13 @@ static void wait_before_sending_break(void) Ensure that we have a valid oplock. ****************************************************************************/ -static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id) +static files_struct *initial_break_processing(struct file_id id, unsigned long file_id) { files_struct *fsp = NULL; if( DEBUGLVL( 3 ) ) { - dbgtext( "initial_break_processing: called for 0x%x/%.0f/%u\n", - (unsigned int)dev, (double)inode, (int)file_id); + dbgtext( "initial_break_processing: called for %s/%u\n", + file_id_static_string(&id), (int)file_id); dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n", exclusive_oplocks_open, level_II_oplocks_open ); } @@ -306,14 +299,13 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un * we have an oplock on it. */ - fsp = file_find_dif(dev, inode, file_id); + fsp = file_find_dif(id, file_id); if(fsp == NULL) { /* The file could have been closed in the meantime - return success. */ if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: cannot find open file with " ); - dbgtext( "dev = 0x%x, inode = %.0f file_id = %lu", (unsigned int)dev, - (double)inode, file_id); + dbgtext( "file_id %s gen_id = %lu", file_id_static_string(&id), file_id); dbgtext( "allowing break to succeed.\n" ); } return NULL; @@ -332,8 +324,8 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un if(fsp->oplock_type == NO_OPLOCK) { if( DEBUGLVL( 3 ) ) { dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n", - (unsigned int)dev, (double)inode, fsp->fh->file_id ); + dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n", + file_id_static_string(&id), fsp->fh->gen_id ); dbgtext( "Allowing break to succeed regardless.\n" ); } return NULL; @@ -415,12 +407,10 @@ static void process_oplock_async_level2_break_message(struct messaging_context * /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id)); + DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id)); - fsp = initial_break_processing(msg.dev, msg.inode, - msg.share_file_id); + fsp = initial_break_processing(msg.id, msg.share_file_id); if (fsp == NULL) { /* We hit a race here. Break messages are sent, and before we @@ -505,12 +495,10 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id)); + DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id)); - fsp = initial_break_processing(msg.dev, msg.inode, - msg.share_file_id); + fsp = initial_break_processing(msg.id, msg.share_file_id); if (fsp == NULL) { /* a We hit race here. Break messages are sent, and before we @@ -537,8 +525,8 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) && !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n", - (unsigned int)fsp->dev, (double)fsp->inode, + DEBUG(3, ("Already downgraded oplock on %s: %s\n", + file_id_static_string(&fsp->file_id), fsp->fsp_name)); /* We just send the same message back. */ messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE, @@ -599,8 +587,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, struct server_id src, DATA_BLOB *data) { - SMB_DEV_T dev; - SMB_INO_T inode; + struct file_id id; unsigned long file_id; files_struct *fsp; char *break_msg; @@ -617,15 +604,14 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx, } /* Pull the data from the message. */ - dev = DEV_T_VAL(data->data, 0); - inode = INO_T_VAL(data->data, 8); + pull_file_id_16((char *)data->data, &id); file_id = (unsigned long)IVAL(data->data, 16); - DEBUG(10, ("Got kernel oplock break message from pid %d: 0x%x/%.0f/%u\n", - (int)procid_to_pid(&src), (unsigned int)dev, (double)inode, + DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n", + (int)procid_to_pid(&src), file_id_static_string(&id), (unsigned int)file_id)); - fsp = initial_break_processing(dev, inode, file_id); + fsp = initial_break_processing(id, file_id); if (fsp == NULL) { DEBUG(3, ("Got a kernel oplock break message for a file " @@ -711,9 +697,8 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id, + DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id, (unsigned int)msg.op_mid)); /* Here's the hack from open.c, store the mid in the 'port' field */ @@ -741,9 +726,8 @@ static void process_open_retry_message(struct messaging_context *msg_ctx, /* De-linearize incoming message. */ message_to_share_mode_entry(&msg, (char *)data->data); - DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n", - (int)procid_to_pid(&src), (unsigned int)msg.dev, - (double)msg.inode, msg.share_file_id, + DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n", + (int)procid_to_pid(&src), file_id_static_string(&msg.id), (unsigned int)msg.op_mid)); schedule_deferred_open_smb_message(msg.op_mid); @@ -771,7 +755,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " "share mode entry for file %s.\n", fsp->fsp_name )); @@ -845,8 +829,7 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e) SIVAL(msg,16,e->private_options); SIVAL(msg,20,(uint32)e->time.tv_sec); SIVAL(msg,24,(uint32)e->time.tv_usec); - SDEV_T_VAL(msg,28,e->dev); - SINO_T_VAL(msg,36,e->inode); + push_file_id_16(msg+28, &e->id); SIVAL(msg,44,e->share_file_id); SIVAL(msg,48,e->uid); SSVAL(msg,52,e->flags); @@ -866,8 +849,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) e->private_options = IVAL(msg,16); e->time.tv_sec = (time_t)IVAL(msg,20); e->time.tv_usec = (int)IVAL(msg,24); - e->dev = DEV_T_VAL(msg,28); - e->inode = INO_T_VAL(msg,36); + pull_file_id_16(msg+28, &e->id); e->share_file_id = (unsigned long)IVAL(msg,44); e->uid = (uint32)IVAL(msg,48); e->flags = (uint16)SVAL(msg,52); diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index c1159cd73b..1ac0cb4674 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -149,9 +149,9 @@ static files_struct *irix_oplock_receive_message(fd_set *fds) } DEBUG(5,("irix_oplock_receive_message: kernel oplock break request " - "received for dev = %x, inode = %.0f\n, file_id = %ul", - (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id )); + "received for file_id %s gen_id = %ul", + file_id_static_string(&fsp->file_id), + fsp->fh->gen_id )); return fsp; } @@ -165,27 +165,27 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type) if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) { if(errno != EAGAIN) { DEBUG(0,("irix_set_kernel_oplock: Unable to get " - "kernel oplock on file %s, dev = %x, inode " - "= %.0f, file_id = %ul. Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, + "kernel oplock on file %s, file_id %s " + "gen_id = %ul. Error was %s\n", + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, strerror(errno) )); } else { DEBUG(5,("irix_set_kernel_oplock: Refused oplock on " - "file %s, fd = %d, dev = %x, inode = %.0f, " - "file_id = %ul. Another process had the file " + "file %s, fd = %d, file_id = 5s, " + "gen_id = %ul. Another process had the file " "open.\n", fsp->fsp_name, fsp->fh->fd, - (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id )); + file_id_static_string(&fsp->file_id), + fsp->fh->gen_id )); } return False; } - DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev " - "= %x, inode = %.0f, file_id = %ul\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id)); + DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s " + "gen_id = %ul\n", + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id)); return True; } @@ -202,10 +202,10 @@ static void irix_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); - dbgtext("irix_release_kernel_oplock: file %s, dev = %x, " - "inode = %.0f file_id = %ul, has kernel oplock state " - "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, state ); + dbgtext("irix_release_kernel_oplock: file %s, file_id = %s" + "gen_id = %ul, has kernel oplock state " + "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, state ); } /* @@ -215,10 +215,10 @@ static void irix_release_kernel_oplock(files_struct *fsp) if( DEBUGLVL( 0 )) { dbgtext("irix_release_kernel_oplock: Error when " "removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. " + dbgtext("%s, file_id = %s gen_id = %ul. " "Error was %s\n", - fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, strerror(errno) ); } } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 14db98cde6..e12a9d66ca 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -167,17 +167,17 @@ static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type) { if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " - "fd = %d, dev = %x, inode = %.0f. (%s)\n", + "fd = %d, file_id = %s. (%s)\n", fsp->fsp_name, fsp->fh->fd, - (unsigned int)fsp->dev, (double)fsp->inode, + file_id_static_string(&fsp->file_id), strerror(errno))); return False; } DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, " - "dev = %x, inode = %.0f, file_id = %lu\n", - fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id)); + "file_id = %s gen_id = %lu\n", + fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id)); return True; } @@ -194,10 +194,10 @@ static void linux_release_kernel_oplock(files_struct *fsp) * oplock state of this file. */ int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); - dbgtext("linux_release_kernel_oplock: file %s, dev = %x, " - "inode = %.0f file_id = %lu has kernel oplock state " - "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, - (double)fsp->inode, fsp->fh->file_id, state ); + dbgtext("linux_release_kernel_oplock: file %s, file_id = %s " + "gen_id = %lu has kernel oplock state " + "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, state ); } /* @@ -207,10 +207,10 @@ static void linux_release_kernel_oplock(files_struct *fsp) if (DEBUGLVL(0)) { dbgtext("linux_release_kernel_oplock: Error when " "removing kernel oplock on file " ); - dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. " + dbgtext("%s, file_id = %s, gen_id = %lu. " "Error was %s\n", fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - fsp->fh->file_id, strerror(errno) ); + file_id_static_string(&fsp->file_id), + fsp->fh->gen_id, strerror(errno) ); } } } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 40311758c9..6d4c08b663 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4171,12 +4171,12 @@ static BOOL resolve_wildcards(const char *name1, char *name2) ****************************************************************************/ static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, - SMB_DEV_T dev, SMB_INO_T inode, const char *newname) + struct file_id id, const char *newname) { files_struct *fsp; BOOL did_rename = False; - for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { /* fsp_name is a relative path under the fsp. To change this for other sharepaths we need to manipulate relative paths. */ /* TODO - create the absolute path and manipulate the newname @@ -4184,16 +4184,16 @@ static void rename_open_files(connection_struct *conn, struct share_mode_lock *l if (fsp->conn != conn) { continue; } - DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", - fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode, + DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n", + fsp->fnum, file_id_static_string(&fsp->file_id), fsp->fsp_name, newname )); string_set(&fsp->fsp_name, newname); did_rename = True; } if (!did_rename) { - DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n", - (unsigned int)dev, (double)inode, newname )); + DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n", + file_id_static_string(&id), newname )); } /* Send messages to all smbd's (not ourself) that the name has changed. */ @@ -4341,7 +4341,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin return NT_STATUS_ACCESS_DENIED; } - lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL); + lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL); if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { uint32 create_options = fsp->fh->private_options; @@ -4349,7 +4349,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", fsp->fsp_name,newname)); - rename_open_files(conn, lck, fsp->dev, fsp->inode, newname); + rename_open_files(conn, lck, fsp->file_id, newname); /* * A rename acts as a new file create w.r.t. allowing an initial delete @@ -4457,6 +4457,7 @@ NTSTATUS rename_internals(connection_struct *conn, const char *dname; long offset = 0; pstring destname; + struct file_id id; *directory = *mask = 0; @@ -4635,9 +4636,10 @@ NTSTATUS rename_internals(connection_struct *conn, * don't do the rename, just return success. */ + id = file_id_sbuf(&sbuf1); + if (strcsequal(directory, newname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, NULL, id, newname); DEBUG(3, ("rename_internals: identical names in " "rename %s - returning success\n", directory)); @@ -4654,14 +4656,12 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, - NULL, NULL); + lck = get_share_mode_lock(NULL, id, NULL, NULL); if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename " "on %s -> %s\n", directory, newname)); - rename_open_files(conn, lck, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, lck, id, newname); TALLOC_FREE(lck); notify_rename(conn, S_ISDIR(sbuf1.st_mode), directory, newname); @@ -4768,9 +4768,10 @@ NTSTATUS rename_internals(connection_struct *conn, return status; } + id = file_id_sbuf(&sbuf1); + if (strcsequal(fname,destname)) { - rename_open_files(conn, NULL, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, NULL, id, newname); DEBUG(3,("rename_internals: identical names " "in wildcard rename %s - success\n", fname)); @@ -4789,12 +4790,10 @@ NTSTATUS rename_internals(connection_struct *conn, return NT_STATUS_SHARING_VIOLATION; } - lck = get_share_mode_lock(NULL, sbuf1.st_dev, - sbuf1.st_ino, NULL, NULL); + lck = get_share_mode_lock(NULL, id, NULL, NULL); if (!SMB_VFS_RENAME(conn,fname,destname)) { - rename_open_files(conn, lck, sbuf1.st_dev, - sbuf1.st_ino, newname); + rename_open_files(conn, lck, id, newname); count++; status = NT_STATUS_OK; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 835fd0cedb..429fdc154d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3366,7 +3366,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return UNIXERROR(ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); } else { /* * Original code - this is an open file. @@ -3379,7 +3379,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return(UNIXERROR(ERRDOS,ERRbadfid)); } pos = fsp->fh->position_information; - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); access_mask = fsp->access_mask; } } else { @@ -3432,7 +3432,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * return UNIXERROR(ERRDOS,ERRbadpath); } - delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino); + delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf)); if (delete_pending) { return ERROR_NT(NT_STATUS_DELETE_PENDING); } @@ -3559,7 +3559,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } } else { /* Do we have this path open ? */ - files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); + files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf)); if (fsp1 && !null_timespec(fsp1->pending_modtime)) { /* the pending modtime overrides the current modtime */ mtime_ts = fsp1->pending_modtime; diff --git a/source3/torture/locktest.c b/source3/torture/locktest.c index 792ada61a9..92838f0ff2 100644 --- a/source3/torture/locktest.c +++ b/source3/torture/locktest.c @@ -116,8 +116,7 @@ static struct record preset[] = { static struct record *recorded; -static void print_brl(SMB_DEV_T dev, - SMB_INO_T ino, +static void print_brl(struct file_id id, struct server_id pid, enum brl_type lock_type, enum brl_flavour lock_flav, @@ -138,8 +137,8 @@ static void print_brl(SMB_DEV_T dev, } #endif - printf("%s %05x:%05x %s %.0f:%.0f(%.0f)\n", - procid_str_static(&pid), (int)dev, (int)ino, + printf("%s %s %s %.0f:%.0f(%.0f)\n", + procid_str_static(&pid), file_id_static_string(&id), lock_type==READ_LOCK?"R":"W", (double)start, (double)start+size-1,(double)size); diff --git a/source3/torture/locktest2.c b/source3/torture/locktest2.c index 7153401022..184c84be43 100644 --- a/source3/torture/locktest2.c +++ b/source3/torture/locktest2.c @@ -136,13 +136,13 @@ static BOOL try_unlock(struct cli_state *c, int fstype, return False; } -static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct server_id pid, +static void print_brl(struct file_id id, struct server_id pid, enum brl_type lock_type, enum brl_flavour lock_flav, br_off start, br_off size) { - printf("%6d %05x:%05x %s %.0f:%.0f(%.0f)\n", - (int)procid_to_pid(&pid), (int)dev, (int)ino, + printf("%6d %s %s %.0f:%.0f(%.0f)\n", + (int)procid_to_pid(&pid), file_id_static_string(&id), lock_type==READ_LOCK?"R":"W", (double)start, (double)start+size-1,(double)size); diff --git a/source3/utils/status.c b/source3/utils/status.c index a797c9c4ba..207be30912 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -166,8 +166,7 @@ static void print_share_mode(const struct share_mode_entry *e, } } -static void print_brl(SMB_DEV_T dev, - SMB_INO_T ino, +static void print_brl(struct file_id id, struct server_id pid, enum brl_type lock_type, enum brl_flavour lock_flav, @@ -175,6 +174,18 @@ static void print_brl(SMB_DEV_T dev, br_off size) { static int count; + int i; + static const struct { + enum brl_type lock_type; + const char *desc; + } lock_types[] = { + { READ_LOCK, "R" }, + { WRITE_LOCK, "W" }, + { PENDING_READ_LOCK, "PR" }, + { PENDING_WRITE_LOCK, "PW" }, + { UNLOCK_LOCK, "U" } + }; + const char *desc="X"; if (count==0) { d_printf("Byte range locks:\n"); d_printf(" Pid dev:inode R/W start size\n"); @@ -182,10 +193,16 @@ static void print_brl(SMB_DEV_T dev, } count++; - d_printf("%8s %05x:%05x %s %9.0f %9.0f\n", - procid_str_static(&pid), (int)dev, (int)ino, - lock_type==READ_LOCK?"R":"W", - (double)start, (double)size); + for (i=0;i<ARRAY_SIZE(lock_types);i++) { + if (lock_type == lock_types[i].lock_type) { + desc = lock_types[i].desc; + } + } + + d_printf("%8s %s %2s %9.0f %9.0f\n", + procid_str_static(&pid), file_id_static_string(&id), + desc, + (double)start, (double)size); } static int traverse_fn1(struct db_record *rec, |