LCOV - code coverage report
Current view: top level - net/9p - protocol.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 316 0.0 %
Date: 2022-04-01 14:58:12 Functions: 0 12 0.0 %
Branches: 0 142 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * net/9p/protocol.c
       4                 :            :  *
       5                 :            :  * 9P Protocol Support Code
       6                 :            :  *
       7                 :            :  *  Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
       8                 :            :  *
       9                 :            :  *  Base on code from Anthony Liguori <aliguori@us.ibm.com>
      10                 :            :  *  Copyright (C) 2008 by IBM, Corp.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <linux/module.h>
      14                 :            : #include <linux/errno.h>
      15                 :            : #include <linux/kernel.h>
      16                 :            : #include <linux/uaccess.h>
      17                 :            : #include <linux/slab.h>
      18                 :            : #include <linux/sched.h>
      19                 :            : #include <linux/stddef.h>
      20                 :            : #include <linux/types.h>
      21                 :            : #include <linux/uio.h>
      22                 :            : #include <net/9p/9p.h>
      23                 :            : #include <net/9p/client.h>
      24                 :            : #include "protocol.h"
      25                 :            : 
      26                 :            : #include <trace/events/9p.h>
      27                 :            : 
      28                 :            : static int
      29                 :            : p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
      30                 :            : 
      31                 :          0 : void p9stat_free(struct p9_wstat *stbuf)
      32                 :            : {
      33                 :          0 :         kfree(stbuf->name);
      34                 :          0 :         stbuf->name = NULL;
      35                 :          0 :         kfree(stbuf->uid);
      36                 :          0 :         stbuf->uid = NULL;
      37                 :          0 :         kfree(stbuf->gid);
      38                 :          0 :         stbuf->gid = NULL;
      39                 :          0 :         kfree(stbuf->muid);
      40                 :          0 :         stbuf->muid = NULL;
      41                 :          0 :         kfree(stbuf->extension);
      42                 :          0 :         stbuf->extension = NULL;
      43                 :          0 : }
      44                 :            : EXPORT_SYMBOL(p9stat_free);
      45                 :            : 
      46                 :          0 : size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size)
      47                 :            : {
      48                 :          0 :         size_t len = min(pdu->size - pdu->offset, size);
      49                 :          0 :         memcpy(data, &pdu->sdata[pdu->offset], len);
      50                 :          0 :         pdu->offset += len;
      51                 :          0 :         return size - len;
      52                 :            : }
      53                 :            : 
      54                 :          0 : static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size)
      55                 :            : {
      56                 :          0 :         size_t len = min(pdu->capacity - pdu->size, size);
      57                 :          0 :         memcpy(&pdu->sdata[pdu->size], data, len);
      58                 :          0 :         pdu->size += len;
      59                 :          0 :         return size - len;
      60                 :            : }
      61                 :            : 
      62                 :            : static size_t
      63                 :          0 : pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size)
      64                 :            : {
      65                 :          0 :         size_t len = min(pdu->capacity - pdu->size, size);
      66                 :          0 :         struct iov_iter i = *from;
      67   [ #  #  #  # ]:          0 :         if (!copy_from_iter_full(&pdu->sdata[pdu->size], len, &i))
      68                 :            :                 len = 0;
      69                 :            : 
      70                 :          0 :         pdu->size += len;
      71                 :          0 :         return size - len;
      72                 :            : }
      73                 :            : 
      74                 :            : /*
      75                 :            :         b - int8_t
      76                 :            :         w - int16_t
      77                 :            :         d - int32_t
      78                 :            :         q - int64_t
      79                 :            :         s - string
      80                 :            :         u - numeric uid
      81                 :            :         g - numeric gid
      82                 :            :         S - stat
      83                 :            :         Q - qid
      84                 :            :         D - data blob (int32_t size followed by void *, results are not freed)
      85                 :            :         T - array of strings (int16_t count, followed by strings)
      86                 :            :         R - array of qids (int16_t count, followed by qids)
      87                 :            :         A - stat for 9p2000.L (p9_stat_dotl)
      88                 :            :         ? - if optional = 1, continue parsing
      89                 :            : */
      90                 :            : 
      91                 :            : static int
      92                 :          0 : p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
      93                 :            :         va_list ap)
      94                 :            : {
      95                 :          0 :         const char *ptr;
      96                 :          0 :         int errcode = 0;
      97                 :            : 
      98         [ #  # ]:          0 :         for (ptr = fmt; *ptr; ptr++) {
      99   [ #  #  #  #  :          0 :                 switch (*ptr) {
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     100                 :          0 :                 case 'b':{
     101                 :          0 :                                 int8_t *val = va_arg(ap, int8_t *);
     102         [ #  # ]:          0 :                                 if (pdu_read(pdu, val, sizeof(*val))) {
     103                 :            :                                         errcode = -EFAULT;
     104                 :            :                                         break;
     105                 :            :                                 }
     106                 :            :                         }
     107                 :            :                         break;
     108                 :          0 :                 case 'w':{
     109                 :          0 :                                 int16_t *val = va_arg(ap, int16_t *);
     110                 :          0 :                                 __le16 le_val;
     111         [ #  # ]:          0 :                                 if (pdu_read(pdu, &le_val, sizeof(le_val))) {
     112                 :          0 :                                         errcode = -EFAULT;
     113                 :          0 :                                         break;
     114                 :            :                                 }
     115                 :          0 :                                 *val = le16_to_cpu(le_val);
     116                 :            :                         }
     117                 :          0 :                         break;
     118                 :          0 :                 case 'd':{
     119                 :          0 :                                 int32_t *val = va_arg(ap, int32_t *);
     120                 :          0 :                                 __le32 le_val;
     121         [ #  # ]:          0 :                                 if (pdu_read(pdu, &le_val, sizeof(le_val))) {
     122                 :          0 :                                         errcode = -EFAULT;
     123                 :          0 :                                         break;
     124                 :            :                                 }
     125                 :          0 :                                 *val = le32_to_cpu(le_val);
     126                 :            :                         }
     127                 :          0 :                         break;
     128                 :          0 :                 case 'q':{
     129                 :          0 :                                 int64_t *val = va_arg(ap, int64_t *);
     130                 :          0 :                                 __le64 le_val;
     131         [ #  # ]:          0 :                                 if (pdu_read(pdu, &le_val, sizeof(le_val))) {
     132                 :          0 :                                         errcode = -EFAULT;
     133                 :          0 :                                         break;
     134                 :            :                                 }
     135                 :          0 :                                 *val = le64_to_cpu(le_val);
     136                 :            :                         }
     137                 :          0 :                         break;
     138                 :          0 :                 case 's':{
     139                 :          0 :                                 char **sptr = va_arg(ap, char **);
     140                 :          0 :                                 uint16_t len;
     141                 :            : 
     142                 :          0 :                                 errcode = p9pdu_readf(pdu, proto_version,
     143                 :            :                                                                 "w", &len);
     144         [ #  # ]:          0 :                                 if (errcode)
     145                 :            :                                         break;
     146                 :            : 
     147         [ #  # ]:          0 :                                 *sptr = kmalloc(len + 1, GFP_NOFS);
     148         [ #  # ]:          0 :                                 if (*sptr == NULL) {
     149                 :            :                                         errcode = -ENOMEM;
     150                 :            :                                         break;
     151                 :            :                                 }
     152         [ #  # ]:          0 :                                 if (pdu_read(pdu, *sptr, len)) {
     153                 :          0 :                                         errcode = -EFAULT;
     154                 :          0 :                                         kfree(*sptr);
     155                 :          0 :                                         *sptr = NULL;
     156                 :            :                                 } else
     157                 :          0 :                                         (*sptr)[len] = 0;
     158                 :            :                         }
     159                 :          0 :                         break;
     160                 :          0 :                 case 'u': {
     161                 :          0 :                                 kuid_t *uid = va_arg(ap, kuid_t *);
     162                 :          0 :                                 __le32 le_val;
     163         [ #  # ]:          0 :                                 if (pdu_read(pdu, &le_val, sizeof(le_val))) {
     164                 :          0 :                                         errcode = -EFAULT;
     165                 :          0 :                                         break;
     166                 :            :                                 }
     167                 :          0 :                                 *uid = make_kuid(&init_user_ns,
     168                 :            :                                                  le32_to_cpu(le_val));
     169                 :          0 :                         } break;
     170                 :          0 :                 case 'g': {
     171                 :          0 :                                 kgid_t *gid = va_arg(ap, kgid_t *);
     172                 :          0 :                                 __le32 le_val;
     173         [ #  # ]:          0 :                                 if (pdu_read(pdu, &le_val, sizeof(le_val))) {
     174                 :          0 :                                         errcode = -EFAULT;
     175                 :          0 :                                         break;
     176                 :            :                                 }
     177                 :          0 :                                 *gid = make_kgid(&init_user_ns,
     178                 :            :                                                  le32_to_cpu(le_val));
     179                 :          0 :                         } break;
     180                 :          0 :                 case 'Q':{
     181                 :          0 :                                 struct p9_qid *qid =
     182                 :            :                                     va_arg(ap, struct p9_qid *);
     183                 :            : 
     184                 :          0 :                                 errcode = p9pdu_readf(pdu, proto_version, "bdq",
     185                 :            :                                                       &qid->type, &qid->version,
     186                 :            :                                                       &qid->path);
     187                 :            :                         }
     188                 :          0 :                         break;
     189                 :          0 :                 case 'S':{
     190                 :          0 :                                 struct p9_wstat *stbuf =
     191                 :            :                                     va_arg(ap, struct p9_wstat *);
     192                 :            : 
     193                 :          0 :                                 memset(stbuf, 0, sizeof(struct p9_wstat));
     194                 :          0 :                                 stbuf->n_uid = stbuf->n_muid = INVALID_UID;
     195                 :          0 :                                 stbuf->n_gid = INVALID_GID;
     196                 :            : 
     197                 :          0 :                                 errcode =
     198                 :          0 :                                     p9pdu_readf(pdu, proto_version,
     199                 :            :                                                 "wwdQdddqssss?sugu",
     200                 :            :                                                 &stbuf->size, &stbuf->type,
     201                 :            :                                                 &stbuf->dev, &stbuf->qid,
     202                 :            :                                                 &stbuf->mode, &stbuf->atime,
     203                 :            :                                                 &stbuf->mtime, &stbuf->length,
     204                 :            :                                                 &stbuf->name, &stbuf->uid,
     205                 :            :                                                 &stbuf->gid, &stbuf->muid,
     206                 :            :                                                 &stbuf->extension,
     207                 :            :                                                 &stbuf->n_uid, &stbuf->n_gid,
     208                 :            :                                                 &stbuf->n_muid);
     209         [ #  # ]:          0 :                                 if (errcode)
     210                 :          0 :                                         p9stat_free(stbuf);
     211                 :            :                         }
     212                 :            :                         break;
     213                 :          0 :                 case 'D':{
     214                 :          0 :                                 uint32_t *count = va_arg(ap, uint32_t *);
     215                 :          0 :                                 void **data = va_arg(ap, void **);
     216                 :            : 
     217                 :          0 :                                 errcode =
     218                 :          0 :                                     p9pdu_readf(pdu, proto_version, "d", count);
     219         [ #  # ]:          0 :                                 if (!errcode) {
     220                 :          0 :                                         *count =
     221                 :          0 :                                             min_t(uint32_t, *count,
     222                 :            :                                                   pdu->size - pdu->offset);
     223                 :          0 :                                         *data = &pdu->sdata[pdu->offset];
     224                 :            :                                 }
     225                 :            :                         }
     226                 :            :                         break;
     227                 :          0 :                 case 'T':{
     228                 :          0 :                                 uint16_t *nwname = va_arg(ap, uint16_t *);
     229                 :          0 :                                 char ***wnames = va_arg(ap, char ***);
     230                 :            : 
     231                 :          0 :                                 errcode = p9pdu_readf(pdu, proto_version,
     232                 :            :                                                                 "w", nwname);
     233         [ #  # ]:          0 :                                 if (!errcode) {
     234                 :          0 :                                         *wnames =
     235                 :          0 :                                             kmalloc_array(*nwname,
     236                 :            :                                                           sizeof(char *),
     237                 :            :                                                           GFP_NOFS);
     238         [ #  # ]:          0 :                                         if (!*wnames)
     239                 :            :                                                 errcode = -ENOMEM;
     240                 :            :                                 }
     241                 :            : 
     242         [ #  # ]:          0 :                                 if (!errcode) {
     243                 :            :                                         int i;
     244                 :            : 
     245         [ #  # ]:          0 :                                         for (i = 0; i < *nwname; i++) {
     246                 :          0 :                                                 errcode =
     247                 :          0 :                                                     p9pdu_readf(pdu,
     248                 :            :                                                                 proto_version,
     249                 :            :                                                                 "s",
     250                 :          0 :                                                                 &(*wnames)[i]);
     251         [ #  # ]:          0 :                                                 if (errcode)
     252                 :            :                                                         break;
     253                 :            :                                         }
     254                 :            :                                 }
     255                 :            : 
     256         [ #  # ]:          0 :                                 if (errcode) {
     257         [ #  # ]:          0 :                                         if (*wnames) {
     258                 :            :                                                 int i;
     259                 :            : 
     260         [ #  # ]:          0 :                                                 for (i = 0; i < *nwname; i++)
     261                 :          0 :                                                         kfree((*wnames)[i]);
     262                 :            :                                         }
     263                 :          0 :                                         kfree(*wnames);
     264                 :          0 :                                         *wnames = NULL;
     265                 :            :                                 }
     266                 :            :                         }
     267                 :            :                         break;
     268                 :          0 :                 case 'R':{
     269                 :          0 :                                 uint16_t *nwqid = va_arg(ap, uint16_t *);
     270                 :          0 :                                 struct p9_qid **wqids =
     271                 :            :                                     va_arg(ap, struct p9_qid **);
     272                 :            : 
     273                 :          0 :                                 *wqids = NULL;
     274                 :            : 
     275                 :          0 :                                 errcode =
     276                 :          0 :                                     p9pdu_readf(pdu, proto_version, "w", nwqid);
     277         [ #  # ]:          0 :                                 if (!errcode) {
     278                 :          0 :                                         *wqids =
     279                 :          0 :                                             kmalloc_array(*nwqid,
     280                 :            :                                                           sizeof(struct p9_qid),
     281                 :            :                                                           GFP_NOFS);
     282         [ #  # ]:          0 :                                         if (*wqids == NULL)
     283                 :            :                                                 errcode = -ENOMEM;
     284                 :            :                                 }
     285                 :            : 
     286         [ #  # ]:          0 :                                 if (!errcode) {
     287                 :            :                                         int i;
     288                 :            : 
     289         [ #  # ]:          0 :                                         for (i = 0; i < *nwqid; i++) {
     290                 :          0 :                                                 errcode =
     291                 :          0 :                                                     p9pdu_readf(pdu,
     292                 :            :                                                                 proto_version,
     293                 :            :                                                                 "Q",
     294                 :          0 :                                                                 &(*wqids)[i]);
     295         [ #  # ]:          0 :                                                 if (errcode)
     296                 :            :                                                         break;
     297                 :            :                                         }
     298                 :            :                                 }
     299                 :            : 
     300         [ #  # ]:          0 :                                 if (errcode) {
     301                 :          0 :                                         kfree(*wqids);
     302                 :          0 :                                         *wqids = NULL;
     303                 :            :                                 }
     304                 :            :                         }
     305                 :            :                         break;
     306                 :          0 :                 case 'A': {
     307                 :          0 :                                 struct p9_stat_dotl *stbuf =
     308                 :            :                                     va_arg(ap, struct p9_stat_dotl *);
     309                 :            : 
     310                 :          0 :                                 memset(stbuf, 0, sizeof(struct p9_stat_dotl));
     311                 :          0 :                                 errcode =
     312                 :          0 :                                     p9pdu_readf(pdu, proto_version,
     313                 :            :                                         "qQdugqqqqqqqqqqqqqqq",
     314                 :            :                                         &stbuf->st_result_mask,
     315                 :            :                                         &stbuf->qid,
     316                 :            :                                         &stbuf->st_mode,
     317                 :            :                                         &stbuf->st_uid, &stbuf->st_gid,
     318                 :            :                                         &stbuf->st_nlink,
     319                 :            :                                         &stbuf->st_rdev, &stbuf->st_size,
     320                 :            :                                         &stbuf->st_blksize, &stbuf->st_blocks,
     321                 :            :                                         &stbuf->st_atime_sec,
     322                 :            :                                         &stbuf->st_atime_nsec,
     323                 :            :                                         &stbuf->st_mtime_sec,
     324                 :            :                                         &stbuf->st_mtime_nsec,
     325                 :            :                                         &stbuf->st_ctime_sec,
     326                 :            :                                         &stbuf->st_ctime_nsec,
     327                 :            :                                         &stbuf->st_btime_sec,
     328                 :            :                                         &stbuf->st_btime_nsec,
     329                 :            :                                         &stbuf->st_gen,
     330                 :            :                                         &stbuf->st_data_version);
     331                 :            :                         }
     332                 :          0 :                         break;
     333                 :          0 :                 case '?':
     334         [ #  # ]:          0 :                         if ((proto_version != p9_proto_2000u) &&
     335                 :            :                                 (proto_version != p9_proto_2000L))
     336                 :            :                                 return 0;
     337                 :            :                         break;
     338                 :          0 :                 default:
     339                 :          0 :                         BUG();
     340                 :          0 :                         break;
     341                 :            :                 }
     342                 :            : 
     343         [ #  # ]:          0 :                 if (errcode)
     344                 :            :                         break;
     345                 :            :         }
     346                 :            : 
     347                 :            :         return errcode;
     348                 :            : }
     349                 :            : 
     350                 :            : int
     351                 :          0 : p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
     352                 :            :         va_list ap)
     353                 :            : {
     354                 :          0 :         const char *ptr;
     355                 :          0 :         int errcode = 0;
     356                 :            : 
     357         [ #  # ]:          0 :         for (ptr = fmt; *ptr; ptr++) {
     358   [ #  #  #  #  :          0 :                 switch (*ptr) {
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     359                 :          0 :                 case 'b':{
     360                 :          0 :                                 int8_t val = va_arg(ap, int);
     361         [ #  # ]:          0 :                                 if (pdu_write(pdu, &val, sizeof(val)))
     362                 :          0 :                                         errcode = -EFAULT;
     363                 :            :                         }
     364                 :          0 :                         break;
     365                 :          0 :                 case 'w':{
     366                 :          0 :                                 __le16 val = cpu_to_le16(va_arg(ap, int));
     367         [ #  # ]:          0 :                                 if (pdu_write(pdu, &val, sizeof(val)))
     368                 :          0 :                                         errcode = -EFAULT;
     369                 :            :                         }
     370                 :          0 :                         break;
     371                 :          0 :                 case 'd':{
     372                 :          0 :                                 __le32 val = cpu_to_le32(va_arg(ap, int32_t));
     373         [ #  # ]:          0 :                                 if (pdu_write(pdu, &val, sizeof(val)))
     374                 :          0 :                                         errcode = -EFAULT;
     375                 :            :                         }
     376                 :          0 :                         break;
     377                 :          0 :                 case 'q':{
     378                 :          0 :                                 __le64 val = cpu_to_le64(va_arg(ap, int64_t));
     379         [ #  # ]:          0 :                                 if (pdu_write(pdu, &val, sizeof(val)))
     380                 :          0 :                                         errcode = -EFAULT;
     381                 :            :                         }
     382                 :          0 :                         break;
     383                 :          0 :                 case 's':{
     384                 :          0 :                                 const char *sptr = va_arg(ap, const char *);
     385                 :          0 :                                 uint16_t len = 0;
     386         [ #  # ]:          0 :                                 if (sptr)
     387                 :          0 :                                         len = min_t(size_t, strlen(sptr),
     388                 :            :                                                                 USHRT_MAX);
     389                 :            : 
     390                 :          0 :                                 errcode = p9pdu_writef(pdu, proto_version,
     391                 :            :                                                                 "w", len);
     392   [ #  #  #  # ]:          0 :                                 if (!errcode && pdu_write(pdu, sptr, len))
     393                 :            :                                         errcode = -EFAULT;
     394                 :            :                         }
     395                 :            :                         break;
     396                 :          0 :                 case 'u': {
     397                 :          0 :                                 kuid_t uid = va_arg(ap, kuid_t);
     398         [ #  # ]:          0 :                                 __le32 val = cpu_to_le32(
     399                 :            :                                                 from_kuid(&init_user_ns, uid));
     400         [ #  # ]:          0 :                                 if (pdu_write(pdu, &val, sizeof(val)))
     401                 :          0 :                                         errcode = -EFAULT;
     402                 :          0 :                         } break;
     403                 :          0 :                 case 'g': {
     404                 :          0 :                                 kgid_t gid = va_arg(ap, kgid_t);
     405         [ #  # ]:          0 :                                 __le32 val = cpu_to_le32(
     406                 :            :                                                 from_kgid(&init_user_ns, gid));
     407         [ #  # ]:          0 :                                 if (pdu_write(pdu, &val, sizeof(val)))
     408                 :          0 :                                         errcode = -EFAULT;
     409                 :          0 :                         } break;
     410                 :          0 :                 case 'Q':{
     411                 :          0 :                                 const struct p9_qid *qid =
     412                 :            :                                     va_arg(ap, const struct p9_qid *);
     413                 :          0 :                                 errcode =
     414                 :          0 :                                     p9pdu_writef(pdu, proto_version, "bdq",
     415                 :          0 :                                                  qid->type, qid->version,
     416                 :            :                                                  qid->path);
     417                 :          0 :                         } break;
     418                 :          0 :                 case 'S':{
     419                 :          0 :                                 const struct p9_wstat *stbuf =
     420                 :            :                                     va_arg(ap, const struct p9_wstat *);
     421                 :          0 :                                 errcode =
     422                 :          0 :                                     p9pdu_writef(pdu, proto_version,
     423                 :            :                                                  "wwdQdddqssss?sugu",
     424                 :          0 :                                                  stbuf->size, stbuf->type,
     425                 :            :                                                  stbuf->dev, &stbuf->qid,
     426                 :            :                                                  stbuf->mode, stbuf->atime,
     427                 :            :                                                  stbuf->mtime, stbuf->length,
     428                 :            :                                                  stbuf->name, stbuf->uid,
     429                 :            :                                                  stbuf->gid, stbuf->muid,
     430                 :            :                                                  stbuf->extension, stbuf->n_uid,
     431                 :            :                                                  stbuf->n_gid, stbuf->n_muid);
     432                 :          0 :                         } break;
     433                 :          0 :                 case 'V':{
     434                 :          0 :                                 uint32_t count = va_arg(ap, uint32_t);
     435                 :          0 :                                 struct iov_iter *from =
     436                 :            :                                                 va_arg(ap, struct iov_iter *);
     437                 :          0 :                                 errcode = p9pdu_writef(pdu, proto_version, "d",
     438                 :            :                                                                         count);
     439   [ #  #  #  # ]:          0 :                                 if (!errcode && pdu_write_u(pdu, from, count))
     440                 :            :                                         errcode = -EFAULT;
     441                 :            :                         }
     442                 :            :                         break;
     443                 :          0 :                 case 'T':{
     444                 :          0 :                                 uint16_t nwname = va_arg(ap, int);
     445                 :          0 :                                 const char **wnames = va_arg(ap, const char **);
     446                 :            : 
     447                 :          0 :                                 errcode = p9pdu_writef(pdu, proto_version, "w",
     448                 :            :                                                                         nwname);
     449         [ #  # ]:          0 :                                 if (!errcode) {
     450                 :            :                                         int i;
     451                 :            : 
     452         [ #  # ]:          0 :                                         for (i = 0; i < nwname; i++) {
     453                 :          0 :                                                 errcode =
     454                 :          0 :                                                     p9pdu_writef(pdu,
     455                 :            :                                                                 proto_version,
     456                 :            :                                                                  "s",
     457                 :          0 :                                                                  wnames[i]);
     458         [ #  # ]:          0 :                                                 if (errcode)
     459                 :            :                                                         break;
     460                 :            :                                         }
     461                 :            :                                 }
     462                 :            :                         }
     463                 :            :                         break;
     464                 :          0 :                 case 'R':{
     465                 :          0 :                                 uint16_t nwqid = va_arg(ap, int);
     466                 :          0 :                                 struct p9_qid *wqids =
     467                 :            :                                     va_arg(ap, struct p9_qid *);
     468                 :            : 
     469                 :          0 :                                 errcode = p9pdu_writef(pdu, proto_version, "w",
     470                 :            :                                                                         nwqid);
     471         [ #  # ]:          0 :                                 if (!errcode) {
     472                 :            :                                         int i;
     473                 :            : 
     474         [ #  # ]:          0 :                                         for (i = 0; i < nwqid; i++) {
     475                 :          0 :                                                 errcode =
     476                 :          0 :                                                     p9pdu_writef(pdu,
     477                 :            :                                                                 proto_version,
     478                 :            :                                                                  "Q",
     479                 :          0 :                                                                  &wqids[i]);
     480         [ #  # ]:          0 :                                                 if (errcode)
     481                 :            :                                                         break;
     482                 :            :                                         }
     483                 :            :                                 }
     484                 :            :                         }
     485                 :            :                         break;
     486                 :          0 :                 case 'I':{
     487                 :          0 :                                 struct p9_iattr_dotl *p9attr = va_arg(ap,
     488                 :            :                                                         struct p9_iattr_dotl *);
     489                 :            : 
     490                 :          0 :                                 errcode = p9pdu_writef(pdu, proto_version,
     491                 :            :                                                         "ddugqqqqq",
     492                 :            :                                                         p9attr->valid,
     493                 :            :                                                         p9attr->mode,
     494                 :            :                                                         p9attr->uid,
     495                 :            :                                                         p9attr->gid,
     496                 :            :                                                         p9attr->size,
     497                 :            :                                                         p9attr->atime_sec,
     498                 :            :                                                         p9attr->atime_nsec,
     499                 :            :                                                         p9attr->mtime_sec,
     500                 :            :                                                         p9attr->mtime_nsec);
     501                 :            :                         }
     502                 :          0 :                         break;
     503                 :          0 :                 case '?':
     504         [ #  # ]:          0 :                         if ((proto_version != p9_proto_2000u) &&
     505                 :            :                                 (proto_version != p9_proto_2000L))
     506                 :            :                                 return 0;
     507                 :            :                         break;
     508                 :          0 :                 default:
     509                 :          0 :                         BUG();
     510                 :          0 :                         break;
     511                 :            :                 }
     512                 :            : 
     513         [ #  # ]:          0 :                 if (errcode)
     514                 :            :                         break;
     515                 :            :         }
     516                 :            : 
     517                 :            :         return errcode;
     518                 :            : }
     519                 :            : 
     520                 :          0 : int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
     521                 :            : {
     522                 :          0 :         va_list ap;
     523                 :          0 :         int ret;
     524                 :            : 
     525                 :          0 :         va_start(ap, fmt);
     526                 :          0 :         ret = p9pdu_vreadf(pdu, proto_version, fmt, ap);
     527                 :          0 :         va_end(ap);
     528                 :            : 
     529                 :          0 :         return ret;
     530                 :            : }
     531                 :            : 
     532                 :            : static int
     533                 :          0 : p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
     534                 :            : {
     535                 :          0 :         va_list ap;
     536                 :          0 :         int ret;
     537                 :            : 
     538                 :          0 :         va_start(ap, fmt);
     539                 :          0 :         ret = p9pdu_vwritef(pdu, proto_version, fmt, ap);
     540                 :          0 :         va_end(ap);
     541                 :            : 
     542                 :          0 :         return ret;
     543                 :            : }
     544                 :            : 
     545                 :          0 : int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st)
     546                 :            : {
     547                 :          0 :         struct p9_fcall fake_pdu;
     548                 :          0 :         int ret;
     549                 :            : 
     550                 :          0 :         fake_pdu.size = len;
     551                 :          0 :         fake_pdu.capacity = len;
     552                 :          0 :         fake_pdu.sdata = buf;
     553                 :          0 :         fake_pdu.offset = 0;
     554                 :            : 
     555                 :          0 :         ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st);
     556         [ #  # ]:          0 :         if (ret) {
     557                 :          0 :                 p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
     558                 :          0 :                 trace_9p_protocol_dump(clnt, &fake_pdu);
     559                 :          0 :                 return ret;
     560                 :            :         }
     561                 :            : 
     562                 :          0 :         return fake_pdu.offset;
     563                 :            : }
     564                 :            : EXPORT_SYMBOL(p9stat_read);
     565                 :            : 
     566                 :          0 : int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
     567                 :            : {
     568                 :          0 :         pdu->id = type;
     569                 :          0 :         return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
     570                 :            : }
     571                 :            : 
     572                 :          0 : int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu)
     573                 :            : {
     574                 :          0 :         int size = pdu->size;
     575                 :          0 :         int err;
     576                 :            : 
     577                 :          0 :         pdu->size = 0;
     578                 :          0 :         err = p9pdu_writef(pdu, 0, "d", size);
     579                 :          0 :         pdu->size = size;
     580                 :            : 
     581                 :          0 :         trace_9p_protocol_dump(clnt, pdu);
     582                 :          0 :         p9_debug(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n",
     583                 :            :                  pdu->size, pdu->id, pdu->tag);
     584                 :            : 
     585                 :          0 :         return err;
     586                 :            : }
     587                 :            : 
     588                 :          0 : void p9pdu_reset(struct p9_fcall *pdu)
     589                 :            : {
     590                 :          0 :         pdu->offset = 0;
     591                 :          0 :         pdu->size = 0;
     592                 :          0 : }
     593                 :            : 
     594                 :          0 : int p9dirent_read(struct p9_client *clnt, char *buf, int len,
     595                 :            :                   struct p9_dirent *dirent)
     596                 :            : {
     597                 :          0 :         struct p9_fcall fake_pdu;
     598                 :          0 :         int ret;
     599                 :          0 :         char *nameptr;
     600                 :            : 
     601                 :          0 :         fake_pdu.size = len;
     602                 :          0 :         fake_pdu.capacity = len;
     603                 :          0 :         fake_pdu.sdata = buf;
     604                 :          0 :         fake_pdu.offset = 0;
     605                 :            : 
     606                 :          0 :         ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid,
     607                 :            :                           &dirent->d_off, &dirent->d_type, &nameptr);
     608         [ #  # ]:          0 :         if (ret) {
     609                 :          0 :                 p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret);
     610                 :          0 :                 trace_9p_protocol_dump(clnt, &fake_pdu);
     611                 :          0 :                 return ret;
     612                 :            :         }
     613                 :            : 
     614                 :          0 :         ret = strscpy(dirent->d_name, nameptr, sizeof(dirent->d_name));
     615         [ #  # ]:          0 :         if (ret < 0) {
     616                 :          0 :                 p9_debug(P9_DEBUG_ERROR,
     617                 :            :                          "On the wire dirent name too long: %s\n",
     618                 :            :                          nameptr);
     619                 :          0 :                 kfree(nameptr);
     620                 :          0 :                 return ret;
     621                 :            :         }
     622                 :          0 :         kfree(nameptr);
     623                 :            : 
     624                 :          0 :         return fake_pdu.offset;
     625                 :            : }
     626                 :            : EXPORT_SYMBOL(p9dirent_read);

Generated by: LCOV version 1.14