예제 #1
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for read()
*******************************************************/
ssize_t smbw_read(int fd, void *buf, size_t count)
{
	struct smbw_file *file;
	int ret;

	DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count));

	smbw_busy++;

	file = smbw_file(fd);
	if (!file) {
		errno = EBADF;
		smbw_busy--;
		return -1;
	}
	
	ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, 
		       file->f->offset, count);

	if (ret == -1) {
		errno = smbw_errno(&file->srv->cli);
		smbw_busy--;
		return -1;
	}

	file->f->offset += ret;
	
	DEBUG(4,(" -> %d\n", ret));

	smbw_busy--;
	return ret;
}
예제 #2
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for pwrite()
*******************************************************/
ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs)
{
	struct smbw_file *file;
	int ret;

	smbw_busy++;

	file = smbw_file(fd);
	if (!file) {
		errno = EBADF;
		smbw_busy--;
		return -1;
	}
	
	ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count);

	if (ret == -1) {
		errno = smbw_errno(&file->srv->cli);
		smbw_busy--;
		return -1;
	}

	smbw_busy--;
	return ret;
}
예제 #3
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for utime and utimes
*******************************************************/
static int smbw_settime(const char *fname, time_t t)
{
	struct smbw_server *srv;
	fstring server, share;
	pstring path;
	uint16 mode;

	if (!fname) {
		errno = EINVAL;
		return -1;
	}

	smbw_init();

	smbw_busy++;

	/* work out what server they are after */
	smbw_parse_path(fname, server, share, path);

	/* get a connection to the server */
	srv = smbw_server(server, share);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
		errno = smbw_errno(&srv->cli);
		goto failed;
	}

	if (!cli_setatr(&srv->cli, path, mode, t)) {
		/* some servers always refuse directory changes */
		if (!(mode & aDIR)) {
			errno = smbw_errno(&srv->cli);
			goto failed;
		}
	}

	smbw_busy--;
	return 0;

 failed:
	smbw_busy--;
	return -1;
}
예제 #4
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for rename()
*******************************************************/
int smbw_rename(const char *oldname, const char *newname)
{
	struct smbw_server *srv;
	fstring server1, share1;
	pstring path1;
	fstring server2, share2;
	pstring path2;

	if (!oldname || !newname) {
		errno = EINVAL;
		return -1;
	}

	smbw_init();

	DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));

	smbw_busy++;

	/* work out what server they are after */
	smbw_parse_path(oldname, server1, share1, path1);
	smbw_parse_path(newname, server2, share2, path2);

	if (strcmp(server1, server2) || strcmp(share1, share2)) {
		/* can't cross filesystems */
		errno = EXDEV;
		return -1;
	}

	/* get a connection to the server */
	srv = smbw_server(server1, share1);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	if (!cli_rename(&srv->cli, path1, path2)) {
		int eno = smbw_errno(&srv->cli);
		if (eno != EEXIST ||
		    !cli_unlink(&srv->cli, path2) ||
		    !cli_rename(&srv->cli, path1, path2)) {
			errno = eno;
			goto failed;
		}
	}

	smbw_busy--;
	return 0;

 failed:
	smbw_busy--;
	return -1;
}
예제 #5
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for unlink()
*******************************************************/
int smbw_unlink(const char *fname)
{
	struct smbw_server *srv;
	fstring server, share;
	pstring path;

	if (!fname) {
		errno = EINVAL;
		return -1;
	}

	smbw_init();

	smbw_busy++;

	/* work out what server they are after */
	smbw_parse_path(fname, server, share, path);

	/* get a connection to the server */
	srv = smbw_server(server, share);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
		int job = smbw_stat_printjob(srv, path, NULL, NULL);
		if (job == -1) {
			goto failed;
		}
		if (cli_printjob_del(&srv->cli, job) != 0) {
			goto failed;
		}
	} else if (!cli_unlink(&srv->cli, path)) {
		errno = smbw_errno(&srv->cli);
		goto failed;
	}

	smbw_busy--;
	return 0;

 failed:
	smbw_busy--;
	return -1;
}
예제 #6
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for chmod()
*******************************************************/
int smbw_chmod(const char *fname, mode_t newmode)
{
	struct smbw_server *srv;
	fstring server, share;
	pstring path;
	uint32 mode;

	if (!fname) {
		errno = EINVAL;
		return -1;
	}

	smbw_init();

	smbw_busy++;

	/* work out what server they are after */
	smbw_parse_path(fname, server, share, path);

	/* get a connection to the server */
	srv = smbw_server(server, share);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	mode = 0;

	if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
	if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
	if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
	if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;

	if (!cli_setatr(&srv->cli, path, mode, 0)) {
		errno = smbw_errno(&srv->cli);
		goto failed;
	}
	
	smbw_busy--;
	return 0;

 failed:
	smbw_busy--;
	return -1;
}
예제 #7
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for chown()
*******************************************************/
int smbw_chown(const char *fname, uid_t owner, gid_t group)
{
	struct smbw_server *srv;
	fstring server, share;
	pstring path;
	uint16 mode;

	if (!fname) {
		errno = EINVAL;
		return -1;
	}

	smbw_init();

	smbw_busy++;

	/* work out what server they are after */
	smbw_parse_path(fname, server, share, path);

	/* get a connection to the server */
	srv = smbw_server(server, share);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
		errno = smbw_errno(&srv->cli);
		goto failed;
	}
	
	/* assume success */

	smbw_busy--;
	return 0;

 failed:
	smbw_busy--;
	return -1;
}
예제 #8
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for close()
*******************************************************/
int smbw_close(int fd)
{
	struct smbw_file *file;

	smbw_busy++;

	file = smbw_file(fd);
	if (!file) {
		int ret = smbw_dir_close(fd);
		smbw_busy--;
		return ret;
	}
	
	if (file->f->ref_count == 1 &&
	    !cli_close(&file->srv->cli, file->f->cli_fd)) {
		errno = smbw_errno(&file->srv->cli);
		smbw_busy--;
		return -1;
	}


	bitmap_clear(smbw_file_bmap, file->fd);
	close(file->fd);
	
	DLIST_REMOVE(smbw_files, file);

	file->f->ref_count--;
	if (file->f->ref_count == 0) {
		SAFE_FREE(file->f->fname);
		SAFE_FREE(file->f);
	}
	ZERO_STRUCTP(file);
	SAFE_FREE(file);
	
	smbw_busy--;

	return 0;
}
예제 #9
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
a wrapper for open()
*******************************************************/
int smbw_open(const char *fname, int flags, mode_t mode)
{
	fstring server, share;
	pstring path;
	struct smbw_server *srv=NULL;
	int eno=0, fd = -1;
	struct smbw_file *file=NULL;

	smbw_init();

	if (!fname) {
		errno = EINVAL;
		return -1;
	}

	smbw_busy++;	

	/* work out what server they are after */
	smbw_parse_path(fname, server, share, path);

	/* get a connection to the server */
	srv = smbw_server(server, share);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	if (path[strlen(path)-1] == '\\') {
		fd = -1;
	} else {
		fd = cli_open(&srv->cli, path, flags, DENY_NONE);
	}
	if (fd == -1) {
		/* it might be a directory. Maybe we should use chkpath? */
		eno = smbw_errno(&srv->cli);
		fd = smbw_dir_open(fname);
		if (fd == -1) errno = eno;
		smbw_busy--;
		return fd;
	}

	file = (struct smbw_file *)malloc(sizeof(*file));
	if (!file) {
		errno = ENOMEM;
		goto failed;
	}

	ZERO_STRUCTP(file);

	file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
	if (!file->f) {
		errno = ENOMEM;
		goto failed;
	}

	ZERO_STRUCTP(file->f);

	file->f->cli_fd = fd;
	file->f->fname = strdup(path);
	if (!file->f->fname) {
		errno = ENOMEM;
		goto failed;
	}
	file->srv = srv;
	file->fd = open(SMBW_DUMMY, O_WRONLY);
	if (file->fd == -1) {
		errno = EMFILE;
		goto failed;
	}

	if (bitmap_query(smbw_file_bmap, file->fd)) {
		DEBUG(0,("ERROR: fd used in smbw_open\n"));
		errno = EIO;
		goto failed;
	}

	file->f->ref_count=1;

	bitmap_set(smbw_file_bmap, file->fd);

	DLIST_ADD(smbw_files, file);

	DEBUG(4,("opened %s\n", fname));

	smbw_busy--;
	return file->fd;

 failed:
	if (fd != -1) {
		cli_close(&srv->cli, fd);
	}
	if (file) {
		if (file->f) {
			SAFE_FREE(file->f->fname);
			SAFE_FREE(file->f);
		}
		SAFE_FREE(file);
	}
	smbw_busy--;
	return -1;
}
예제 #10
0
파일: smbw.c 프로젝트: livebox/livebox2
/***************************************************** 
return a connection to a server (existing or new)
*******************************************************/
struct smbw_server *smbw_server(char *server, char *share)
{
	struct smbw_server *srv=NULL;
	struct cli_state c;
	char *username;
	char *password;
	char *workgroup;
	struct nmb_name called, calling;
	char *p, *server_n = server;
	fstring group;
	pstring ipenv;
	struct in_addr ip;

