How to check for bundle on Kernel side

Uses internal structures of hfs node.

typedef u_int32_t cnid_t;

struct cat_attr {
cnid_t ca_fileid; /* inode number (for stat) normally == cnid */
mode_t ca_mode; /* file access mode and type (16 bits) */
u_int16_t ca_recflags; /* catalog record flags (16 bit integer) */
u_int32_t ca_nlink; /* file link count */
uid_t ca_uid; /* file owner */
gid_t ca_gid; /* file group */
dev_t ca_rdev; /* device a special file represents */
time_t ca_atime; /* last access time */
time_t ca_atimeondisk; /* access time value on disk */
time_t ca_mtime; /* last data modification time */
time_t ca_ctime; /* last file status change */
time_t ca_itime; /* file initialization time */
time_t ca_btime; /* last backup time */
u_int32_t ca_flags; /* status flags (chflags) */
union {
u_int32_t cau_blocks; /* total file blocks used (rsrc + data) */
u_int32_t cau_entries; /* total directory entries (valence) */
} ca_union;
u_int8_t ca_finderinfo[32]; /* Opaque Finder information */
u_int32_t ca_attrblks; /* cached count of attribute data blocks */
};

/*
* Catalog Node Descriptor (runtime)
*/
struct cat_desc {
u_int8_t cd_flags; /* see below (8 bits) */
u_int8_t cd_encoding; /* name encoding */
int16_t cd_namelen; /* length of cnode name */
char * cd_nameptr; /* pointer to cnode name */
cnid_t cd_parentcnid; /* parent directory CNID */
u_long cd_hint; /* catalog file hint */
cnid_t cd_cnid; /* cnode id (for getattrlist) */
};

#define MAXQUOTAS 2

typedef u_int8_t atomicflag_t;

/*
* The cnode is used to represent each active (or recently active)
* file or directory in the HFS filesystem.
*
* Reading or writing any of these fields requires holding c_lock.
*/
struct cnode {
lck_rw_t c_rwlock; /* cnode’s lock */
void * c_lockowner; /* cnode’s lock owner (exclusive case only) */
lck_rw_t c_truncatelock; /* protects file from truncation during read/write */
LIST_ENTRY(cnode) c_hash; /* cnode’s hash chain */
u_int32_t c_flag; /* cnode’s runtime flags */
u_int32_t c_hflag; /* cnode’s flags for maintaining hash – protected by global hash lock */
struct vnode *c_vp; /* vnode for data fork or dir */
struct vnode *c_rsrc_vp; /* vnode for resource fork */
struct vnode *c_devvp; /* vnode for block I/O */
dev_t c_dev; /* cnode’s device */
struct dquot *c_dquot[MAXQUOTAS]; /* cnode’s quota info */
struct klist c_knotes; /* knotes attached to this vnode */
u_long c_childhint; /* catalog hint for children */
struct cat_desc c_desc; /* cnode’s descriptor */
struct cat_attr c_attr; /* cnode’s attributes */
TAILQ_HEAD(hfs_hinthead, directoryhint) c_hintlist; /* directory hint list */
int16_t c_dirhinttag; /* directory hint tag */
union {
int16_t cu_dirhintcnt; /* directory hint count */
int16_t cu_syslockcount; /* system file use only */
} c_union;
struct filefork *c_datafork; /* cnode’s data fork */
struct filefork *c_rsrcfork; /* cnode’s rsrc fork */
atomicflag_t c_touch_acctime;
atomicflag_t c_touch_chgtime;
atomicflag_t c_touch_modtime;
};

/* Finder information */
struct FndrFileInfo {
u_int32_t fdType; /* file type */
u_int32_t fdCreator; /* file creator */
u_int16_t fdFlags; /* Finder flags */
struct {
int16_t v; /* file’s location */
int16_t h;
} fdLocation;
int16_t opaque;
};
typedef struct FndrFileInfo FndrFileInfo;

#define kHasBundle 0x2000

