diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/clidfs.c | 61 | ||||
-rw-r--r-- | source3/libsmb/clifsinfo.c | 62 | ||||
-rw-r--r-- | source3/libsmb/clilist.c | 97 | ||||
-rw-r--r-- | source3/libsmb/climessage.c | 46 | ||||
-rw-r--r-- | source3/libsmb/clistr.c | 43 |
5 files changed, 182 insertions, 127 deletions
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 32a2c31c83..ef3d0e8db3 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -266,7 +266,8 @@ const char *cli_cm_get_mntpoint(struct cli_state *c) ********************************************************************/ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx, - const char *server, + struct cli_state *referring_cli, + const char *server, const char *share, bool show_hdr) { @@ -289,8 +290,18 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx, cli_cm_set_mntpoint(node->cli, ""); - return node->cli; + if (referring_cli && referring_cli->posix_capabilities) { + uint16 major, minor; + uint32 caplow, caphigh; + if (cli_unix_extensions_version(node->cli, &major, + &minor, &caplow, &caphigh)) { + cli_set_unix_extensions_capabilities(node->cli, + major, minor, + caplow, caphigh); + } + } + return node->cli; } /******************************************************************** @@ -317,6 +328,7 @@ static struct cli_state *cli_cm_find(const char *server, const char *share) ****************************************************************************/ struct cli_state *cli_cm_open(TALLOC_CTX *ctx, + struct cli_state *referring_cli, const char *server, const char *share, bool show_hdr) @@ -327,7 +339,7 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx, c = cli_cm_find(server, share); if (!c) { - c = cli_cm_connect(ctx, server, share, show_hdr); + c = cli_cm_connect(ctx, referring_cli, server, share, show_hdr); } return c; @@ -378,17 +390,17 @@ static void cm_set_password(const char *newpass) } } -void cli_cm_set_credentials(struct user_auth_info *user) +void cli_cm_set_credentials(void) { SAFE_FREE(cm_creds.username); - cm_creds.username = SMB_STRDUP(user->username); + cm_creds.username = SMB_STRDUP(get_cmdline_auth_info_username()); - if (user->got_pass) { - cm_set_password(user->password); + if (get_cmdline_auth_info_got_pass()) { + cm_set_password(get_cmdline_auth_info_password()); } - cm_creds.use_kerberos = user->use_kerberos; - cm_creds.signing_state = user->signing_state; + cm_creds.use_kerberos = get_cmdline_auth_info_use_kerberos(); + cm_creds.signing_state = get_cmdline_auth_info_signing_state(); } /**************************************************************************** @@ -729,7 +741,8 @@ bool cli_resolve_path(TALLOC_CTX *ctx, /* Check for the referral. */ - if (!(cli_ipc = cli_cm_open(ctx, rootcli->desthost, "IPC$", false))) { + if (!(cli_ipc = cli_cm_open(ctx, rootcli, + rootcli->desthost, "IPC$", false))) { return false; } @@ -768,7 +781,8 @@ bool cli_resolve_path(TALLOC_CTX *ctx, */ /* Open the connection to the target server & share */ - if ((*targetcli = cli_cm_open(ctx, server, share, false)) == NULL) { + if ((*targetcli = cli_cm_open(ctx, rootcli, + server, share, false)) == NULL) { d_printf("Unable to follow dfs referral [\\%s\\%s]\n", server, share ); return false; @@ -853,31 +867,6 @@ bool cli_resolve_path(TALLOC_CTX *ctx, } /******************************************************************** - Temporary hack - remove when pstring is dead. JRA. -********************************************************************/ - -bool cli_resolve_path_pstring( const char *mountpt, - struct cli_state *rootcli, - const char *path, - struct cli_state **targetcli, - pstring targetpath) -{ - char *tpath = NULL; - TALLOC_CTX *ctx = talloc_stackframe(); - bool ret = cli_resolve_path(ctx, - mountpt, - rootcli, - path, - targetcli, - &tpath); - if (tpath) { - pstrcpy(targetpath, tpath); - } - TALLOC_FREE(ctx); - return ret; -} - -/******************************************************************** ********************************************************************/ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index a45623b9e4..1a75d144b2 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -22,7 +22,7 @@ /**************************************************************************** Get UNIX extensions version info. ****************************************************************************/ - + bool cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 *pminor, uint32 *pcaplow, uint32 *pcaphigh) { @@ -33,18 +33,18 @@ bool cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 * unsigned int rparam_count=0, rdata_count=0; setup = TRANSACT2_QFSINFO; - + SSVAL(param,0,SMB_QUERY_CIFS_UNIX_INFO); - if (!cli_send_trans(cli, SMBtrans2, - NULL, + if (!cli_send_trans(cli, SMBtrans2, + NULL, 0, 0, &setup, 1, 0, param, 2, 0, NULL, 0, 560)) { goto cleanup; } - + if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_count, &rdata, &rdata_count)) { @@ -67,7 +67,7 @@ bool cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 * cli->posix_capabilities = *pcaplow = IVAL(rdata,4); *pcaphigh = IVAL(rdata,8); - /* todo: but not yet needed + /* todo: but not yet needed * return the other stuff */ @@ -75,13 +75,13 @@ cleanup: SAFE_FREE(rparam); SAFE_FREE(rdata); - return ret; + return ret; } /**************************************************************************** Set UNIX extensions capabilities. ****************************************************************************/ - + bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, uint16 minor, uint32 caplow, uint32 caphigh) { @@ -93,7 +93,7 @@ bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, u unsigned int rparam_count=0, rdata_count=0; setup = TRANSACT2_SETFSINFO; - + SSVAL(param,0,0); SSVAL(param,2,SMB_SET_CIFS_UNIX_INFO); @@ -102,15 +102,15 @@ bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, u SIVAL(data,4,caplow); SIVAL(data,8,caphigh); - if (!cli_send_trans(cli, SMBtrans2, - NULL, + if (!cli_send_trans(cli, SMBtrans2, + NULL, 0, 0, &setup, 1, 0, param, 4, 0, data, 12, 560)) { goto cleanup; } - + if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_count, &rdata, &rdata_count)) { @@ -128,7 +128,7 @@ cleanup: SAFE_FREE(rparam); SAFE_FREE(rdata); - return ret; + return ret; } bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr) @@ -143,18 +143,18 @@ bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr) smb_panic("cli_get_fs_attr_info() called with NULL Pionter!"); setup = TRANSACT2_QFSINFO; - + SSVAL(param,0,SMB_QUERY_FS_ATTRIBUTE_INFO); - if (!cli_send_trans(cli, SMBtrans2, - NULL, + if (!cli_send_trans(cli, SMBtrans2, + NULL, 0, 0, &setup, 1, 0, param, 2, 0, NULL, 0, 560)) { goto cleanup; } - + if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_count, &rdata, &rdata_count)) { @@ -174,7 +174,7 @@ bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr) *fs_attr = IVAL(rdata,0); - /* todo: but not yet needed + /* todo: but not yet needed * return the other stuff */ @@ -182,7 +182,7 @@ cleanup: SAFE_FREE(rparam); SAFE_FREE(rdata); - return ret; + return ret; } bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number) @@ -195,18 +195,18 @@ bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint unsigned char nlen; setup = TRANSACT2_QFSINFO; - + SSVAL(param,0,SMB_INFO_VOLUME); - if (!cli_send_trans(cli, SMBtrans2, - NULL, + if (!cli_send_trans(cli, SMBtrans2, + NULL, 0, 0, &setup, 1, 0, param, 2, 0, NULL, 0, 560)) { goto cleanup; } - + if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_count, &rdata, &rdata_count)) { @@ -230,7 +230,7 @@ bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint nlen = CVAL(rdata,l2_vol_cch); clistr_pull(cli, volume_name, rdata + l2_vol_szVolLabel, sizeof(fstring), nlen, STR_NOALIGN); - /* todo: but not yet needed + /* todo: but not yet needed * return the other stuff */ @@ -238,7 +238,7 @@ cleanup: SAFE_FREE(rparam); SAFE_FREE(rdata); - return ret; + return ret; } bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate) @@ -251,18 +251,18 @@ bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 * unsigned int nlen; setup = TRANSACT2_QFSINFO; - + SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO); - if (!cli_send_trans(cli, SMBtrans2, - NULL, + if (!cli_send_trans(cli, SMBtrans2, + NULL, 0, 0, &setup, 1, 0, param, 2, 0, NULL, 0, 560)) { goto cleanup; } - + if (!cli_receive_trans(cli, SMBtrans2, &rparam, &rparam_count, &rdata, &rdata_count)) { @@ -291,7 +291,7 @@ bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 * nlen = IVAL(rdata,12); clistr_pull(cli, volume_name, rdata + 18, sizeof(fstring), nlen, STR_UNICODE); - /* todo: but not yet needed + /* todo: but not yet needed * return the other stuff */ @@ -299,5 +299,5 @@ cleanup: SAFE_FREE(rparam); SAFE_FREE(rdata); - return ret; + return ret; } diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index 284538541a..fc47f94aa1 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -19,8 +19,6 @@ #include "includes.h" -extern file_info def_finfo; - /**************************************************************************** Calculate a safe next_entry_offset. ****************************************************************************/ @@ -44,7 +42,8 @@ static size_t calc_next_entry_offset(const char *base, const char *pdata_end) by NT and 2 is used by OS/2 ****************************************************************************/ -static size_t interpret_long_filename(struct cli_state *cli, +static size_t interpret_long_filename(TALLOC_CTX *ctx, + struct cli_state *cli, int level, const char *p, const char *pdata_end, @@ -52,20 +51,16 @@ static size_t interpret_long_filename(struct cli_state *cli, uint32 *p_resume_key, DATA_BLOB *p_last_name_raw) { - file_info finfo2; int len; + size_t ret; const char *base = p; data_blob_free(p_last_name_raw); - if (!finfo) { - finfo = &finfo2; - } - if (p_resume_key) { *p_resume_key = 0; } - memcpy(finfo,&def_finfo,sizeof(*finfo)); + ZERO_STRUCTP(finfo); finfo->cli = cli; switch (level) { @@ -90,10 +85,16 @@ static size_t interpret_long_filename(struct cli_state *cli, important to cope with the differences between win2000 and win9x for this call (tridge) */ - p += clistr_pull(cli, finfo->name, p, - sizeof(finfo->name), - len+2, - STR_TERMINATE); + ret = clistr_pull_talloc(ctx, + cli, + &finfo->name, + p, + len+2, + STR_TERMINATE); + if (ret == (size_t)-1) { + return pdata_end - base; + } + p += ret; return PTR_DIFF(p, base); case 2: /* this is what OS/2 uses mostly */ @@ -113,10 +114,16 @@ static size_t interpret_long_filename(struct cli_state *cli, if (p + len + 1 > pdata_end) { return pdata_end - base; } - p += clistr_pull(cli, finfo->name, p, - sizeof(finfo->name), - len, - STR_NOALIGN); + ret = clistr_pull_talloc(ctx, + cli, + &finfo->name, + p, + len, + STR_NOALIGN); + if (ret == (size_t)-1) { + return pdata_end - base; + } + p += ret; return PTR_DIFF(p, base) + 1; case 260: /* NT uses this, but also accepts 2 */ @@ -168,9 +175,15 @@ static size_t interpret_long_filename(struct cli_state *cli, if (p + namelen < p || p + namelen > pdata_end) { return pdata_end - base; } - clistr_pull(cli, finfo->name, p, - sizeof(finfo->name), - namelen, 0); + ret = clistr_pull_talloc(ctx, + cli, + &finfo->name, + p, + namelen, + 0); + if (ret == (size_t)-1) { + return pdata_end - base; + } /* To be robust in the face of unicode conversion failures we need to copy the raw bytes of the last name seen here. @@ -221,6 +234,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, char *param; const char *mnt; uint32 resume_key = 0; + TALLOC_CTX *frame = talloc_stackframe(); DATA_BLOB last_name_raw = data_blob(NULL, 0); /* NT uses 260, OS/2 uses 2. Both accept 1. */ @@ -228,6 +242,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, mask = SMB_STRDUP(Mask); if (!mask) { + TALLOC_FREE(frame); return -1; } @@ -292,6 +307,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, #endif )) { SAFE_FREE(param); + TALLOC_FREE(frame); break; } @@ -352,7 +368,8 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, /* Last entry - fixup the last offset length. */ SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2)); } - p2 += interpret_long_filename(cli, + p2 += interpret_long_filename(frame, + cli, info_level, p2, rdata_end, @@ -417,14 +434,15 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, /* no connection problem. let user function add each entry */ rdata_end = dirlist + dirlist_len; for (p=dirlist,i=0;i<total_received;i++) { - p += interpret_long_filename(cli, + p += interpret_long_filename(frame, + cli, info_level, p, rdata_end, &finfo, NULL, NULL); - fn( mnt,&finfo, Mask, state ); + fn(mnt,&finfo, Mask, state); } } @@ -432,6 +450,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, SAFE_FREE(dirlist); data_blob_free(&last_name_raw); SAFE_FREE(mask); + TALLOC_FREE(frame); return(total_received); } @@ -440,10 +459,12 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, The length of the structure is returned. ****************************************************************************/ -static int interpret_short_filename(struct cli_state *cli, char *p,file_info *finfo) +static int interpret_short_filename(TALLOC_CTX *ctx, + struct cli_state *cli, + char *p, + file_info *finfo) { - - *finfo = def_finfo; + ZERO_STRUCTP(finfo); finfo->cli = cli; finfo->mode = CVAL(p,21); @@ -454,16 +475,21 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec; finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0; finfo->size = IVAL(p,26); - clistr_pull(cli, finfo->name, p+30, sizeof(finfo->name), 12, STR_ASCII); - if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) { - strncpy(finfo->short_name,finfo->name, sizeof(finfo->short_name)-1); - finfo->short_name[sizeof(finfo->short_name)-1] = '\0'; + clistr_pull_talloc(ctx, + cli, + &finfo->name, + p+30, + 12, + STR_ASCII); + if (!finfo->name) { + finfo->name = talloc_strdup(ctx, finfo->short_name); + } else if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) { + finfo->name = talloc_strdup(ctx, finfo->short_name); } return(DIR_STRUCT_SIZE); } - /**************************************************************************** Do a directory listing, calling fn on each file found. this uses the old SMBsearch interface. It is needed for testing Samba, @@ -482,6 +508,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, int i; char *dirlist = NULL; char *mask = NULL; + TALLOC_CTX *frame = NULL; ZERO_ARRAY(status); @@ -507,7 +534,9 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, p = smb_buf(cli->outbuf); *p++ = 4; - p += clistr_push(cli, p, first?mask:"", -1, STR_TERMINATE); + p += clistr_push(cli, p, first?mask:"", + cli->bufsize - PTR_DIFF(p,cli->outbuf), + STR_TERMINATE); *p++ = 5; if (first) { SSVAL(p,0,0); @@ -577,11 +606,13 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, } } + frame = talloc_stackframe(); for (p=dirlist,i=0;i<num_received;i++) { file_info finfo; - p += interpret_short_filename(cli, p,&finfo); + p += interpret_short_filename(frame,cli, p,&finfo); fn("\\", &finfo, Mask, state); } + TALLOC_FREE(frame); SAFE_FREE(mask); SAFE_FREE(dirlist); diff --git a/source3/libsmb/climessage.c b/source3/libsmb/climessage.c index 2a195753ae..13ef1d43d4 100644 --- a/source3/libsmb/climessage.c +++ b/source3/libsmb/climessage.c @@ -19,11 +19,11 @@ #include "includes.h" - /**************************************************************************** -start a message sequence + Start a message sequence. ****************************************************************************/ -int cli_message_start_build(struct cli_state *cli, char *host, char *username) + +int cli_message_start_build(struct cli_state *cli, const char *host, const char *username) { char *p; @@ -33,25 +33,26 @@ int cli_message_start_build(struct cli_state *cli, char *host, char *username) SCVAL(cli->outbuf,smb_com,SMBsendstrt); SSVAL(cli->outbuf,smb_tid,cli->cnum); cli_setup_packet(cli); - + p = smb_buf(cli->outbuf); *p++ = 4; - p += clistr_push(cli, p, username, -1, STR_ASCII|STR_TERMINATE); + p += clistr_push(cli, p, username, + cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_ASCII|STR_TERMINATE); *p++ = 4; - p += clistr_push(cli, p, host, -1, STR_ASCII|STR_TERMINATE); - + p += clistr_push(cli, p, host, + cli->bufsize - PTR_DIFF(p,cli->outbuf), STR_ASCII|STR_TERMINATE); + cli_setup_bcc(cli, p); return(PTR_DIFF(p, cli->outbuf)); } -bool cli_message_start(struct cli_state *cli, char *host, char *username, +bool cli_message_start(struct cli_state *cli, const char *host, const char *username, int *grp) { cli_message_start_build(cli, host, username); - - cli_send_smb(cli); - + cli_send_smb(cli); + if (!cli_receive_smb(cli)) { return False; } @@ -63,11 +64,11 @@ bool cli_message_start(struct cli_state *cli, char *host, char *username, return True; } - /**************************************************************************** -send a message + Send a message ****************************************************************************/ -int cli_message_text_build(struct cli_state *cli, char *msg, int len, int grp) + +int cli_message_text_build(struct cli_state *cli, const char *msg, int len, int grp) { char *msgdos; int lendos; @@ -80,17 +81,23 @@ int cli_message_text_build(struct cli_state *cli, char *msg, int len, int grp) cli_setup_packet(cli); SSVAL(cli->outbuf,smb_vwv0,grp); - + p = smb_buf(cli->outbuf); *p++ = 1; if ((lendos = (int)convert_string_allocate(NULL,CH_UNIX, CH_DOS, msg,len, (void **)(void *)&msgdos, True)) < 0 || !msgdos) { DEBUG(3,("Conversion failed, sending message in UNIX charset\n")); SSVAL(p, 0, len); p += 2; + if (len > cli->bufsize - PTR_DIFF(p,cli->outbuf)) { + return -1; + } memcpy(p, msg, len); p += len; } else { SSVAL(p, 0, lendos); p += 2; + if (lendos > cli->bufsize - PTR_DIFF(p,cli->outbuf)) { + return -1; + } memcpy(p, msgdos, lendos); p += lendos; SAFE_FREE(msgdos); @@ -101,7 +108,7 @@ int cli_message_text_build(struct cli_state *cli, char *msg, int len, int grp) return(PTR_DIFF(p, cli->outbuf)); } -bool cli_message_text(struct cli_state *cli, char *msg, int len, int grp) +bool cli_message_text(struct cli_state *cli, const char *msg, int len, int grp) { cli_message_text_build(cli, msg, len, grp); @@ -114,11 +121,12 @@ bool cli_message_text(struct cli_state *cli, char *msg, int len, int grp) if (cli_is_error(cli)) return False; return True; -} +} /**************************************************************************** -end a message + End a message. ****************************************************************************/ + int cli_message_end_build(struct cli_state *cli, int grp) { char *p; @@ -150,4 +158,4 @@ bool cli_message_end(struct cli_state *cli, int grp) if (cli_is_error(cli)) return False; return True; -} +} diff --git a/source3/libsmb/clistr.c b/source3/libsmb/clistr.c index 39315729c4..5d20d632aa 100644 --- a/source3/libsmb/clistr.c +++ b/source3/libsmb/clistr.c @@ -20,9 +20,13 @@ #include "includes.h" -size_t clistr_push_fn(const char *function, unsigned int line, - struct cli_state *cli, void *dest, - const char *src, int dest_len, int flags) +size_t clistr_push_fn(const char *function, + unsigned int line, + struct cli_state *cli, + void *dest, + const char *src, + int dest_len, + int flags) { size_t buf_used = PTR_DIFF(dest, cli->outbuf); if (dest_len == -1) { @@ -38,23 +42,46 @@ size_t clistr_push_fn(const char *function, unsigned int line, dest, src, cli->bufsize - buf_used, flags); } - + /* 'normal' push into size-specified buffer */ return push_string_fn(function, line, cli->outbuf, SVAL(cli->outbuf, smb_flg2), dest, src, dest_len, flags); } -size_t clistr_pull_fn(const char *function, unsigned int line, - struct cli_state *cli, char *dest, const void *src, - int dest_len, int src_len, - int flags) +size_t clistr_pull_fn(const char *function, + unsigned int line, + struct cli_state *cli, + char *dest, + const void *src, + int dest_len, + int src_len, + int flags) { return pull_string_fn(function, line, cli->inbuf, SVAL(cli->inbuf, smb_flg2), dest, src, dest_len, src_len, flags); } +size_t clistr_pull_talloc_fn(const char *function, + unsigned int line, + TALLOC_CTX *ctx, + struct cli_state *cli, + char **pp_dest, + const void *src, + int src_len, + int flags) +{ + return pull_string_talloc_fn(function, + line, + ctx, + cli->inbuf, + SVAL(cli->inbuf, smb_flg2), + pp_dest, + src, + src_len, + flags); +} size_t clistr_align_out(struct cli_state *cli, const void *p, int flags) { |