summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/client.h15
-rw-r--r--source3/include/proto.h7
-rw-r--r--source3/lib/util.c12
-rw-r--r--source3/libsmb/clientgen.c100
-rw-r--r--source3/smbd/trans2.c14
-rw-r--r--source3/smbwrapper/smbw.c3
-rw-r--r--source3/smbwrapper/smbw_dir.c36
-rw-r--r--source3/smbwrapper/smbw_stat.c46
8 files changed, 214 insertions, 19 deletions
diff --git a/source3/include/client.h b/source3/include/client.h
index 79fb96dad2..495780cbaa 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -25,8 +25,9 @@
#define _CLIENT_H
/* the client asks for a smaller buffer to save ram and also to get more
- overlap on the wire */
-#define CLI_BUFFER_SIZE (0x4000)
+ overlap on the wire. This size gives us a nice read/write size, which
+ will be a multiple of the page size on almost any system */
+#define CLI_BUFFER_SIZE (0x4400)
/*
* These definitions depend on smb.h
@@ -45,6 +46,16 @@ typedef struct file_info
pstring name;
} file_info;
+struct print_job_info
+{
+ uint16 id;
+ uint16 priority;
+ size_t size;
+ fstring user;
+ fstring name;
+ time_t t;
+};
+
struct pwd_info
{
BOOL null_pwd;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 78863b5984..29803cdbbc 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -321,6 +321,7 @@ struct hostent *Get_Hostbyname(char *name);
BOOL process_exists(int pid);
char *uidtoname(uid_t uid);
char *gidtoname(gid_t gid);
+uid_t nametouid(const char *name);
void smb_panic(char *why);
char *readdirname(void *p);
BOOL is_in_path(char *name, name_compare_entry *namelist);
@@ -417,6 +418,8 @@ BOOL cli_establish_connection(struct cli_state *cli,
struct nmb_name *calling, struct nmb_name *called,
char *service, char *service_type,
BOOL do_shutdown, BOOL do_tcon);
+int cli_print_queue(struct cli_state *cli,
+ void (*fn)(struct print_job_info *));
/*The following definitions come from libsmb/credentials.c */
@@ -2294,6 +2297,8 @@ int smbw_utime(const char *fname, void *buf);
int smbw_chown(const char *fname, uid_t owner, gid_t group);
int smbw_chmod(const char *fname, mode_t newmode);
off_t smbw_lseek(int fd, off_t offset, int whence);
+int smbw_dup(int fd);
+int smbw_dup2(int fd, int fd2);
/*The following definitions come from smbwrapper/smbw_dir.c */
@@ -2321,6 +2326,8 @@ void smbw_setup_stat(struct stat *st, char *fname, size_t size, int mode);
BOOL smbw_getatr(struct smbw_server *srv, char *path,
uint32 *mode, size_t *size,
time_t *c_time, time_t *a_time, time_t *m_time);
+int smbw_stat_printjob(struct smbw_server *srv,char *path,
+ size_t *size, time_t *m_time);
int smbw_fstat(int fd, struct stat *st);
int smbw_stat(const char *fname, struct stat *st);
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 313021abb8..ccbaebf4ea 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -4044,7 +4044,6 @@ BOOL process_exists(int pid)
/*******************************************************************
turn a uid into a user name
********************************************************************/
-
char *uidtoname(uid_t uid)
{
static char name[40];
@@ -4054,6 +4053,7 @@ char *uidtoname(uid_t uid)
return(name);
}
+
/*******************************************************************
turn a gid into a group name
********************************************************************/
@@ -4068,6 +4068,16 @@ char *gidtoname(gid_t gid)
}
/*******************************************************************
+turn a user name into a uid
+********************************************************************/
+uid_t nametouid(const char *name)
+{
+ struct passwd *pass = getpwnam(name);
+ if (pass) return(pass->pw_uid);
+ return (uid_t)-1;
+}
+
+/*******************************************************************
something really nasty happened - panic!
********************************************************************/
void smb_panic(char *why)
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index e871bd7d9d..0e01370f5d 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -137,6 +137,29 @@ static void cli_setup_packet(struct cli_state *cli)
}
+/*****************************************************************************
+ Convert a character pointer in a cli_call_api() response to a form we can use.
+ This function contains code to prevent core dumps if the server returns
+ invalid data.
+*****************************************************************************/
+static char *fix_char_ptr(unsigned int datap, unsigned int converter,
+ char *rdata, int rdrcnt)
+{
+ if (datap == 0) { /* turn NULL pointers into zero length strings */
+ return "";
+ } else {
+ unsigned int offset = datap - converter;
+
+ if (offset >= rdrcnt) {
+ DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
+ datap, converter, rdrcnt));
+ return "<ERROR>";
+ } else {
+ return &rdata[offset];
+ }
+ }
+}
+
/****************************************************************************
send a SMB trans or trans2 request
****************************************************************************/
@@ -739,6 +762,8 @@ BOOL cli_send_tconX(struct cli_state *cli,
bzero(cli->outbuf,smb_size);
bzero(cli->inbuf,smb_size);
+ fstrcpy(cli->share, share);
+
if (cli->sec_mode & 1) {
passlen = 1;
pass = "";
@@ -779,6 +804,8 @@ BOOL cli_send_tconX(struct cli_state *cli,
return False;
}
+ fstrcpy(cli->dev, smb_buf(cli->inbuf));
+
if (cli->protocol >= PROTOCOL_NT1 &&
smb_buflen(cli->inbuf) == 3) {
/* almost certainly win95 - enable bug fixes */
@@ -2466,3 +2493,76 @@ BOOL cli_establish_connection(struct cli_state *cli,
return True;
}
+
+
+
+/****************************************************************************
+call fn() on each entry in a print queue
+****************************************************************************/
+int cli_print_queue(struct cli_state *cli,
+ void (*fn)(struct print_job_info *))
+{
+ char *rparam = NULL;
+ char *rdata = NULL;
+ char *p;
+ int rdrcnt, rprcnt;
+ pstring param;
+ int result_code=0;
+ int i = -1;
+
+ bzero(param,sizeof(param));
+
+ p = param;
+ SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
+ p += 2;
+ pstrcpy(p,"zWrLeh"); /* parameter description? */
+ p = skip_string(p,1);
+ pstrcpy(p,"WWzWWDDzz"); /* returned data format */
+ p = skip_string(p,1);
+ pstrcpy(p,cli->share); /* name of queue */
+ p = skip_string(p,1);
+ SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
+ SSVAL(p,2,1000); /* size of bytes of returned data buffer */
+ p += 4;
+ pstrcpy(p,""); /* subformat */
+ p = skip_string(p,1);
+
+ DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
+
+ if (cli_api(cli,
+ param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
+ NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
+ &rparam, &rprcnt, /* return params, length */
+ &rdata, &rdrcnt)) { /* return data, length */
+ int converter;
+ result_code = SVAL(rparam,0);
+ converter = SVAL(rparam,2); /* conversion factor */
+
+ if (result_code == 0) {
+ struct print_job_info job;
+
+ p = rdata;
+
+ for (i = 0; i < SVAL(rparam,4); ++i) {
+ job.id = SVAL(p,0);
+ job.priority = SVAL(p,2);
+ fstrcpy(job.user,
+ fix_char_ptr(SVAL(p,4), converter,
+ rdata, rdrcnt));
+ job.t = make_unix_date3(p + 12);
+ job.size = IVAL(p,16);
+ fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
+ converter,
+ rdata, rdrcnt));
+ fn(&job);
+ p += 28;
+ }
+ }
+ }
+
+ /* If any parameters or data were returned, free the storage. */
+ if(rparam) free(rparam);
+ if(rdata) free(rdata);
+
+ return i;
+}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 6fd0272a0a..6d2f61f5b9 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -249,7 +249,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
if (sys_fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
close_file(fsp,False);
- return(ERROR(ERRDOS,ERRnoaccess));
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
size = sbuf.st_size;
@@ -681,7 +681,7 @@ static int call_trans2findfirst(connection_struct *conn,
}
#endif
- return(ERROR(ERRDOS,ERRbadpath));
+ return(UNIXERROR(ERRDOS,ERRbadpath));
}
p = strrchr(directory,'/');
@@ -707,7 +707,7 @@ static int call_trans2findfirst(connection_struct *conn,
dptr_num = dptr_create(conn,directory, True ,SVAL(inbuf,smb_pid));
if (dptr_num < 0)
- return(ERROR(ERRDOS,ERRbadfile));
+ return(UNIXERROR(ERRDOS,ERRbadfile));
/* Convert the formatted mask. */
mask_convert(mask);
@@ -1475,7 +1475,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if(sys_fstat(fd,&st)!=0) {
DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno)));
- return(ERROR(ERRDOS,ERRbadpath));
+ return(UNIXERROR(ERRDOS,ERRbadpath));
}
} else {
/* set path info */
@@ -1639,7 +1639,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
{
if(file_utime(conn, fname, &tvs)!=0)
{
- return(ERROR(ERRDOS,ERRnoaccess));
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
}
@@ -1647,7 +1647,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if (mode != dos_mode(conn, fname, &st) && file_chmod(conn, fname, mode, NULL))
{
DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
- return(ERROR(ERRDOS,ERRnoaccess));
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
if(size != st.st_size)
@@ -1657,7 +1657,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
fd = dos_open(fname,O_RDWR,0);
if (fd == -1)
{
- return(ERROR(ERRDOS,ERRbadpath));
+ return(UNIXERROR(ERRDOS,ERRbadpath));
}
set_filelen(fd, size);
close(fd);
diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c
index 74a40a2451..3a2cbcf5ac 100644
--- a/source3/smbwrapper/smbw.c
+++ b/source3/smbwrapper/smbw.c
@@ -390,8 +390,7 @@ struct smbw_server *smbw_server(char *server, char *share)
return NULL;
}
- if (!cli_send_tconX(&c, share,
- strstr(share,"IPC$")?"IPC":"A:",
+ if (!cli_send_tconX(&c, share, "?????",
password, strlen(password)+1)) {
errno = smbw_errno(&c);
cli_shutdown(&c);
diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c
index a127048793..3fdaebec5a 100644
--- a/source3/smbwrapper/smbw_dir.c
+++ b/source3/smbwrapper/smbw_dir.c
@@ -113,6 +113,28 @@ static void smbw_share_add(const char *share, uint32 type, const char *comment)
/*****************************************************
+add a entry to a directory listing
+*******************************************************/
+static void smbw_printjob_add(struct print_job_info *job)
+{
+ struct file_info finfo;
+
+ ZERO_STRUCT(finfo);
+
+ pstrcpy(finfo.name, job->name);
+ finfo.mode = aRONLY | aDIR;
+ finfo.mtime = job->t;
+ finfo.atime = job->t;
+ finfo.ctime = job->t;
+ finfo.uid = nametouid(job->user);
+ finfo.mode = aRONLY;
+ finfo.size = job->size;
+
+ smbw_dir_add(&finfo);
+}
+
+
+/*****************************************************
open a directory on the server
*******************************************************/
int smbw_dir_open(const char *fname)
@@ -159,15 +181,20 @@ int smbw_dir_open(const char *fname)
slprintf(mask, sizeof(mask)-1, "%s\\*", path);
string_sub(mask,"\\\\","\\");
- if (strcmp(share,"IPC$") == 0) {
+ if (strcmp(srv->cli.dev,"IPC") == 0) {
DEBUG(4,("doing NetShareEnum\n"));
- if (cli_RNetShareEnum(&srv->cli, smbw_share_add) <= 0) {
+ if (cli_RNetShareEnum(&srv->cli, smbw_share_add) < 0) {
+ errno = smbw_errno(&srv->cli);
+ goto failed;
+ }
+ } else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
+ if (cli_print_queue(&srv->cli, smbw_printjob_add) < 0) {
errno = smbw_errno(&srv->cli);
goto failed;
}
} else {
if (cli_list(&srv->cli, mask, aHIDDEN|aSYSTEM|aDIR,
- smbw_dir_add) <= 0) {
+ smbw_dir_add) < 0) {
errno = smbw_errno(&srv->cli);
goto failed;
}
@@ -344,7 +371,8 @@ int smbw_chdir(const char *name)
goto failed;
}
- if (strcmp(share,"IPC$") &&
+ if (strncmp(srv->cli.dev,"IPC",3) &&
+ strncmp(srv->cli.dev,"LPT",3) &&
!smbw_getatr(srv, path,
&mode, NULL, NULL, NULL, NULL)) {
errno = smbw_errno(&srv->cli);
diff --git a/source3/smbwrapper/smbw_stat.c b/source3/smbwrapper/smbw_stat.c
index ae8671c591..69ca38a2ae 100644
--- a/source3/smbwrapper/smbw_stat.c
+++ b/source3/smbwrapper/smbw_stat.c
@@ -74,6 +74,38 @@ BOOL smbw_getatr(struct smbw_server *srv, char *path,
return False;
}
+
+static struct print_job_info printjob;
+
+/*****************************************************
+gather info from a printjob listing
+*******************************************************/
+static void smbw_printjob_stat(struct print_job_info *job)
+{
+ if (strcmp(job->name, printjob.name) == 0) {
+ printjob = *job;
+ }
+}
+
+/*****************************************************
+stat a printjob
+*******************************************************/
+int smbw_stat_printjob(struct smbw_server *srv,char *path,
+ size_t *size, time_t *m_time)
+{
+ if (path[0] == '\\') path++;
+
+ ZERO_STRUCT(printjob);
+
+ fstrcpy(printjob.name, path);
+ cli_print_queue(&srv->cli, smbw_printjob_stat);
+
+ *size = printjob.size;
+ *m_time = printjob.t;
+ return 0;
+}
+
+
/*****************************************************
a wrapper for fstat()
*******************************************************/
@@ -151,8 +183,16 @@ int smbw_stat(const char *fname, struct stat *st)
goto failed;
}
- if (strcmp(share,"IPC$") == 0) {
+ if (strncmp(srv->cli.dev,"IPC",3) == 0) {
mode = aDIR | aRONLY;
+ } else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
+ if (strcmp(path,"\\") == 0) {
+ mode = aDIR | aRONLY;
+ } else {
+ mode = aRONLY;
+ smbw_stat_printjob(srv, path, &size, &m_time);
+ c_time = a_time = m_time;
+ }
} else {
if (!smbw_getatr(srv, path,
&mode, &size, &c_time, &a_time, &m_time)) {
@@ -163,8 +203,8 @@ int smbw_stat(const char *fname, struct stat *st)
smbw_setup_stat(st, path, size, mode);
- st->st_atime = time(NULL);
- st->st_ctime = m_time;
+ st->st_atime = a_time;
+ st->st_ctime = c_time;
st->st_mtime = m_time;
st->st_dev = srv->dev;