	zero_ip(&ip);
	ZERO_STRUCT(c);

	get_auth_data_fn(server, share, &workgroup, &username, &password);

	/* try to use an existing connection */
	for (srv=smbw_srvs;srv;srv=srv->next) {
		if (strcmp(server,srv->server_name)==0 &&
		    strcmp(share,srv->share_name)==0 &&
		    strcmp(workgroup,srv->workgroup)==0 &&
		    strcmp(username, srv->username) == 0) 
			return srv;
	}

	if (server[0] == 0) {
		errno = EPERM;
		return NULL;
	}

	make_nmb_name(&calling, global_myname, 0x0);
	make_nmb_name(&called , server, 0x20);

	DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));

	if ((p=strchr(server_n,'#')) && 
	    (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
		struct in_addr sip;
		pstring s;

		fstrcpy(group, server_n);
		p = strchr(group,'#');
		*p = 0;
		
		/* cache the workgroup master lookup */
		slprintf(s,sizeof(s)-1,"MASTER_%s", group);
		if (!(server_n = smbw_getshared(s))) {
			if (!find_master_ip(group, &sip)) {
				errno = ENOENT;
				return NULL;
			}
			fstrcpy(group, inet_ntoa(sip));
			server_n = group;
			smbw_setshared(s,server_n);
		}
	}

	DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));

 again:
	slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);

	zero_ip(&ip);
	if ((p=smbw_getshared(ipenv))) {
		ip = *(interpret_addr2(p));
	}

	/* have to open a new connection */
	if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
		errno = ENOENT;
		return NULL;
	}

	if (!cli_session_request(&c, &calling, &called)) {
		cli_shutdown(&c);
		if (strcmp(called.name, "*SMBSERVER")) {
			make_nmb_name(&called , "*SMBSERVER", 0x20);
			goto again;
		}
		errno = ENOENT;
		return NULL;
	}

	DEBUG(4,(" session request ok\n"));

	if (!cli_negprot(&c)) {
		cli_shutdown(&c);
		errno = ENOENT;
		return NULL;
	}

	if (!cli_session_setup(&c, username, 
			       password, strlen(password),
			       password, strlen(password),
			       workgroup) &&
	    /* try an anonymous login if it failed */
	    !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
		cli_shutdown(&c);
		errno = EPERM;
		return NULL;
	}

	DEBUG(4,(" session setup ok\n"));

	if (!cli_send_tconX(&c, share, "?????",
			    password, strlen(password)+1)) {
		errno = smbw_errno(&c);
		cli_shutdown(&c);
		return NULL;
	}

	smbw_setshared(ipenv,inet_ntoa(ip));
	
	DEBUG(4,(" tconx ok\n"));

	srv = (struct smbw_server *)malloc(sizeof(*srv));
	if (!srv) {
		errno = ENOMEM;
		goto failed;
	}

	ZERO_STRUCTP(srv);

	srv->cli = c;

	srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));

	srv->server_name = strdup(server);
	if (!srv->server_name) {
		errno = ENOMEM;
		goto failed;
	}

	srv->share_name = strdup(share);
	if (!srv->share_name) {
		errno = ENOMEM;
		goto failed;
	}

	srv->workgroup = strdup(workgroup);
	if (!srv->workgroup) {
		errno = ENOMEM;
		goto failed;
	}

	srv->username = strdup(username);
	if (!srv->username) {
		errno = ENOMEM;
		goto failed;
	}

	/* some programs play with file descriptors fairly intimately. We
	   try to get out of the way by duping to a high fd number */
	if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
		if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) == 
		    srv->cli.fd+SMBW_CLI_FD) {
			close(srv->cli.fd);
			srv->cli.fd += SMBW_CLI_FD;
		}
	}

	DLIST_ADD(smbw_srvs, srv);

	return srv;

 failed:
	cli_shutdown(&c);
	if (!srv) return NULL;

	SAFE_FREE(srv->server_name);
	SAFE_FREE(srv->share_name);
	SAFE_FREE(srv);
	return NULL;
}
예제 #11
0
파일: smbw_stat.c 프로젝트: AllardJ/Tomato
/***************************************************** 
a wrapper for stat()
*******************************************************/
int smbw_stat(const char *fname, struct stat *st)
{
	struct smbw_server *srv;
	fstring server, share;
	pstring path;
	time_t m_time=0, a_time=0, c_time=0;
	size_t size=0;
	uint16 mode=0;
	SMB_INO_T ino = 0;

	ZERO_STRUCTP(st);

	if (!fname) {
		errno = EINVAL;
		return -1;
	}

	DEBUG(4,("stat(%s)\n", fname));

	smbw_init();

	smbw_busy++;

	/* work out what server they are after */
	smbw_parse_path(fname, server, share, path);

	/* get a connection to the server */
	srv = smbw_server(server, share);
	if (!srv) {
		/* smbw_server sets errno */
		goto failed;
	}

	DEBUG(4,("smbw_stat\n"));

	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,
				 &ino)) {
			errno = smbw_errno(&srv->cli);
			goto failed;
		}
	}

	st->st_ino = ino;

	smbw_setup_stat(st, path, size, mode);

	st->st_atime = a_time;
	st->st_ctime = c_time;
	st->st_mtime = m_time;
	st->st_dev = srv->dev;

	smbw_busy--;
	return 0;

 failed:
	smbw_busy--;
	return -1;
}