2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "realcalls.h"
27 static struct smbw_file *smbw_files;
28 static struct smbw_server *smbw_srvs;
30 struct bitmap *smbw_file_bmap;
31 extern pstring global_myname;
32 extern int DEBUGLEVEL;
34 fstring smbw_prefix = SMBW_PREFIX;
38 /* needs to be here because of dumb include files on some systems */
39 int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;
41 /*****************************************************
43 *******************************************************/
46 extern BOOL in_client;
47 static int initialised;
48 static pstring servicesf = CONFIGFILE;
53 if (initialised) return;
61 setup_logging("smbsh",True);
65 if ((p=smbw_getshared("LOGFILE"))) {
69 smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN);
70 if (!smbw_file_bmap) {
80 lp_load(servicesf,True,False,False);
82 get_myname(global_myname,NULL);
84 if ((p=smbw_getshared("DEBUG"))) {
88 if ((p=smbw_getshared("PREFIX"))) {
89 slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p);
90 string_sub(smbw_prefix,"//", "/");
91 DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix));
94 if ((p=getenv(SMBW_PWD_ENV))) {
96 DEBUG(4,("Initial cwd from smbw_cwd is %s\n", smbw_cwd));
99 DEBUG(4,("Initial cwd from getwd is %s\n", smbw_cwd));
103 set_maxfiles(SMBW_MAX_OPEN);
108 /*****************************************************
109 determine if a file descriptor is a smb one
110 *******************************************************/
113 if (smbw_busy) return 0;
114 return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd);
117 /*****************************************************
118 a crude inode number generator
119 *******************************************************/
120 ino_t smbw_inode(const char *name)
122 return (ino_t)str_checksum(name);
125 /*****************************************************
126 remove redundent stuff from a filename
127 *******************************************************/
128 void clean_fname(char *name)
139 DEBUG(5,("cleaning %s\n", name));
141 if ((p=strstr(name,"/./"))) {
149 if ((p=strstr(name,"//"))) {
157 if (strcmp(name,"/../")==0) {
162 if ((p=strstr(name,"/../"))) {
164 for (p2=(p>name?p-1:p);p2>name;p2--) {
165 if (p2[0] == '/') break;
173 if (strcmp(name,"/..")==0) {
179 p = l>=3?(name+l-3):name;
180 if (strcmp(p,"/..")==0) {
182 for (p2=p-1;p2>name;p2--) {
183 if (p2[0] == '/') break;
194 p = l>=2?(name+l-2):name;
195 if (strcmp(p,"/.")==0) {
203 if (strncmp(p=name,"./",2) == 0) {
211 if (l > 1 && p[l-1] == '/') {
219 /*****************************************************
220 parse a smb path into its components.
221 *******************************************************/
222 char *smbw_parse_path(const char *fname, char *server, char *share, char *path)
226 int len = strlen(smbw_prefix)-1;
228 *server = *share = *path = 0;
230 if (fname[0] == '/') {
233 slprintf(s,sizeof(s)-1, "%s/%s", smbw_cwd, fname);
237 DEBUG(5,("cleaned %s (fname=%s cwd=%s)\n",
238 s, fname, smbw_cwd));
240 if (strncmp(s,smbw_prefix,len) ||
241 (s[len] != '/' && s[len] != 0)) return s;
254 len = MIN(len,sizeof(fstring)-1);
256 strncpy(server, p, len);
262 char *workgroup = smbw_getshared("WORKGROUP");
263 if (!workgroup) workgroup = lp_workgroup();
264 slprintf(server,sizeof(fstring)-1, "%s#1D", workgroup);
266 fstrcpy(share,"IPC$");
280 len = MIN(len,sizeof(fstring)-1);
282 strncpy(share, p, len);
293 string_sub(path, "/", "\\");
296 DEBUG(4,("parsed path name=%s cwd=%s [%s] [%s] [%s]\n",
298 server, share, path));
303 /*****************************************************
304 determine if a path name (possibly relative) is in the
306 *******************************************************/
307 int smbw_path(const char *path)
309 fstring server, share;
316 len = strlen(smbw_prefix)-1;
318 if (path[0] == '/' && strncmp(path,smbw_prefix,len)) {
322 if (smbw_busy) return 0;
324 DEBUG(3,("smbw_path(%s)\n", path));
326 cwd = smbw_parse_path(path, server, share, s);
328 if (strncmp(cwd,smbw_prefix,len) == 0 &&
329 (cwd[len] == '/' || cwd[len] == 0)) {
336 /*****************************************************
337 return a unix errno from a SMB error pair
338 *******************************************************/
339 int smbw_errno(struct cli_state *c)
345 ret = cli_error(c, &eclass, &ecode);
348 DEBUG(3,("smbw_error %d %d (0x%x) -> %d\n",
349 (int)eclass, (int)ecode, (int)ecode, ret));
354 /*****************************************************
355 return a connection to a server (existing or new)
356 *******************************************************/
357 struct smbw_server *smbw_server(char *server, char *share)
359 struct smbw_server *srv=NULL;
364 struct nmb_name called, calling;
365 char *p, *server_n = server;
369 extern struct in_addr ipzero;
374 username = smbw_getshared("USER");
375 if (!username) username = getenv("USER");
376 if (!username) username = "guest";
378 workgroup = smbw_getshared("WORKGROUP");
379 if (!workgroup) workgroup = lp_workgroup();
381 password = smbw_getshared("PASSWORD");
382 if (!password) password = "";
384 /* try to use an existing connection */
385 for (srv=smbw_srvs;srv;srv=srv->next) {
386 if (strcmp(server,srv->server_name)==0 &&
387 strcmp(share,srv->share_name)==0) return srv;
390 if (server[0] == 0) {
395 make_nmb_name(&calling, global_myname, 0x0, "");
396 make_nmb_name(&called , server, 0x20, "");
398 DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));
400 if ((p=strchr(server_n,'#')) && strcmp(p+1,"1D")==0) {
404 fstrcpy(group, server_n);
405 p = strchr(group,'#');
408 /* cache the workgroup master lookup */
409 slprintf(s,sizeof(s)-1,"MASTER_%s", group);
410 if (!(server_n = smbw_getshared(s))) {
411 if (!find_master_ip(group, &ip)) {
415 fstrcpy(group, inet_ntoa(ip));
417 smbw_setshared(s,server_n);
421 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
424 slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);
427 if ((p=smbw_getshared(ipenv))) {
428 ip = *(interpret_addr2(p));
431 /* have to open a new connection */
432 if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
437 if (!cli_session_request(&c, &calling, &called)) {
439 if (strcmp(called.name, "*SMBSERVER")) {
440 make_nmb_name(&called , "*SMBSERVER", 0x20, "");
447 DEBUG(4,(" session request ok\n"));
449 if (!cli_negprot(&c)) {
455 if (!cli_session_setup(&c, username,
456 password, strlen(password),
457 password, strlen(password),
459 /* try an anonymous login if it failed */
460 !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) {
466 DEBUG(4,(" session setup ok\n"));
468 if (!cli_send_tconX(&c, share, "?????",
469 password, strlen(password)+1)) {
470 errno = smbw_errno(&c);
475 smbw_setshared(ipenv,inet_ntoa(ip));
477 DEBUG(4,(" tconx ok\n"));
479 srv = (struct smbw_server *)malloc(sizeof(*srv));
489 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
491 srv->server_name = strdup(server);
492 if (!srv->server_name) {
497 srv->share_name = strdup(share);
498 if (!srv->share_name) {
503 /* some programs play with file descriptors fairly intimately. We
504 try to get out of the way by duping to a high fd number */
505 if (fcntl(SMBW_CLI_FD + srv->cli.fd, F_GETFD) && errno == EBADF) {
506 if (dup2(srv->cli.fd,SMBW_CLI_FD+srv->cli.fd) ==
507 srv->cli.fd+SMBW_CLI_FD) {
509 srv->cli.fd += SMBW_CLI_FD;
513 DLIST_ADD(smbw_srvs, srv);
519 if (!srv) return NULL;
521 if (srv->server_name) free(srv->server_name);
522 if (srv->share_name) free(srv->share_name);
528 /*****************************************************
529 map a fd to a smbw_file structure
530 *******************************************************/
531 struct smbw_file *smbw_file(int fd)
533 struct smbw_file *file;
535 for (file=smbw_files;file;file=file->next) {
536 if (file->fd == fd) return file;
541 /*****************************************************
543 *******************************************************/
544 int smbw_open(const char *fname, int flags, mode_t mode)
546 fstring server, share;
548 struct smbw_server *srv=NULL;
550 struct smbw_file *file=NULL;
561 /* work out what server they are after */
562 smbw_parse_path(fname, server, share, path);
564 /* get a connection to the server */
565 srv = smbw_server(server, share);
567 /* smbw_server sets errno */
571 if (path[strlen(path)-1] == '\\') {
574 fd = cli_open(&srv->cli, path, flags, DENY_NONE);
577 /* it might be a directory. Maybe we should use chkpath? */
578 eno = smbw_errno(&srv->cli);
579 fd = smbw_dir_open(fname);
580 if (fd == -1) errno = eno;
585 file = (struct smbw_file *)malloc(sizeof(*file));
593 file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
599 ZERO_STRUCTP(file->f);
601 file->f->cli_fd = fd;
602 file->f->fname = strdup(path);
603 if (!file->f->fname) {
608 file->fd = open(SMBW_DUMMY, O_WRONLY);
609 if (file->fd == -1) {
614 if (bitmap_query(smbw_file_bmap, file->fd)) {
615 DEBUG(0,("ERROR: fd used in smbw_open\n"));
620 file->f->ref_count=1;
622 bitmap_set(smbw_file_bmap, file->fd);
624 DLIST_ADD(smbw_files, file);
626 DEBUG(4,("opened %s\n", fname));
633 cli_close(&srv->cli, fd);
637 if (file->f->fname) {
638 free(file->f->fname);
649 /*****************************************************
650 a wrapper for pread()
651 *******************************************************/
652 ssize_t smbw_pread(int fd, void *buf, size_t count, off_t ofs)
654 struct smbw_file *file;
659 file = smbw_file(fd);
666 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, ofs, count);
669 errno = smbw_errno(&file->srv->cli);
678 /*****************************************************
680 *******************************************************/
681 ssize_t smbw_read(int fd, void *buf, size_t count)
683 struct smbw_file *file;
686 DEBUG(4,("smbw_read(%d, %d)\n", fd, (int)count));
690 file = smbw_file(fd);
697 ret = cli_read(&file->srv->cli, file->f->cli_fd, buf,
698 file->f->offset, count);
701 errno = smbw_errno(&file->srv->cli);
706 file->f->offset += ret;
708 DEBUG(4,(" -> %d\n", ret));
716 /*****************************************************
717 a wrapper for write()
718 *******************************************************/
719 ssize_t smbw_write(int fd, void *buf, size_t count)
721 struct smbw_file *file;
726 file = smbw_file(fd);
728 DEBUG(3,("bad fd in read\n"));
734 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, file->f->offset, count);
737 errno = smbw_errno(&file->srv->cli);
742 file->f->offset += ret;
748 /*****************************************************
749 a wrapper for pwrite()
750 *******************************************************/
751 ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs)
753 struct smbw_file *file;
758 file = smbw_file(fd);
760 DEBUG(3,("bad fd in read\n"));
766 ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count);
769 errno = smbw_errno(&file->srv->cli);
778 /*****************************************************
779 a wrapper for close()
780 *******************************************************/
781 int smbw_close(int fd)
783 struct smbw_file *file;
787 file = smbw_file(fd);
789 int ret = smbw_dir_close(fd);
794 if (file->f->ref_count == 1 &&
795 !cli_close(&file->srv->cli, file->f->cli_fd)) {
796 errno = smbw_errno(&file->srv->cli);
802 bitmap_clear(smbw_file_bmap, file->fd);
805 DLIST_REMOVE(smbw_files, file);
807 file->f->ref_count--;
808 if (file->f->ref_count == 0) {
809 free(file->f->fname);
821 /*****************************************************
822 a wrapper for fcntl()
823 *******************************************************/
824 int smbw_fcntl(int fd, int cmd, long arg)
830 /*****************************************************
831 a wrapper for access()
832 *******************************************************/
833 int smbw_access(const char *name, int mode)
837 DEBUG(4,("smbw_access(%s, 0x%x)\n", name, mode));
839 if (smbw_stat(name, &st)) return -1;
841 if (((mode & R_OK) && !(st.st_mode & S_IRUSR)) ||
842 ((mode & W_OK) && !(st.st_mode & S_IWUSR)) ||
843 ((mode & X_OK) && !(st.st_mode & S_IXUSR))) {
851 /*****************************************************
852 a wrapper for realink() - needed for correct errno setting
853 *******************************************************/
854 int smbw_readlink(const char *path, char *buf, size_t bufsize)
859 ret = smbw_stat(path, &st);
861 DEBUG(4,("readlink(%s) failed\n", path));
865 /* it exists - say it isn't a link */
866 DEBUG(4,("readlink(%s) not a link\n", path));
873 /*****************************************************
874 a wrapper for unlink()
875 *******************************************************/
876 int smbw_unlink(const char *fname)
878 struct smbw_server *srv;
879 fstring server, share;
891 /* work out what server they are after */
892 smbw_parse_path(fname, server, share, path);
894 /* get a connection to the server */
895 srv = smbw_server(server, share);
897 /* smbw_server sets errno */
901 if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
902 int job = smbw_stat_printjob(srv, path, NULL, NULL);
906 if (cli_printjob_del(&srv->cli, job) != 0) {
909 } else if (!cli_unlink(&srv->cli, path)) {
910 errno = smbw_errno(&srv->cli);
923 /*****************************************************
924 a wrapper for rename()
925 *******************************************************/
926 int smbw_rename(const char *oldname, const char *newname)
928 struct smbw_server *srv;
929 fstring server1, share1;
931 fstring server2, share2;
934 if (!oldname || !newname) {
941 DEBUG(4,("smbw_rename(%s,%s)\n", oldname, newname));
945 /* work out what server they are after */
946 smbw_parse_path(oldname, server1, share1, path1);
947 smbw_parse_path(newname, server2, share2, path2);
949 if (strcmp(server1, server2) || strcmp(share1, share2)) {
950 /* can't cross filesystems */
955 /* get a connection to the server */
956 srv = smbw_server(server1, share1);
958 /* smbw_server sets errno */
962 if (!cli_rename(&srv->cli, path1, path2)) {
963 int eno = smbw_errno(&srv->cli);
965 !cli_unlink(&srv->cli, path2) ||
966 !cli_rename(&srv->cli, path1, path2)) {
981 /*****************************************************
982 a wrapper for utime and utimes
983 *******************************************************/
984 static int smbw_settime(const char *fname, time_t t)
986 struct smbw_server *srv;
987 fstring server, share;
1000 /* work out what server they are after */
1001 smbw_parse_path(fname, server, share, path);
1003 /* get a connection to the server */
1004 srv = smbw_server(server, share);
1006 /* smbw_server sets errno */
1010 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1011 errno = smbw_errno(&srv->cli);
1015 if (!cli_setatr(&srv->cli, path, mode, t)) {
1016 /* some servers always refuse directory changes */
1017 if (!(mode & aDIR)) {
1018 errno = smbw_errno(&srv->cli);
1031 /*****************************************************
1033 *******************************************************/
1034 int smbw_utime(const char *fname, void *buf)
1036 struct utimbuf *tbuf = (struct utimbuf *)buf;
1037 return smbw_settime(fname, tbuf?tbuf->modtime:time(NULL));
1040 /*****************************************************
1042 *******************************************************/
1043 int smbw_utimes(const char *fname, void *buf)
1045 struct timeval *tbuf = (struct timeval *)buf;
1046 return smbw_settime(fname, tbuf?tbuf->tv_sec:time(NULL));
1050 /*****************************************************
1051 a wrapper for chown()
1052 *******************************************************/
1053 int smbw_chown(const char *fname, uid_t owner, gid_t group)
1055 struct smbw_server *srv;
1056 fstring server, share;
1069 /* work out what server they are after */
1070 smbw_parse_path(fname, server, share, path);
1072 /* get a connection to the server */
1073 srv = smbw_server(server, share);
1075 /* smbw_server sets errno */
1079 if (!cli_getatr(&srv->cli, path, &mode, NULL, NULL)) {
1080 errno = smbw_errno(&srv->cli);
1084 /* assume success */
1094 /*****************************************************
1095 a wrapper for chmod()
1096 *******************************************************/
1097 int smbw_chmod(const char *fname, mode_t newmode)
1099 struct smbw_server *srv;
1100 fstring server, share;
1113 /* work out what server they are after */
1114 smbw_parse_path(fname, server, share, path);
1116 /* get a connection to the server */
1117 srv = smbw_server(server, share);
1119 /* smbw_server sets errno */
1125 if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
1126 if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
1127 if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
1128 if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
1130 if (!cli_setatr(&srv->cli, path, mode, 0)) {
1131 errno = smbw_errno(&srv->cli);
1143 /*****************************************************
1144 a wrapper for lseek()
1145 *******************************************************/
1146 off_t smbw_lseek(int fd, off_t offset, int whence)
1148 struct smbw_file *file;
1153 file = smbw_file(fd);
1155 off_t ret = smbw_dir_lseek(fd, offset, whence);
1162 file->f->offset = offset;
1165 file->f->offset += offset;
1168 if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd,
1169 NULL, &size, NULL, NULL, NULL) &&
1170 !cli_getattrE(&file->srv->cli, file->f->cli_fd,
1171 NULL, &size, NULL, NULL, NULL)) {
1176 file->f->offset = size + offset;
1181 return file->f->offset;
1185 /*****************************************************
1187 *******************************************************/
1188 int smbw_dup(int fd)
1191 struct smbw_file *file, *file2;
1195 file = smbw_file(fd);
1201 fd2 = dup(file->fd);
1206 if (bitmap_query(smbw_file_bmap, fd2)) {
1207 DEBUG(0,("ERROR: fd already open in dup!\n"));
1212 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1219 ZERO_STRUCTP(file2);
1224 file->f->ref_count++;
1226 bitmap_set(smbw_file_bmap, fd2);
1228 DLIST_ADD(smbw_files, file2);
1239 /*****************************************************
1240 a wrapper for dup2()
1241 *******************************************************/
1242 int smbw_dup2(int fd, int fd2)
1244 struct smbw_file *file, *file2;
1248 file = smbw_file(fd);
1254 if (bitmap_query(smbw_file_bmap, fd2)) {
1255 DEBUG(0,("ERROR: fd already open in dup2!\n"));
1260 if (dup2(file->fd, fd2) != fd2) {
1264 file2 = (struct smbw_file *)malloc(sizeof(*file2));
1271 ZERO_STRUCTP(file2);
1276 file->f->ref_count++;
1278 bitmap_set(smbw_file_bmap, fd2);
1280 DLIST_ADD(smbw_files, file2);
1291 /*****************************************************
1292 close a connection to a server
1293 *******************************************************/
1294 static void smbw_srv_close(struct smbw_server *srv)
1298 cli_shutdown(&srv->cli);
1300 free(srv->server_name);
1301 free(srv->share_name);
1303 DLIST_REMOVE(smbw_srvs, srv);
1312 /*****************************************************
1313 when we fork we have to close all connections and files
1315 *******************************************************/
1322 struct smbw_file *file, *next_file;
1323 struct smbw_server *srv, *next_srv;
1325 if (pipe(p)) return real_fork();
1327 child = real_fork();
1330 /* block the parent for a moment until the sockets are
1340 /* close all files */
1341 for (file=smbw_files;file;file=next_file) {
1342 next_file = file->next;
1346 /* close all server connections */
1347 for (srv=smbw_srvs;srv;srv=next_srv) {
1348 next_srv = srv->next;
1349 smbw_srv_close(srv);
1352 /* unblock the parent */
1356 /* and continue in the child */
1360 #ifndef NO_ACL_WRAPPER
1361 /*****************************************************
1363 *******************************************************/
1364 int smbw_acl(const char *pathp, int cmd, int nentries, aclent_t *aclbufp)
1366 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1372 #ifndef NO_FACL_WRAPPER
1373 /*****************************************************
1375 *******************************************************/
1376 int smbw_facl(int fd, int cmd, int nentries, aclent_t *aclbufp)
1378 if (cmd == GETACL || cmd == GETACLCNT) return 0;
1386 /* this can't be in wrapped.c because of include conflicts */
1387 void stat64_convert(struct stat *st, struct stat64 *st64)
1389 st64->st_size = st->st_size;
1390 st64->st_mode = st->st_mode;
1391 st64->st_ino = st->st_ino;
1392 st64->st_dev = st->st_dev;
1393 st64->st_rdev = st->st_rdev;
1394 st64->st_nlink = st->st_nlink;
1395 st64->st_uid = st->st_uid;
1396 st64->st_gid = st->st_gid;
1397 st64->st_atime = st->st_atime;
1398 st64->st_mtime = st->st_mtime;
1399 st64->st_ctime = st->st_ctime;
1400 st64->st_blksize = st->st_blksize;
1401 st64->st_blocks = st->st_blocks;
1405 #ifdef HAVE_READDIR64
1406 void dirent64_convert(struct dirent *d, struct dirent64 *d64)
1408 d64->d_ino = d->d_ino;
1409 d64->d_off = d->d_off;
1410 d64->d_reclen = d->d_reclen;
1411 pstrcpy(d64->d_name, d->d_name);
1417 /* Definition of `struct stat' used in the linux kernel.. */
1418 struct kernel_stat {
1419 unsigned short int st_dev;
1420 unsigned short int __pad1;
1421 unsigned long int st_ino;
1422 unsigned short int st_mode;
1423 unsigned short int st_nlink;
1424 unsigned short int st_uid;
1425 unsigned short int st_gid;
1426 unsigned short int st_rdev;
1427 unsigned short int __pad2;
1428 unsigned long int st_size;
1429 unsigned long int st_blksize;
1430 unsigned long int st_blocks;
1431 unsigned long int st_atime;
1432 unsigned long int __unused1;
1433 unsigned long int st_mtime;
1434 unsigned long int __unused2;
1435 unsigned long int st_ctime;
1436 unsigned long int __unused3;
1437 unsigned long int __unused4;
1438 unsigned long int __unused5;
1442 * Prototype for gcc in 'fussy' mode.
1444 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf);
1445 void xstat_convert(int vers, struct stat *st, struct kernel_stat *kbuf)
1447 #ifdef _STAT_VER_LINUX_OLD
1448 if (vers == _STAT_VER_LINUX_OLD) {
1449 memcpy(st, kbuf, sizeof(*st));
1456 st->st_dev = kbuf->st_dev;
1457 st->st_ino = kbuf->st_ino;
1458 st->st_mode = kbuf->st_mode;
1459 st->st_nlink = kbuf->st_nlink;
1460 st->st_uid = kbuf->st_uid;
1461 st->st_gid = kbuf->st_gid;
1462 st->st_rdev = kbuf->st_rdev;
1463 st->st_size = kbuf->st_size;
1464 st->st_blksize = kbuf->st_blksize;
1465 st->st_blocks = kbuf->st_blocks;
1466 st->st_atime = kbuf->st_atime;
1467 st->st_mtime = kbuf->st_mtime;
1468 st->st_ctime = kbuf->st_ctime;