/** * Initialize a key in the registry: * create each component key of the specified path. */ static WERROR init_registry_key_internal(struct db_context *db, const char *add_path) { char *subkey, *key; WERROR werr; TALLOC_CTX *frame = talloc_stackframe(); if (add_path == NULL) { werr = WERR_INVALID_PARAM; goto done; } key = talloc_strdup(frame, add_path); subkey = strrchr_m(key, '\\'); if (subkey == NULL) { subkey = key; key = NULL; } else { *subkey = '\0'; subkey++; } werr = create_key_recursive(db, key, subkey); done: talloc_free(frame); return werr; }
/* ************************************************************************** ** * get ready for syslog stuff * ************************************************************************** ** */ void setup_logging(const char *pname, BOOL interactive) { debug_init(); /* reset to allow multiple setup calls, going from interactive to non-interactive */ stdout_logging = False; dbf = NULL; if (interactive) { stdout_logging = True; dbf = x_stdout; x_setbuf( x_stdout, NULL ); } #ifdef WITH_SYSLOG else { const char *p = strrchr_m( pname,'/' ); if (p) pname = p + 1; #ifdef LOG_DAEMON openlog( pname, LOG_PID, SYSLOG_FACILITY ); #else /* for old systems that have no facility codes. */ openlog( pname, LOG_PID ); #endif } #endif } /* setup_logging */
/** * Given a stream name, populate xattr_name with the xattr name to use for * accessing the stream. */ static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx, const char *stream_name, char **xattr_name) { char *stype; stype = strchr_m(stream_name + 1, ':'); *xattr_name = talloc_asprintf(ctx, "%s%s", SAMBA_XATTR_DOSSTREAM_PREFIX, stream_name + 1); if (*xattr_name == NULL) { return NT_STATUS_NO_MEMORY; } if (stype == NULL) { /* Append an explicit stream type if one wasn't specified. */ *xattr_name = talloc_asprintf(ctx, "%s:$DATA", *xattr_name); if (*xattr_name == NULL) { return NT_STATUS_NO_MEMORY; } } else { /* Normalize the stream type to upercase. */ strupper_m(strrchr_m(*xattr_name, ':') + 1); } DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name, stream_name)); return NT_STATUS_OK; }
static WERROR create_key_recursive(struct db_context *db, char *path, const char *subkey) { WERROR werr; char *p; if (subkey == NULL) { return WERR_INVALID_PARAM; } if (path == NULL) { return regdb_create_basekey(db, subkey); } p = strrchr_m(path, '\\'); if (p == NULL) { werr = create_key_recursive(db, NULL, path); } else { *p = '\0'; werr = create_key_recursive(db, path, p+1); *p = '\\'; } if (!W_ERROR_IS_OK(werr)) { goto done; } werr = regdb_create_subkey_internal(db, path, subkey); done: return werr; }
static char *clean_path(TALLOC_CTX *ctx, const char *path) { size_t len; char *p1, *p2, *p; char *path_out; /* No absolute paths. */ while (IS_DIRECTORY_SEP(*path)) { path++; } path_out = talloc_strdup(ctx, path); if (!path_out) { return NULL; } p1 = strchr_m(path_out, '*'); p2 = strchr_m(path_out, '?'); if (p1 || p2) { if (p1 && p2) { p = MIN(p1,p2); } else if (!p1) { p = p2; } else { p = p1; } *p = '\0'; /* Now go back to the start of this component. */ p1 = strrchr_m(path_out, '/'); p2 = strrchr_m(path_out, '\\'); p = MAX(p1,p2); if (p) { *p = '\0'; } } /* Strip any trailing separator */ len = strlen(path_out); if ( (len > 0) && IS_DIRECTORY_SEP(path_out[len-1])) { path_out[len-1] = '\0'; } return path_out; }
static void check_magic(files_struct *fsp,connection_struct *conn) { if (!*lp_magicscript(SNUM(conn))) return; DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); { char *p; if (!(p = strrchr_m(fsp->fsp_name,'/'))) p = fsp->fsp_name; else p++; if (!strequal(lp_magicscript(SNUM(conn)),p)) return; } { int ret; pstring magic_output; pstring fname; SMB_STRUCT_STAT st; int tmp_fd, outfd; pstrcpy(fname,fsp->fsp_name); if (*lp_magicoutput(SNUM(conn))) pstrcpy(magic_output,lp_magicoutput(SNUM(conn))); else slprintf(magic_output,sizeof(fname)-1, "%s.out",fname); chmod(fname,0755); ret = smbrun(fname,&tmp_fd); DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); unlink(fname); if (ret != 0 || tmp_fd == -1) { if (tmp_fd != -1) close(tmp_fd); return; } outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); if (outfd == -1) { close(tmp_fd); return; } if (sys_fstat(tmp_fd,&st) == -1) { close(tmp_fd); close(outfd); return; } transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size); close(tmp_fd); close(outfd); } }
void dump_core_setup(const char *progname) { pstring logbase; char * end; if (lp_logfile() && *lp_logfile()) { snprintf(logbase, sizeof(logbase), "%s", lp_logfile()); if ((end = strrchr_m(logbase, '/'))) { *end = '\0'; } } else { /* We will end up here is the log file is given on the command * line by the -l option but the "log file" option is not set * in smb.conf. */ snprintf(logbase, sizeof(logbase), "%s", dyn_LOGFILEBASE); } SMB_ASSERT(progname != NULL); snprintf(corepath, sizeof(corepath), "%s/cores", logbase); mkdir(corepath,0700); snprintf(corepath, sizeof(corepath), "%s/cores/%s", logbase, progname); mkdir(corepath,0700); sys_chown(corepath,getuid(),getgid()); chmod(corepath,0700); #ifdef HAVE_GETRLIMIT #ifdef RLIMIT_CORE { struct rlimit rlp; getrlimit(RLIMIT_CORE, &rlp); rlp.rlim_cur = MAX(16*1024*1024,rlp.rlim_cur); setrlimit(RLIMIT_CORE, &rlp); getrlimit(RLIMIT_CORE, &rlp); DEBUG(3,("Maximum core file size limits now %d(soft) %d(hard)\n", (int)rlp.rlim_cur,(int)rlp.rlim_max)); } #endif #endif #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) /* On Linux we lose the ability to dump core when we change our user * ID. We know how to dump core safely, so let's make sure we have our * dumpable flag set. */ prctl(PR_SET_DUMPABLE, 1); #endif /* FIXME: if we have a core-plus-pid facility, configurably set * this up here. */ }
static struct tdb_wrap_private *tdb_wrap_private_open(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode) { struct tdb_wrap_private *result; result = talloc(mem_ctx, struct tdb_wrap_private); if (result == NULL) { return NULL; } result->name = talloc_strdup(result, name); if (result->name == NULL) { goto fail; } #if _SAMBA_BUILD_ == 3 /* This #if _SAMBA_BUILD == 3 is very unfortunate, as it means * that in the top level build, these options are not * available for these databases. However, having two * different tdb_wrap lists is a worse fate, so this will do * for now */ if (!lp_use_mmap()) { tdb_flags |= TDB_NOMMAP; } if ((hash_size == 0) && (name != NULL)) { const char *base; base = strrchr_m(name, '/'); if (base != NULL) { base += 1; } else { base = name; } hash_size = lp_parm_int(-1, "tdb_hashsize", base, 0); } #endif result->tdb = tdb_open_compat(name, hash_size, tdb_flags, open_flags, mode, tdb_wrap_log, NULL); if (result->tdb == NULL) { goto fail; } talloc_set_destructor(result, tdb_wrap_private_destructor); DLIST_ADD(tdb_list, result); return result; fail: TALLOC_FREE(result); return NULL; }
uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) { uint32 result = 0; DEBUG(8,("dos_mode: %s\n", path)); if (!VALID_STAT(*sbuf)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { const char *p = strrchr_m(path,'/'); if (p) { p++; } else { p = path; } if (p[0] == '.' && p[1] != '.' && p[1] != 0) { result |= aHIDDEN; } } /* Get the DOS attributes from an EA by preference. */ if (get_ea_dos_attribute(conn, path, sbuf, &result)) { result |= set_sparse_flag(sbuf); } else { result |= dos_mode_from_sbuf(conn, path, sbuf); } if (S_ISREG(sbuf->st_mode)) { result |= set_offline_flag(conn, path); } /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { result |= aHIDDEN; } DEBUG(8,("dos_mode returning ")); if (result & aHIDDEN) DEBUG(8, ("h")); if (result & aRONLY ) DEBUG(8, ("r")); if (result & aSYSTEM) DEBUG(8, ("s")); if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); return(result); }
NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx, const struct smb_filename *smb_fname_in, struct smb_filename **smb_fname_out) { char *stream_name = NULL; NTSTATUS status; /* * Only attempt to strip off the trailing :$DATA if there is an actual * stream there. If it is the default stream, the smb_fname_out will * just have a NULL stream so the base file is opened. */ if (smb_fname_in->stream_name && !is_ntfs_default_stream_smb_fname(smb_fname_in)) { char *str_tmp = smb_fname_in->stream_name; /* First strip off the leading ':' */ if (str_tmp[0] == ':') { str_tmp++; } /* Create a new copy of the stream_name. */ stream_name = talloc_strdup(ctx, str_tmp); if (stream_name == NULL) { return NT_STATUS_NO_MEMORY; } /* Strip off the :$DATA if one exists. */ str_tmp = strrchr_m(stream_name, ':'); if (str_tmp) { if (strcasecmp_m(str_tmp, ":$DATA") != 0) { return NT_STATUS_INVALID_PARAMETER; } str_tmp[0] = '\0'; } } /* * If there was a stream that wasn't the default stream the leading * colon and trailing :$DATA has now been stripped off. Create a new * smb_filename to pass back. */ status = create_synthetic_smb_fname(ctx, smb_fname_in->base_name, stream_name, &smb_fname_in->st, smb_fname_out); TALLOC_FREE(stream_name); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("Failed to prep stream name for %s: %s\n", *smb_fname_out ? smb_fname_str_dbg(*smb_fname_out) : "NULL", nt_errstr(status))); } return status; }
static void clean_path(const char *path, pstring path_out) { size_t len; char *p1, *p2, *p; /* No absolute paths. */ while (IS_DIRECTORY_SEP(*path)) { path++; } pstrcpy(path_out, path); p1 = strchr_m(path_out, '*'); p2 = strchr_m(path_out, '?'); if (p1 || p2) { if (p1 && p2) { p = MIN(p1,p2); } else if (!p1) { p = p2; } else { p = p1; } *p = '\0'; /* Now go back to the start of this component. */ p1 = strrchr_m(path_out, '/'); p2 = strrchr_m(path_out, '\\'); p = MAX(p1,p2); if (p) { *p = '\0'; } } /* Strip any trailing separator */ len = strlen(path_out); if ( (len > 0) && IS_DIRECTORY_SEP(path_out[len-1])) { path_out[len-1] = '\0'; } }
/******************************************************************* return True if the filename is one of the special executable types ********************************************************************/ static BOOL is_executable(const char *fname) { if ((fname = strrchr_m(fname,'.'))) { if (strequal(fname,".com") || strequal(fname,".dll") || strequal(fname,".exe") || strequal(fname,".sym")) { return True; } } return False; }
static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, NETDFS_DFS_INFO3* dfs3) { int ii; pstring str; dfs3->ptr0_path = 1; if (j->volume_name[0] == '\0') slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s", global_myname(), j->service_name); else slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(), j->service_name, j->volume_name); init_unistr2(&dfs3->path, str, UNI_STR_TERMINATE); dfs3->ptr0_comment = 1; init_unistr2(&dfs3->comment, j->comment, UNI_STR_TERMINATE); dfs3->state = 1; dfs3->num_stores = dfs3->size_stores = j->referral_count; /* also enumerate the stores */ if (j->referral_count) { dfs3->stores = TALLOC_ARRAY(ctx, NETDFS_DFS_STORAGEINFO, j->referral_count); if (!dfs3->stores) return False; memset(dfs3->stores, '\0', j->referral_count * sizeof(NETDFS_DFS_STORAGEINFO)); dfs3->ptr0_stores = 1; } else { dfs3->stores = NULL; dfs3->ptr0_stores = 0; } for(ii=0;ii<j->referral_count;ii++) { char* p; pstring path; NETDFS_DFS_STORAGEINFO* stor = &(dfs3->stores[ii]); struct referral* ref = &(j->referral_list[ii]); pstrcpy(path, ref->alternate_path); trim_char(path,'\\','\0'); p = strrchr_m(path,'\\'); if(p==NULL) { DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path)); continue; } *p = '\0'; DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1)); stor->state = 2; /* set all stores as ONLINE */ init_unistr2(&stor->server, path, UNI_STR_TERMINATE); init_unistr2(&stor->share, p+1, UNI_STR_TERMINATE); stor->ptr0_server = stor->ptr0_share = 1; } return True; }
uint32_t dos_mode_msdfs(connection_struct *conn, const struct smb_filename *smb_fname) { uint32_t result = 0; DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname))); if (!VALID_STAT(smb_fname->st)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { const char *p = strrchr_m(smb_fname->base_name, '/'); if (p) { p++; } else { p = smb_fname->base_name; } /* Only . and .. are not hidden. */ if (p[0] == '.' && !((p[1] == '\0') || (p[1] == '.' && p[2] == '\0'))) { result |= FILE_ATTRIBUTE_HIDDEN; } } result |= dos_mode_from_sbuf(conn, smb_fname); /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & FILE_ATTRIBUTE_HIDDEN) && IS_HIDDEN_PATH(conn, smb_fname->base_name)) { result |= FILE_ATTRIBUTE_HIDDEN; } if (result == 0) { result = FILE_ATTRIBUTE_NORMAL; } result = filter_mode_by_protocol(result); /* * Add in that it is a reparse point */ result |= FILE_ATTRIBUTE_REPARSE_POINT; dos_mode_debug_print(__func__, result); return(result); }
static struct tdb_wrap_private *tdb_wrap_private_open(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, struct loadparm_context *lp_ctx) { struct tdb_wrap_private *result; struct tdb_logging_context lctx; result = talloc(mem_ctx, struct tdb_wrap_private); if (result == NULL) { return NULL; } result->name = talloc_strdup(result, name); if (result->name == NULL) { goto fail; } if (!lpcfg_use_mmap(lp_ctx)) { tdb_flags |= TDB_NOMMAP; } if ((hash_size == 0) && (name != NULL)) { const char *base; base = strrchr_m(name, '/'); if (base != NULL) { base += 1; } else { base = name; } hash_size = lpcfg_parm_int(lp_ctx, NULL, "tdb_hashsize", base, 0); } lctx.log_fn = tdb_wrap_log; lctx.log_private = NULL; result->tdb = tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, &lctx, NULL); if (result->tdb == NULL) { goto fail; } talloc_set_destructor(result, tdb_wrap_private_destructor); DLIST_ADD(tdb_list, result); return result; fail: TALLOC_FREE(result); return NULL; }
static char *reg_test(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *pattern, const char *long_name, const char *short_name) { char *ret; ret = talloc_strdup(mem_ctx, "---"); pattern = 1+strrchr_m(pattern,'\\'); if (reg_match_one(cli, pattern, ".")) ret[0] = '+'; if (reg_match_one(cli, pattern, "..")) ret[1] = '+'; if (reg_match_one(cli, pattern, long_name) || (*short_name && reg_match_one(cli, pattern, short_name))) ret[2] = '+'; return ret; }
static BOOL ensurepath(char *fname) { /* *must* be called with buffer ready malloc'ed */ /* ensures path exists */ char *partpath, *ffname; char *p=fname, *basehack; DEBUG(5, ( "Ensurepath called with: %s\n", fname)); partpath = string_create_s(strlen(fname)); ffname = string_create_s(strlen(fname)); if ((partpath == NULL) || (ffname == NULL)){ DEBUG(0, ("Out of memory in ensurepath: %s\n", fname)); return(False); } *partpath = 0; /* fname copied to ffname so can strtok */ safe_strcpy(ffname, fname, strlen(fname)); /* do a `basename' on ffname, so don't try and make file name directory */ if ((basehack=strrchr_m(ffname, '\\')) == NULL) return True; else *basehack='\0'; p=strtok(ffname, "\\"); while (p) { safe_strcat(partpath, p, strlen(fname) + 1); if (!cli_chkpath(cli, partpath)) { if (!cli_mkdir(cli, partpath)) { DEBUG(0, ("Error mkdirhiering\n")); return False; } else { DEBUG(3, ("mkdirhiering %s\n", partpath)); } } safe_strcat(partpath, "\\", strlen(fname) + 1); p = strtok(NULL,"/\\"); } return True; }
static void clean_path( pstring clean, const char *path ) { int len; char *p; pstring newpath; pstrcpy( newpath, path ); p = newpath; while ( p ) { /* first check for '*' */ p = strrchr_m( newpath, '*' ); if ( p ) { *p = '\0'; p = newpath; continue; } /* first check for '?' */ p = strrchr_m( newpath, '?' ); if ( p ) { *p = '\0'; p = newpath; } } /* strip a trailing backslash */ len = strlen( newpath ); if ( newpath[len-1] == '\\' ) newpath[len-1] = '\0'; pstrcpy( clean, newpath ); }
static int generic_job_submit(int snum, struct printjob *pjob) { int ret; pstring current_directory; pstring print_directory; char *wd, *p; pstring jobname; fstring job_page_count, job_size; /* we print from the directory path to give the best chance of parsing the lpq output */ wd = sys_getwd(current_directory); if (!wd) return 0; pstrcpy(print_directory, pjob->filename); p = strrchr_m(print_directory,'/'); if (!p) return 0; *p++ = 0; if (chdir(print_directory) != 0) return 0; pstrcpy(jobname, pjob->jobname); pstring_sub(jobname, "'", "_"); slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count); slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size); /* send it to the system spooler */ ret = print_run_command(snum, PRINTERNAME(snum), True, lp_printcommand(snum), NULL, "%s", p, "%J", jobname, "%f", p, "%z", job_size, "%c", job_page_count, NULL); chdir(wd); return ret; }
static void set_logfile(poptContext con, const char * arg) { char *lfile = NULL; const char *pname; /* Find out basename of current program */ pname = strrchr_m(poptGetInvocationName(con),'/'); if (!pname) pname = poptGetInvocationName(con); else pname++; if (asprintf(&lfile, "%s/log.%s", arg, pname) < 0) { return; } lp_set_logfile(lfile); SAFE_FREE(lfile); }
static void split_dfs_path( const char *nodepath, fstring server, fstring share ) { char *p; pstring path; pstrcpy( path, nodepath ); if ( path[0] != '\\' ) return; p = strrchr_m( path, '\\' ); if ( !p ) return; *p = '\0'; p++; fstrcpy( share, p ); fstrcpy( server, &path[1] ); }
static void set_logfile(poptContext con, const char * arg) { pstring logfile; const char *pname; /* Find out basename of current program */ pname = strrchr_m(poptGetInvocationName(con),'/'); if (!pname) pname = poptGetInvocationName(con); else pname++; #ifdef EMBED pstr_sprintf(logfile, "%s/smb_log.%s", arg, pname); #else pstr_sprintf(logfile, "%s/log.%s", arg, pname); #endif lp_set_logfile(logfile); }
uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname) { uint32 result = 0; bool offline; DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname))); if (!VALID_STAT(smb_fname->st)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { const char *p = strrchr_m(smb_fname->base_name,'/'); if (p) { p++; } else { p = smb_fname->base_name; } /* Only . and .. are not hidden. */ if (p[0] == '.' && !((p[1] == '\0') || (p[1] == '.' && p[2] == '\0'))) { result |= FILE_ATTRIBUTE_HIDDEN; } } /* Get the DOS attributes from an EA by preference. */ if (!get_ea_dos_attribute(conn, smb_fname, &result)) { result |= dos_mode_from_sbuf(conn, smb_fname); } offline = SMB_VFS_IS_OFFLINE(conn, smb_fname, &smb_fname->st); if (S_ISREG(smb_fname->st.st_ex_mode) && offline) { result |= FILE_ATTRIBUTE_OFFLINE; } if (conn->fs_capabilities & FILE_FILE_COMPRESSION) { bool compressed = false; NTSTATUS status = dos_mode_check_compressed(conn, smb_fname, &compressed); if (NT_STATUS_IS_OK(status) && compressed) { result |= FILE_ATTRIBUTE_COMPRESSED; } } /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & FILE_ATTRIBUTE_HIDDEN) && IS_HIDDEN_PATH(conn, smb_fname->base_name)) { result |= FILE_ATTRIBUTE_HIDDEN; } if (result == 0) { result = FILE_ATTRIBUTE_NORMAL; } result = filter_mode_by_protocol(result); dos_mode_debug_print(result); return result; }
static bool get_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32 *pattr) { struct xattr_DOSATTRIB dosattrib; enum ndr_err_code ndr_err; DATA_BLOB blob; ssize_t sizeret; fstring attrstr; uint32_t dosattr; if (!lp_store_dos_attributes(SNUM(conn))) { return False; } /* Don't reset pattr to zero as we may already have filename-based attributes we need to preserve. */ sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); if (sizeret == -1) { if (errno == ENOSYS #if defined(ENOTSUP) || errno == ENOTSUP) { #else ) { #endif DEBUG(1,("get_ea_dos_attribute: Cannot get attribute " "from EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno))); set_store_dos_attributes(SNUM(conn), False); } return False; } blob.data = (uint8_t *)attrstr; blob.length = sizeret; ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib, (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(1,("get_ea_dos_attribute: bad ndr decode " "from EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), ndr_errstr(ndr_err))); return false; } DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n", smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex)); switch (dosattrib.version) { case 0xFFFF: dosattr = dosattrib.info.compatinfoFFFF.attrib; break; case 1: dosattr = dosattrib.info.info1.attrib; if (!null_nttime(dosattrib.info.info1.create_time)) { struct timespec create_time = nt_time_to_unix_timespec( dosattrib.info.info1.create_time); update_stat_ex_create_time(&smb_fname->st, create_time); DEBUG(10,("get_ea_dos_attribute: file %s case 1 " "set btime %s\n", smb_fname_str_dbg(smb_fname), time_to_asc(convert_timespec_to_time_t( create_time)) )); } break; case 2: dosattr = dosattrib.info.oldinfo2.attrib; /* Don't know what flags to check for this case. */ break; case 3: dosattr = dosattrib.info.info3.attrib; if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) && !null_nttime(dosattrib.info.info3.create_time)) { struct timespec create_time = nt_time_to_unix_timespec( dosattrib.info.info3.create_time); update_stat_ex_create_time(&smb_fname->st, create_time); DEBUG(10,("get_ea_dos_attribute: file %s case 3 " "set btime %s\n", smb_fname_str_dbg(smb_fname), time_to_asc(convert_timespec_to_time_t( create_time)) )); } break; default: DEBUG(1,("get_ea_dos_attribute: Badly formed DOSATTRIB on " "file %s - %s\n", smb_fname_str_dbg(smb_fname), attrstr)); return false; } if (S_ISDIR(smb_fname->st.st_ex_mode)) { dosattr |= FILE_ATTRIBUTE_DIRECTORY; } /* FILE_ATTRIBUTE_SPARSE is valid on get but not on set. */ *pattr = (uint32)(dosattr & (SAMBA_ATTRIBUTES_MASK|FILE_ATTRIBUTE_SPARSE)); DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr)); if (dosattr & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); if (dosattr & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); if (dosattr & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); if (dosattr & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); if (dosattr & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); DEBUG(8,("\n")); return True; } /**************************************************************************** Set DOS attributes in an EA. Also sets the create time. ****************************************************************************/ static bool set_ea_dos_attribute(connection_struct *conn, struct smb_filename *smb_fname, uint32 dosmode) { struct xattr_DOSATTRIB dosattrib; enum ndr_err_code ndr_err; DATA_BLOB blob; ZERO_STRUCT(dosattrib); ZERO_STRUCT(blob); dosattrib.version = 3; dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB| XATTR_DOSINFO_CREATE_TIME; dosattrib.info.info3.attrib = dosmode; dosattrib.info.info3.create_time = unix_timespec_to_nt_time( smb_fname->st.st_ex_btime); DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n", (unsigned int)dosmode, time_to_asc(convert_timespec_to_time_t(smb_fname->st.st_ex_btime)), smb_fname_str_dbg(smb_fname) )); ndr_err = ndr_push_struct_blob( &blob, talloc_tos(), &dosattrib, (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n", ndr_errstr(ndr_err))); return false; } if (blob.data == NULL || blob.length == 0) { return false; } if (SMB_VFS_SETXATTR(conn, smb_fname->base_name, SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length, 0) == -1) { bool ret = false; bool need_close = false; files_struct *fsp = NULL; if((errno != EPERM) && (errno != EACCES)) { if (errno == ENOSYS #if defined(ENOTSUP) || errno == ENOTSUP) { #else ) { #endif DEBUG(1,("set_ea_dos_attributes: Cannot set " "attribute EA on file %s: Error = %s\n", smb_fname_str_dbg(smb_fname), strerror(errno) )); set_store_dos_attributes(SNUM(conn), False); } return false; } /* We want DOS semantics, ie allow non owner with write permission to change the bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) return false; if (!can_write_to_file(conn, smb_fname)) { return false; } /* * We need to get an open file handle to do the * metadata operation under root. */ if (!NT_STATUS_IS_OK(get_file_handle_for_metadata(conn, smb_fname, &fsp, &need_close))) { return false; } become_root(); if (SMB_VFS_FSETXATTR(fsp, SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length, 0) == 0) { ret = true; } unbecome_root(); if (need_close) { close_file(NULL, fsp, NORMAL_CLOSE); } return ret; } DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n", (unsigned int)dosmode, smb_fname_str_dbg(smb_fname))); return true; } /**************************************************************************** Change a unix mode to a dos mode for an ms dfs link. ****************************************************************************/ uint32 dos_mode_msdfs(connection_struct *conn, const struct smb_filename *smb_fname) { uint32 result = 0; DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname))); if (!VALID_STAT(smb_fname->st)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { const char *p = strrchr_m(smb_fname->base_name, '/'); if (p) { p++; } else { p = smb_fname->base_name; } /* Only . and .. are not hidden. */ if (p[0] == '.' && !((p[1] == '\0') || (p[1] == '.' && p[2] == '\0'))) { result |= FILE_ATTRIBUTE_HIDDEN; } } result |= dos_mode_from_sbuf(conn, smb_fname); /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & FILE_ATTRIBUTE_HIDDEN) && IS_HIDDEN_PATH(conn, smb_fname->base_name)) { result |= FILE_ATTRIBUTE_HIDDEN; } if (result == 0) { result = FILE_ATTRIBUTE_NORMAL; } result = filter_mode_by_protocol(result); /* * Add in that it is a reparse point */ result |= FILE_ATTRIBUTE_REPARSE_POINT; DEBUG(8,("dos_mode_msdfs returning ")); if (result & FILE_ATTRIBUTE_HIDDEN) DEBUG(8, ("h")); if (result & FILE_ATTRIBUTE_READONLY ) DEBUG(8, ("r")); if (result & FILE_ATTRIBUTE_SYSTEM) DEBUG(8, ("s")); if (result & FILE_ATTRIBUTE_DIRECTORY ) DEBUG(8, ("d")); if (result & FILE_ATTRIBUTE_ARCHIVE ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); return(result); }
static int generic_job_submit(int snum, struct printjob *pjob, enum printing_types printing_type, char *lpq_cmd) { int ret = -1; char *current_directory = NULL; char *print_directory = NULL; char *wd = NULL; char *p = NULL; char *jobname = NULL; TALLOC_CTX *ctx = talloc_tos(); fstring job_page_count, job_size; print_queue_struct *q; print_status_struct status; /* we print from the directory path to give the best chance of parsing the lpq output */ wd = sys_getwd(); if (!wd) { return -1; } current_directory = talloc_strdup(ctx, wd); SAFE_FREE(wd); if (!current_directory) { return -1; } print_directory = talloc_strdup(ctx, pjob->filename); if (!print_directory) { return -1; } p = strrchr_m(print_directory,'/'); if (!p) { return -1; } *p++ = 0; if (chdir(print_directory) != 0) { return -1; } jobname = talloc_strdup(ctx, pjob->jobname); if (!jobname) { ret = -1; goto out; } jobname = talloc_string_sub(ctx, jobname, "'", "_"); if (!jobname) { ret = -1; goto out; } slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count); slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size); /* send it to the system spooler */ ret = print_run_command(snum, lp_printername(talloc_tos(), snum), True, lp_print_command(talloc_tos(), snum), NULL, "%s", p, "%J", jobname, "%f", p, "%z", job_size, "%c", job_page_count, NULL); if (ret != 0) { ret = -1; goto out; } /* * check the queue for the newly submitted job, this allows us to * determine the backend job identifier (sysjob). */ pjob->sysjob = -1; ret = generic_queue_get(lp_printername(talloc_tos(), snum), printing_type, lpq_cmd, &q, &status); if (ret > 0) { int i; for (i = 0; i < ret; i++) { if (strcmp(q[i].fs_file, p) == 0) { pjob->sysjob = q[i].sysjob; DEBUG(5, ("new job %u (%s) matches sysjob %d\n", pjob->jobid, jobname, pjob->sysjob)); break; } } SAFE_FREE(q); ret = 0; } if (pjob->sysjob == -1) { DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as " "Unix job\n", pjob->jobid, jobname)); } out: if (chdir(current_directory) == -1) { smb_panic("chdir failed in generic_job_submit"); } TALLOC_FREE(current_directory); return ret; }
static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode) { fstring attrstr; files_struct *fsp = NULL; BOOL ret = False; if (!lp_store_dos_attributes(SNUM(conn))) { return False; } snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK); if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) { if((errno != EPERM) && (errno != EACCES)) { if (errno == ENOSYS #if defined(ENOTSUP) || errno == ENOTSUP) { #else ) { #endif set_store_dos_attributes(SNUM(conn), False); } return False; } /* We want DOS semantics, ie allow non owner with write permission to change the bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) return False; /* * We need to open the file with write access whilst * still in our current user context. This ensures we * are not violating security in doing the setxattr. */ if (!NT_STATUS_IS_OK(open_file_fchmod(conn,path,sbuf,&fsp))) return ret; become_root(); if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) { ret = True; } unbecome_root(); close_file_fchmod(fsp); return ret; } DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path)); return True; } /**************************************************************************** Change a unix mode to a dos mode for an ms dfs link. ****************************************************************************/ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) { uint32 result = 0; DEBUG(8,("dos_mode_msdfs: %s\n", path)); if (!VALID_STAT(*sbuf)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { const char *p = strrchr_m(path,'/'); if (p) { p++; } else { p = path; } if (p[0] == '.' && p[1] != '.' && p[1] != 0) { result |= aHIDDEN; } } result |= dos_mode_from_sbuf(conn, path, sbuf); /* Optimization : Only call is_hidden_path if it's not already hidden. */ if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { result |= aHIDDEN; } DEBUG(8,("dos_mode_msdfs returning ")); if (result & aHIDDEN) DEBUG(8, ("h")); if (result & aRONLY ) DEBUG(8, ("r")); if (result & aSYSTEM) DEBUG(8, ("s")); if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); DEBUG(8,("\n")); return(result); }
static int generic_job_submit(int snum, struct printjob *pjob) { int ret = -1; char *current_directory = NULL; char *print_directory = NULL; char *wd = NULL; char *p = NULL; char *jobname = NULL; TALLOC_CTX *ctx = talloc_tos(); fstring job_page_count, job_size; /* we print from the directory path to give the best chance of parsing the lpq output */ wd = sys_getwd(); if (!wd) { return -1; } current_directory = talloc_strdup(ctx, wd); SAFE_FREE(wd); if (!current_directory) { return -1; } print_directory = talloc_strdup(ctx, pjob->filename); if (!print_directory) { return -1; } p = strrchr_m(print_directory,'/'); if (!p) { return -1; } *p++ = 0; if (chdir(print_directory) != 0) { return -1; } jobname = talloc_strdup(ctx, pjob->jobname); if (!jobname) { ret = -1; goto out; } jobname = talloc_string_sub(ctx, jobname, "'", "_"); if (!jobname) { ret = -1; goto out; } slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count); slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size); /* send it to the system spooler */ ret = print_run_command(snum, lp_printername(snum), True, lp_printcommand(snum), NULL, "%s", p, "%J", jobname, "%f", p, "%z", job_size, "%c", job_page_count, NULL); out: if (chdir(current_directory) == -1) { smb_panic("chdir failed in generic_job_submit"); } TALLOC_FREE(current_directory); return ret; }
static NTSTATUS check_magic(struct files_struct *fsp) { int ret; const char *magic_output = NULL; SMB_STRUCT_STAT st; int tmp_fd, outfd; TALLOC_CTX *ctx = NULL; const char *p; struct connection_struct *conn = fsp->conn; char *fname = NULL; NTSTATUS status; if (!*lp_magic_script(talloc_tos(), SNUM(conn))) { return NT_STATUS_OK; } DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp))); ctx = talloc_stackframe(); fname = fsp->fsp_name->base_name; if (!(p = strrchr_m(fname,'/'))) { p = fname; } else { p++; } if (!strequal(lp_magic_script(talloc_tos(), SNUM(conn)),p)) { status = NT_STATUS_OK; goto out; } if (*lp_magic_output(talloc_tos(), SNUM(conn))) { magic_output = lp_magic_output(talloc_tos(), SNUM(conn)); } else { magic_output = talloc_asprintf(ctx, "%s.out", fname); } if (!magic_output) { status = NT_STATUS_NO_MEMORY; goto out; } /* Ensure we don't depend on user's PATH. */ p = talloc_asprintf(ctx, "./%s", fname); if (!p) { status = NT_STATUS_NO_MEMORY; goto out; } if (chmod(fname, 0755) == -1) { status = map_nt_error_from_unix(errno); goto out; } ret = smbrun(p,&tmp_fd); DEBUG(3,("Invoking magic command %s gave %d\n", p,ret)); unlink(fname); if (ret != 0 || tmp_fd == -1) { if (tmp_fd != -1) { close(tmp_fd); } status = NT_STATUS_UNSUCCESSFUL; goto out; } outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); if (outfd == -1) { int err = errno; close(tmp_fd); status = map_nt_error_from_unix(err); goto out; } if (sys_fstat(tmp_fd, &st, false) == -1) { int err = errno; close(tmp_fd); close(outfd); status = map_nt_error_from_unix(err); goto out; } if (transfer_file(tmp_fd,outfd,(off_t)st.st_ex_size) == (off_t)-1) { int err = errno; close(tmp_fd); close(outfd); status = map_nt_error_from_unix(err); goto out; } close(tmp_fd); if (close(outfd) == -1) { status = map_nt_error_from_unix(errno); goto out; } status = NT_STATUS_OK; out: TALLOC_FREE(ctx); return status; }
/** * Given a stream name, populate xattr_name with the xattr name to use for * accessing the stream. */ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle, TALLOC_CTX *ctx, const char *stream_name, char **xattr_name) { char *sname; char *stype; struct streams_xattr_config *config; SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config, return NT_STATUS_UNSUCCESSFUL); sname = talloc_strdup(ctx, stream_name + 1); if (sname == NULL) { return NT_STATUS_NO_MEMORY; } /* * With vfs_fruit option "fruit:encoding = native" we're * already converting stream names that contain illegal NTFS * characters from their on-the-wire Unicode Private Range * encoding to their native ASCII representation. * * As as result the name of xattrs storing the streams (via * vfs_streams_xattr) may contain a colon, so we have to use * strrchr_m() instead of strchr_m() for matching the stream * type suffix. * * In check_path_syntax() we've already ensured the streamname * we got from the client is valid. */ stype = strrchr_m(sname, ':'); if (stype) { /* * We only support one stream type: "$DATA" */ if (strcasecmp_m(stype, ":$DATA") != 0) { talloc_free(sname); return NT_STATUS_INVALID_PARAMETER; } /* Split name and type */ stype[0] = '\0'; } *xattr_name = talloc_asprintf(ctx, "%s%s%s", config->prefix, sname, config->store_stream_type ? ":$DATA" : ""); if (*xattr_name == NULL) { talloc_free(sname); return NT_STATUS_NO_MEMORY; } DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name, stream_name)); talloc_free(sname); return NT_STATUS_OK; }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ int copies; /* Number of copies */ int port; /* Port number */ char uri[1024], /* URI */ *sep, /* Pointer to separator */ *password; /* Password */ const char *username, /* Username */ *server, /* Server name */ *printer; /* Printer name */ const char *workgroup; /* Workgroup */ FILE *fp; /* File to print */ int status=0; /* Status of LPD job */ struct cli_state *cli; /* SMB interface */ char null_str[1]; int tries = 0; const char *dev_uri; null_str[0] = '\0'; /* we expect the URI in argv[0]. Detect the case where it is in argv[1] and cope */ if (argc > 2 && strncmp(argv[0],"smb://", 6) && !strncmp(argv[1],"smb://", 6)) { argv++; argc--; } if (argc == 1) { /* * NEW! In CUPS 1.1 the backends are run with no arguments to list the * available devices. These can be devices served by this backend * or any other backends (i.e. you can have an SNMP backend that * is only used to enumerate the available network printers... :) */ list_devices(); return (0); } if (argc < 6 || argc > 7) { fprintf(stderr, "Usage: %s [DEVICE_URI] job-id user title copies options [file]\n", argv[0]); fputs(" The DEVICE_URI environment variable can also contain the\n", stderr); fputs(" destination printer:\n", stderr); fputs("\n", stderr); fputs(" smb://[username:password@][workgroup/]server[:port]/printer\n", stderr); return (1); } /* * If we have 7 arguments, print the file named on the command-line. * Otherwise, print data from stdin... */ if (argc == 6) { /* * Print from Copy stdin to a temporary file... */ fp = stdin; copies = 1; } else if ((fp = fopen(argv[6], "rb")) == NULL) { perror("ERROR: Unable to open print file"); return (1); } else copies = atoi(argv[4]); /* * Find the URI... */ dev_uri = getenv("DEVICE_URI"); if (dev_uri) strncpy(uri, dev_uri, sizeof(uri) - 1); else if (strncmp(argv[0], "smb://", 6) == 0) strncpy(uri, argv[0], sizeof(uri) - 1); else { fputs("ERROR: No device URI found in DEVICE_URI environment variable or argv[0] !\n", stderr); return (1); } uri[sizeof(uri) - 1] = '\0'; /* * Extract the destination from the URI... */ if ((sep = strrchr_m(uri, '@')) != NULL) { username = uri + 6; *sep++ = '\0'; server = sep; /* * Extract password as needed... */ if ((password = strchr_m(username, ':')) != NULL) *password++ = '\0'; else password = null_str; } else { username = null_str; password = null_str; server = uri + 6; } if ((sep = strchr_m(server, '/')) == NULL) { fputs("ERROR: Bad URI - need printer name!\n", stderr); return (1); } *sep++ = '\0'; printer = sep; if ((sep = strchr_m(printer, '/')) != NULL) { /* * Convert to smb://[username:password@]workgroup/server/printer... */ *sep++ = '\0'; workgroup = server; server = printer; printer = sep; } else workgroup = NULL; if ((sep = strrchr_m(server, ':')) != NULL) { *sep++ = '\0'; port=atoi(sep); } else port=0; /* * Setup the SAMBA server state... */ setup_logging("smbspool", True); in_client = True; /* Make sure that we tell lp_load we are */ load_case_tables(); if (!lp_load(dyn_CONFIGFILE, True, False, False, True)) { fprintf(stderr, "ERROR: Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE); return (1); } if (workgroup == NULL) workgroup = lp_workgroup(); load_interfaces(); do { if ((cli = smb_connect(workgroup, server, port, printer, username, password, argv[2])) == NULL) { if (getenv("CLASS") == NULL) { fprintf(stderr, "ERROR: Unable to connect to CIFS host, will retry in 60 seconds...\n"); sleep (60); /* should just waiting and retrying fix authentication ??? */ tries++; } else { fprintf(stderr, "ERROR: Unable to connect to CIFS host, trying next printer...\n"); return (1); } } } while ((cli == NULL) && (tries < MAX_RETRY_CONNECT)); if (cli == NULL) { fprintf(stderr, "ERROR: Unable to connect to CIFS host after (tried %d times)\n", tries); return (1); } /* * Now that we are connected to the server, ignore SIGTERM so that we * can finish out any page data the driver sends (e.g. to eject the * current page... Only ignore SIGTERM if we are printing data from * stdin (otherwise you can't cancel raw jobs...) */ if (argc < 7) CatchSignal(SIGTERM, SIG_IGN); /* * Queue the job... */ for (i = 0; i < copies; i ++) if ((status = smb_print(cli, argv[3] /* title */, fp)) != 0) break; cli_shutdown(cli); /* * Return the queue status... */ return (status); }