* can't be locked. Thus, this must always be called in a while loop to stabilize
* things, since we can always lose the race condition getting to the parent vnode.
*/
-int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, long rights,
- long *outRightsp)
+int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, afs_uint32 rights,
+ afs_uint32 *outRightsp)
{
cm_scache_t *aclScp;
long code;
#include "cm_user.h"
extern int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up,
- long rights, long *outRights);
+ afs_uint32 rights, afs_uint32 *outRights);
extern long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *up,
struct cm_req *reqp);
* Get an acl cache entry for a particular user and file, or return that it doesn't exist.
* Called with the scp locked.
*/
-long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, long *rightsp)
+long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, afs_uint32 *rightsp)
{
cm_aclent_t *aclp;
long retval = -1;
*
* The scp must be locked when this function is called.
*/
-long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, long rights)
+long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, afs_uint32 rights)
{
register struct cm_aclent *aclp;
struct cm_aclent *nextp; /* next guy same vnode */
struct cm_scache *backp; /* back ptr to vnode */
struct cm_user *userp; /* user whose access is cached */
- long randomAccess; /* watch for more rights in acl.h */
+ afs_uint32 randomAccess; /* watch for more rights in acl.h */
unsigned long tgtLifetime; /* time this expires */
} cm_aclent_t;
extern long cm_InitACLCache(int newFile, long size);
-extern long cm_FindACLCache(struct cm_scache *scp, struct cm_user *userp, long *rightsp);
+extern long cm_FindACLCache(struct cm_scache *scp, struct cm_user *userp, afs_uint32 *rightsp);
static cm_aclent_t *GetFreeACLEnt(cm_scache_t * scp);
-extern long cm_AddACLCache(struct cm_scache *scp, struct cm_user *userp, long rights);
+extern long cm_AddACLCache(struct cm_scache *scp, struct cm_user *userp, afs_uint32 rights);
extern void cm_FreeAllACLEnts(struct cm_scache *scp);
return code;
}
+#ifdef QUERY_AFSID
long cm_UsernameToId(char *uname, cm_ucell_t * ucellp, afs_uint32* uid)
{
afs_int32 code;
return 0;
}
-
+#endif /* QUERY_AFSID */
long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
{
ucellp->kvno = ct.AuthHandle;
ucellp->expirationTime = ct.EndTimestamp;
ucellp->gen++;
+#ifdef QUERY_AFSID
ucellp->uid = ANONYMOUSID;
+#endif
if (uname) {
StringCbCopyA(ucellp->userName, MAXKTCNAMELEN, uname);
-
+#ifdef QUERY_AFSID
cm_UsernameToId(uname, ucellp, &ucellp->uid);
+#endif
}
ucellp->flags |= CM_UCELLFLAG_RXKAD;
lock_ReleaseMutex(&userp->mx);
* CM_SCACHESYNC_STOREDATA_EXCL and CM_SCACHEFLAG_DATASTORING.
*/
long cm_SyncOp(cm_scache_t *scp, cm_buf_t *bufp, cm_user_t *up, cm_req_t *reqp,
- long rights, long flags)
+ afs_uint32 rights, afs_uint32 flags)
{
osi_queueData_t *qdp;
long code;
cm_buf_t *tbufp;
- long outRights;
+ afs_uint32 outRights;
int bufLocked;
/* lookup this first */
return CM_ERROR_READONLY;
if (cm_HaveAccessRights(scp, up, rights, &outRights)) {
- if (~outRights & rights) return CM_ERROR_NOACCESS;
+ if (~outRights & rights)
+ return CM_ERROR_NOACCESS;
}
else {
/* we don't know the required access rights */
/* for those syncops that setup for RPCs.
* Called with scache locked.
*/
-void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, long flags)
+void cm_SyncOpDone(cm_scache_t *scp, cm_buf_t *bufp, afs_uint32 flags)
{
osi_queueData_t *qdp;
cm_buf_t *tbufp;
* started before that, can cause old info to be merged from the first call.
*/
void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp,
- cm_user_t *userp, int flags)
+ cm_user_t *userp, afs_uint32 flags)
{
// yj: i want to create some fake status for the /afs directory and the
// entries under that directory
unsigned long unique;
} cm_fid_t;
-#if 0
-typedef struct cm_accessCache {
- osi_queue_t q; /* queue header */
- struct cm_user *userp; /* user having access rights */
- unsigned long rights; /* rights */
-} cm_accessCache_t;
-#endif
-
/* Key used for byte range locking. Each unique key identifies a
unique client per cm_scache_t for the purpose of locking. */
typedef afs_uint64 cm_key_t;
#define CM_SCACHE_MAGIC ('S' | 'C'<<8 | 'A'<<16 | 'C'<<24)
typedef struct cm_scache {
- osi_queue_t q; /* lru queue; cm_scacheLock */
+ osi_queue_t q; /* lru queue; cm_scacheLock */
afs_uint32 magic;
- struct cm_scache *nextp; /* next in hash; cm_scacheLock */
+ struct cm_scache *nextp; /* next in hash; cm_scacheLock */
cm_fid_t fid;
- afs_uint32 flags; /* flags; locked by mx */
+ afs_uint32 flags; /* flags; locked by mx */
/* synchronization stuff */
- osi_mutex_t mx; /* mutex for this structure */
- osi_rwlock_t bufCreateLock; /* read-locked during buffer creation;
- * write-locked to prevent buffers from
- * being created during a truncate op, etc.
- */
+ osi_mutex_t mx; /* mutex for this structure */
+ osi_rwlock_t bufCreateLock; /* read-locked during buffer creation;
+ * write-locked to prevent buffers from
+ * being created during a truncate op, etc.
+ */
afs_uint32 refCount; /* reference count; cm_scacheLock */
- osi_queueData_t *bufReadsp; /* queue of buffers being read */
+ osi_queueData_t *bufReadsp; /* queue of buffers being read */
osi_queueData_t *bufWritesp; /* queue of buffers being written */
/* parent info for ACLs */
afs_uint32 parentVnode; /* parent vnode for ACL callbacks */
- afs_uint32 parentUnique; /* for ACL callbacks */
+ afs_uint32 parentUnique; /* for ACL callbacks */
/* local modification stat */
- afs_uint32 mask; /* for clientModTime, length and
- * truncPos */
+ afs_uint32 mask; /* for clientModTime, length and
+ * truncPos */
/* file status */
afs_uint32 fileType; /* file type */
time_t clientModTime; /* mtime */
time_t serverModTime; /* at server, for concurrent call
* comparisons */
- osi_hyper_t length; /* file length */
+ osi_hyper_t length; /* file length */
cm_prefetch_t prefetch; /* prefetch info structure */
- afs_uint32 unixModeBits; /* unix protection mode bits */
+ afs_uint32 unixModeBits; /* unix protection mode bits */
afs_uint32 linkCount; /* link count */
afs_uint32 dataVersion; /* data version */
- afs_uint32 owner; /* file owner */
- afs_uint32 group; /* file owning group */
+ afs_uint32 owner; /* file owner */
+ afs_uint32 group; /* file owning group */
+ cm_user_t *creator; /* user, if new file */
/* pseudo file status */
- osi_hyper_t serverLength; /* length known to server */
+ osi_hyper_t serverLength; /* length known to server */
/* aux file status */
- osi_hyper_t truncPos; /* file size to truncate to before
- * storing data */
+ osi_hyper_t truncPos; /* file size to truncate to before
+ * storing data */
/* symlink and mount point info */
char mountPointStringp[MOUNTPOINTLEN]; /* the string stored in a mount point;
extern int cm_FidCmp(cm_fid_t *, cm_fid_t *);
extern long cm_SyncOp(cm_scache_t *, struct cm_buf *, struct cm_user *,
- struct cm_req *, long, long);
+ struct cm_req *, afs_uint32, afs_uint32);
-extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, long);
+extern void cm_SyncOpDone(cm_scache_t *, struct cm_buf *, afs_uint32);
extern void cm_MergeStatus(cm_scache_t *, struct AFSFetchStatus *, struct AFSVolSync *,
- struct cm_user *, int flags);
+ struct cm_user *, afs_uint32 flags);
extern void cm_AFSFidFromFid(struct AFSFid *, cm_fid_t *);
int iterator; /* for use as ListTokens cookie */
long flags; /* flags */
char userName[MAXKTCNAMELEN]; /* user name */
+#ifdef QUERY_AFSID
afs_uint32 uid; /* User's AFS ID in this cell */
+#endif
} cm_ucell_t;
#define CM_UCELLFLAG_HASTIX 1 /* has Kerberos tickets */
code = cm_GetSCache(&newFid, &scp, userp, reqp);
if (code == 0) {
lock_ObtainMutex(&scp->mx);
+ scp->creator = userp; /* remember who created it */
if (!cm_HaveCallback(scp)) {
cm_MergeStatus(scp, &newFileStatus, &volSync,
userp, 0);
CM_SCACHESYNC_NEEDCALLBACK);
if (code == CM_ERROR_NOACCESS &&
- lock_type == LockWrite) {
+ lock_type == LockWrite &&
+ scp->creator == userp) {
/* check for PRSFS_INSERT. */
cm_ucell_t * ucp;
CM_SCACHESYNC_GETSTATUS |
CM_SCACHESYNC_NEEDCALLBACK);
- if (code) {
- if (code == CM_ERROR_NOACCESS)
- osi_Log0(afsd_logp, "cm_LockCheckPerms user has no INSERT bits for scp");
-
- goto return_code;
- }
-
- code = CM_ERROR_NOACCESS;
-
- lock_ObtainMutex(&userp->mx);
- for (ucp = userp->cellInfop; ucp; ucp = ucp->nextp) {
- if (scp->fid.cell == ucp->cellp->cellID) {
- if (scp->owner == ucp->uid)
- code = 0;
-
- break;
- }
- }
- lock_ReleaseMutex(&userp->mx);
+ if (code == CM_ERROR_NOACCESS)
+ osi_Log0(afsd_logp, "cm_LockCheckPerms user is creator but has no INSERT bits for scp");
}
return_code:
fidp->flags &= ~SMB_FID_DELONCLOSE;
}
+ /* if this was a newly created file, then clear the creator
+ * in the stat cache entry. */
+ if (fidp->flags & SMB_FID_CREATED) {
+ lock_ObtainMutex(&fidp->scp->mx);
+ if (fidp->scp->creator == userp)
+ fidp->scp->creator = NULL;
+ lock_ReleaseMutex(&fidp->scp->mx);
+ fidp->flags &= ~SMB_FID_CREATED;
+ }
+
if (fidp->flags & SMB_FID_NTOPEN) {
fidp->NTopen_dscp = NULL;
fidp->NTopen_pathp = NULL;
afs_uint32 dosTime;
char *tidPathp;
cm_req_t req;
+ int created = 0; /* the file was new */
cm_InitReq(&req);
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (!excl && code == CM_ERROR_EXISTS) {
+ if (code == 0) {
+ created = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ dscp, lastNamep, NULL, TRUE);
+ } else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
/* always create it open for read/write */
fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
+ /* remember that the file was newly created */
+ if (created)
+ fidp->flags |= SMB_FID_CREATED;
+
/* save a pointer to the vnode */
fidp->scp = scp;
/* and the user */
#define SMB_FID_OPENREAD 1 /* open for reading */
#define SMB_FID_OPENWRITE 2 /* open for writing */
-#define SMB_FID_UNUSED 4 /* free for use */
+#define SMB_FID_CREATED 4 /* a new file */
#define SMB_FID_IOCTL 8 /* a file descriptor for the
* magic ioctl file */
#define SMB_FID_OPENDELETE 0x10 /* open for deletion (NT) */
long returnEALength;
char *tidPathp;
cm_req_t req;
+ int created = 0;
cm_InitReq(&req);
smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (!excl && code == CM_ERROR_EXISTS) {
+ if (code == 0) {
+ created = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ dscp, lastNamep, NULL, TRUE);
+ } else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
fidp->flags |= SMB_FID_OPENREAD;
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
+
+ /* remember that the file was newly created */
+ if (created)
+ fidp->flags |= SMB_FID_CREATED;
+
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
int parmSlot; /* which parm we're dealing with */
char *tidPathp;
cm_req_t req;
+ int created = 0;
cm_InitReq(&req);
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (!excl && code == CM_ERROR_EXISTS) {
+ if (code == 0) {
+ created = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ dscp, lastNamep, NULL, TRUE);
+ } else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
+ /* remember if the file was newly created */
+ if (created)
+ fidp->flags |= SMB_FID_CREATED;
+
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
char *tidPathp;
BOOL foundscp;
cm_req_t req;
+ int created = 0;
cm_InitReq(&req);
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+ if (code == 0) {
+ created = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ dscp, lastNamep, NULL, TRUE);
+ } else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
fidp->flags = fidflags;
+ /* remember if the file was newly created */
+ if (created)
+ fidp->flags |= SMB_FID_CREATED;
+
/* save parent dir and pathname for delete or change notification */
if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
fidp->flags |= SMB_FID_NTOPEN;
ULONG *lparmp;
char *outData;
cm_req_t req;
+ int created = 0;
cm_InitReq(&req);
setAttr.clientModTime = time(NULL);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+ if (code == 0) {
+ created = 1;
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ dscp, lastNamep, NULL, TRUE);
+ } else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
fidp->flags = fidflags;
+ /* remember if the file was newly created */
+ if (created)
+ fidp->flags |= SMB_FID_CREATED;
+
/* save parent dir and pathname for deletion or change notification */
if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
fidp->flags |= SMB_FID_NTOPEN;