Arduino - Function -> return Cstr instead of string
You cannot work with c-strings like with Strings. You need to use the standard c-string functions (like sprintf(), strcpy() and siblings) or directly access the char array.
This gives the following problems with your code:

See this line:
  char* received = &quot;&quot;;

Here you create a pointer to a constant empty string. But this will NOT create a buffer, where you can put data. If you want to define a buffer to put the data in, you need to define an array:
  char received[30] = &quot;&quot;;

where 30 is the size of the array and thus the buffer has space for 29 characters (30 minus the one character, that is needed for the terminating null character). Now you could use a counter variable to save the current position in the buffer and set the array elements to the received character:
  int position = 0;
  ...
  received[position] = ch;
  position++;

Then, when you reached the end of the buffer or you received end of line, you would end the data in the buffer with the null character:
  if (ch == '\n' || ch == '\r' || position == 29) {
      if (ch == '\r')
      {
          //get rid of the \n
          myFile.read();
      }
      received[position] = '\0';


Now you have the second problem: When defining a variable inside the function, it will become invalid, when you exit the function. You try to return a pointer to char, which will point to a non-valid memory location. Thus you cannot simply return an array, that was created inside the function (outside of dynamic allocation). Here commonly an external buffer is provided to the function by reference as a pointer. The function will then write into that buffer and does not need to return it.
  //defining the array outside of the function, for example at global scope
  #define BUFFER_SIZE  30
  char received[BUFFER_SIZE] = &quot;&quot;;
  ...
  void readLine(char *buffer, int size) {
      ...
      // Here you can use buffer as a simple char array
      buffer[position] = ch;
  }

Here I also provide the size of the array as parameter, so that the function can make sure not to exceed that (because that will give you bad and difficult to troubleshoot problems). Then, when the function has run, the read data is now in the received character array. This way you don't need to use multiple buffers and also don't need to copy data between buffers.