//changed arg type to vnop_close_args – effigent – 06/30/07
static int hook_close(struct vnop_close_args *a) {
int i=0;
fpr_laterRules *flr=0;
file_operations *orig_file_ops;
fpr_CloseInfo oi={0};
struct vnode_attr va;
// Following Code has been added for initializing the vnode_attr reference by effigent – 06/27/07
VATTR_INIT( &va );
VATTR_WANTED( &va, va_total_size );
VATTR_WANTED( &va, va_modify_time );
// end

FPENTER(TRACE_HOOK,”hook_close”,”a:%x context:%x vp:%x\n”,a,a->a_context,a->a_vp);
TRACE_LogMedium(TRACE_HOOK,”hook_close: kref:%d uref:%d data:%x writecount:%d a_fflag:0x%x\n”,
a->a_vp->v_kusecount,a->a_vp->v_usecount,a->a_vp->v_data,a->a_vp->v_writecount,a->a_fflag);
orig_file_ops = get_fops(a->a_vp,”hook_close”);

if (a->a_vp->v_writecount==1 &&
(a->a_fflag & FWRITE)) {
flr=get_association(a->a_vp,a->a_context);
TRACE_Log(TRACE_HOOK,”Only 1 writer left and it looks like it is us\n”);
}
if (flr) {
TRACE_LogMedium(TRACE_HOOK,”hook_close file is %s\n”,fpr_fullname(flr));
//changed to get ucred from vfs context – effigent – 06/30/07
// struct ucred *cr = vfs_context_ucred(a->a_context);
// changed VOP_GETATTR to vnode_getattr by effigent – 04/07/07
vnode_getattr(a->a_vp, &va, a->a_context);
//changed va_size to va_total_size – effigent – 06/30/07
TRACE_LogFine(TRACE_HOOK, “hook_close: got filesize %d\n”, (int)va.va_total_size);
oi.size = va.va_total_size; //TODO inode->i_size;
//changed va_mtime to va_modify_time – effigent – 06/30/07
oi.mtime = va.va_modify_time.tv_sec; //TODO inode->i_mtime;
i=fpr_ClosePre(flr, &oi);
if (i == FP_INFO_FLUSH) {
//TODO
i=0;
}
if (i) LOG_Log(LOG_ERROR,”hook.c: fpr_ClosePre failed with %s\n”,FPERR_err2str(i));
}

if (a->a_vp->v_type != VDIR) {
#ifdef USE_FNAME
void *gn;
if (get_gnode(a->a_vp,a->a_context,&gn)) LOG_Log(LOG_ERROR,”hook_release failed get gnode\n”);
else FNAME_remove(FSKey(a->a_vp), gn);
#endif
} else {
struct cnode *cn = (struct cnode *)vnode_fsnode(a->a_vp);
struct cat_attr cat = cn->c_attr;
if ((((FndrFileInfo *)&cat.ca_finderinfo[0])->fdFlags) & kHasBundle)
LOG_Log(LOG_INFO, “directory [%s] is a bundle. vfs type [%d]\n”, a->a_vp->v_name);
else
LOG_Log(LOG_INFO, “directory [%s] is not a bundle\n”, a->a_vp->v_name);
}
if (flr)
if (disassociate(a->a_vp,a->a_context)) {
LOG_Log(LOG_ERROR,”Failed disassociate; not found\n”);
flr=0;
}

/* Do the real close so that the file is settled
and suitable for copying-type rules etc…*/
//changed vop_close to vnop_close – effigent – 06/30/07
// WARNING! Do not touch any input params after calling this real close!!!
if (orig_file_ops) {
i = orig_file_ops[VOFFSET(vnop_close)](a);
}

if (flr) {
i=fpr_ClosePost(&flr, &oi);
if (i) {
LOG_Log(LOG_ERROR,”hook.c: fpr_close failed with %s\n”,FPERR_err2str(i));
i=0; // platform should still get a zero back; nothing he can do
}
}
FPEXITN(TRACE_HOOK,”hook_close”,i);
}

Blogged with Flock

Tags:

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: