1 /*
2  * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 /* clang-format off */
19 
20 /** \file
21  * Implements 64-bit LIB3F fstat subprogram.  */
22 
23 /* must include ent3f.h AFTER io3f.h */
24 #include <sys/stat.h>
25 #include "io3f.h"
26 #include "ent3f.h"
27 
ENT3F(FSTAT64,fstat64)28 int ENT3F(FSTAT64, fstat64)(int *lu, long long *statb)
29 {
30 #if defined(TARGET_WIN) || defined(WIN32) || defined(WIN64)
31   /*
32    * The __int64_t members in the _stat64 are 8-byte aligned, thus the
33    * st_size member is at offset 24. On WIN32, 64-bit ints are 4-byte
34    * aligned, so st_size shows up at offset 20!. The correct solution is
35    * to use or make default -Mllalign, but that's not in the picture.
36    * So, just declare a replacement struct which explicitly pad members
37    * the members line up with the _stat64 struct.
38    */
39   struct {
40     int st_dev;       /*  0 */
41     short st_ino;     /*  4 */
42     short st_mode;    /*  6 */
43     short st_nlink;   /*  8 */
44     short st_uid;     /* 10 */
45     short st_gid;     /* 12 */
46     short pad1;       /* 14 */
47     int st_rdev;      /* 16 */
48     int pad2;         /* 20 */
49     __int64 st_size;  /* 24 */
50     __int64 st_atime; /* 32 */
51     __int64 st_mtime; /* 40 */
52     __int64 st_ctime; /* 48 */
53   } b;
54   struct _stat64 *bp;
55   char *p;
56   int i;
57   void *f;
58   bp = (struct _stat64 *)&b;
59 
60   f = __fio_find_unit(*lu);
61   if (f && !FIO_FCB_STDUNIT(f)) {
62     /** need a way to get f->fp's fildes **/
63     if (i = _stat64(FIO_FCB_NAME(f), bp))
64       i = __io_errno();
65   } else {
66     switch (*lu) {
67     case 0:
68       i = 2;
69       break;
70     case 5:
71       i = 0;
72       break;
73     case 6:
74       i = 1;
75       break;
76     default:
77       i = -1;
78       break;
79     }
80     if (i = _fstat64(i, bp))
81       i = __io_errno();
82   }
83   statb[0] = b.st_dev;
84   statb[1] = b.st_ino;
85   statb[2] = b.st_mode;
86   statb[3] = b.st_nlink;
87   statb[4] = b.st_uid;
88   statb[5] = b.st_gid;
89   statb[6] = b.st_rdev;
90   statb[7] = b.st_size;
91   statb[8] = b.st_atime;
92   statb[9] = b.st_mtime;
93   statb[10] = b.st_ctime;
94   statb[11] = 0;
95   statb[12] = 0;
96   return i;
97 #else
98   struct stat b;
99   char *p;
100   int i;
101   void *f;
102 
103   f = __fio_find_unit(*lu);
104   if (f && !FIO_FCB_STDUNIT(f)) {
105     /** need a way to get f->fp's fildes **/
106     if ((i = stat(FIO_FCB_NAME(f), &b)))
107       i = __io_errno();
108   } else {
109     switch (*lu) {
110     case 0:
111       i = 2;
112       break;
113     case 5:
114       i = 0;
115       break;
116     case 6:
117       i = 1;
118       break;
119     default:
120       i = -1;
121       break;
122     }
123     if ((i = fstat(i, &b)))
124       i = __io_errno();
125   }
126   statb[0] = b.st_dev;
127   statb[1] = b.st_ino;
128   statb[2] = b.st_mode;
129   statb[3] = b.st_nlink;
130   statb[4] = b.st_uid;
131   statb[5] = b.st_gid;
132   statb[6] = b.st_rdev;
133   statb[7] = b.st_size;
134   statb[8] = b.st_atime;
135   statb[9] = b.st_mtime;
136   statb[10] = b.st_ctime;
137   statb[11] = b.st_blksize;
138   statb[12] = b.st_blocks;
139   return i;
140 #endif
141 }
142